每天一个C语言小项目,提升你的编程能力! 非实际游戏效果图 网上有一个香蕉金刚的跑酷游戏,不过我们这个扔香蕉游戏模仿的并不是这个,而是模仿的微软在20多年前的一个小游戏,不知道谁也有印象呢? 图片都是从原来的游戏中抓图弄出来的,颜色也是从原游戏抓图中取色设置的,应该和原来的风格很像。 你的任务是用香蕉击中你的对手。 你可以通过鼠标调整投掷香蕉的角度和力度,香蕉会受重力加速度的影响。同时,请注意屏幕底部表示风力的箭头,香蕉同样会受风力影响。风力的箭头越长,表示风力越强。还有,周围的楼宇会阻挡你的香蕉。(好像有点像愤怒的小鸟) 游戏运行效果如下: 游戏中涉及到两个玩家的代表人物和香蕉们,你可能需要自己找到两张图,然后通过easyx的贴图技术弄进去。当然你也可以来找我(在文末) 其他的部分你可以直接查看下面的游戏源代码: 本项目编译环境:VisualStudio201320192022,EasyX插件 代码展示: 1。定义变量、函数和一些必要的常量includeeasyx。hincludestdio。hincludeconio。hincludetime。hincludemath。h定义常量definePI3。1415926536圆周率defineSCRWIDTH640屏幕宽度defineSCRHEIGHT480屏幕高度defineGRAVITY9。8重力加速度defineBACKATTRBLUE背景的颜色defineOBJECTCOLOR0x55AAFF对手的颜色defineEXPLOSIONCOLOR0x5500FF爆炸的颜色defineSUNATTR0x00FFFF太阳的颜色defineSUNHEIGHT40太阳的高度defineSUNHAPPYtrue太阳高兴defineSUNSHOCKfalse太阳受惊全局变量IMAGEgimgBanana〔4〕;香蕉图片IMAGEgimgGorD;大猩猩(双手放下)IMAGEgimgGorL;大猩猩(左边的手抬起)IMAGEgimgGorR;大猩猩(右边的手抬起)POINTgptGorilla〔2〕;两个游戏者的位置intgiLastBuilding;最后一栋楼的编号intgiWind;风力boolgbSunHit;是否击中太阳函数定义voidInit();初始化voidIntro();游戏介绍voidPlayGame(TCHARplayer1,TCHARplayer2);主游戏函数voidMakeCityScape(POINTaryBCoor);创建随机的游戏场景voidPlaceGorillas(POINTaryBCoor);将游戏者放到楼宇顶端voidDoSun(boolsmile);绘制太阳boolDoShot(intidPlayer,intx,inty,intwin);接收游戏者输入,实现扔香蕉攻击对方intPlotShot(intstartX,intstartY,doubleangle,intvelocity,intidPlayer);进行香蕉攻击,使香蕉划过屏幕voidDrawBanana(intx,inty,intr,boold);绘制香蕉voidDoExplosion(intx,inty);香蕉攻击后的爆炸效果intExplodeGorilla(intx,inty);游戏者死亡后爆炸voidVictoryDance(intidPlayer);绘制跳舞的大猩猩(胜利后执行) 2。初始化游戏图片元素(香蕉和猩猩本猩)voidInit(){initgraph(SCRWIDTH,SCRHEIGHT);创建绘图窗口srand((unsignedint)time(NULL));设置随机种子初始化香蕉图案IMAGEtmp;loadimage(tmp,T(resBanana。gif));SetWorkingImage(tmp);getimage(gimgBanana〔0〕,0,0,9,7);getimage(gimgBanana〔1〕,9,0,9,7);getimage(gimgBanana〔2〕,18,0,9,7);getimage(gimgBanana〔3〕,27,0,9,7);初始化大猩猩图案loadimage(tmp,T(resGorilla。gif),0,0,true);SetWorkingImage(tmp);getimage(gimgGorD,0,0,30,30);getimage(gimgGorL,30,0,30,30);getimage(gimgGorR,60,0,30,30);SetWorkingImage(NULL);} 3。游戏的简单介绍voidIntro(){settextstyle(24,0,T(宋体));在屏幕中央输出字符串RECTr{0,40,640,80};drawtext(T(扔香蕉的大猩猩),r,DTCENTERDTVCENTERDTSINGLELINE);settextstyle(16,0,T(System));r。top120;r。bottom480;drawtext(T(这个游戏模仿的微软在20多年前的一个小游戏,不知道谁也有印象呢?)T(你的任务是用香蕉击中你的对手。你可以通过鼠标调整投掷香蕉的角度和力度,)T(香蕉会受重力加速度的影响。同时,请注意屏幕底部表示风力的箭头,)T(香蕉同样会受风力影响。风力的箭头越长,表示风力越强。)T(还有,周围的楼宇会阻挡你的香蕉。),r,DTCENTERDTVCENTER);r。top400;drawtext(T(按任意键继续),r,DTCENTERDTVCENTERDTSINGLELINE);getmessage(EMCHAR);} 4。主游戏函数参数:player1,player2:游戏者名称voidPlayGame(TCHARplayer1,TCHARplayer2){POINTaryBCoor〔31〕;楼宇群的坐标intaryScore〔2〕{0,0};两个游戏者的得分TCHARsScore〔20〕;保存得分的字符串intplayer0;攻击者setbkcolor(BACKATTR);while(true){cleardevice();MakeCityScape(aryBCoor);PlaceGorillas(aryBCoor);DoSun(SUNHAPPY);boolbHitfalse;while(bHitfalse){settextcolor(WHITE);RECTr{0,0,SCRWIDTH,20};drawtext(player1,r,DTLEFTDTSINGLELINE);drawtext(player2,r,DTRIGHTDTSINGLELINE);r。topSCRHEIGHT40;r。bottomSCRHEIGHT20;ifMSCVER1200stprintfs(sScore,T(dScored),aryScore〔0〕,aryScore〔1〕);elsestprintf(sScore,T(dScored),aryScore〔0〕,aryScore〔1〕);endifdrawtext(sScore,r,DTCENTERDTSINGLELINE);intwin;进行攻击。击中任意游戏者即返回true。同时,更新win为胜利者bHitDoShot(player,gptGorilla〔player〕。x,gptGorilla〔player〕。y,win);如果太阳被击中,重绘太阳if(gbSunHit)DoSun(SUNHAPPY);如果击中对手,更新分数if(bHittrue)aryScore〔win〕;交替攻击player1player;Sleep(100);}Sleep(1000);};} 5。创建随机的游戏场景参数:aryBCoor〔〕:存储每一栋楼的左上角坐标voidMakeCityScape(POINTaryBCoor){intx10;设置随机的楼群倾斜的趋势intsloperand()6;intiNewHt;新楼的高度switch(slope){case0:iNewHt15;break;逐渐升高case1:iNewHt130;break;逐渐降低case2:case3:case4:iNewHt15;break;倒V型(比较常见)case5:iNewHt130;break;V型}intiBottomLine465;建筑的最低端intiHtInc10;高度增加值intiDefBWidth37;默认的建筑宽度intiRandomHeight120;随机的高度差异intiWWidth3;窗户宽度intiWHeight6;窗户高度intiWDifV15;窗户的垂直间距intiWDifH10;窗户的水平间距intiCurBuilding0;do{switch(slope){case0:iNewHtiHtInc;break;case1:iNewHtiHtInc;break;case2:case3:case4:if(xSCRWIDTH2)iNewHt2iHtInc;elseiNewHt2iHtInc;break;case5:if(xSCRWIDTH2)iNewHt2iHtInc;elseiNewHt2iHtInc;break;}设置楼宇宽度,并检查是否超出屏幕intiBWidthiDefBWidthrand()iDefBWidth;设置楼宇高度,并检查楼宇是否超出屏幕下方intiBHeightiNewHtrand()iRandomHeight;if(iBHeightiHtInc)iBHeightiHtInc;检查楼宇是否太高if(iBottomLineiBHeight25)iBHeight20;保存楼的坐标aryBCoor〔iCurBuilding〕。xx;aryBCoor〔iCurBuilding〕。yiBottomLineiBHeight;绘制楼宇COLORREFaryBuildingColor〔3〕{CYAN,LIGHTGRAY,RED};定义楼宇的三种颜色intcolorIDrand()3;setlinecolor(BACKATTR);rectangle(x1,iBottomLine1,xiBWidth1,iBottomLineiBHeight1);setfillcolor(aryBuildingColor〔colorID〕);solidrectangle(x,iBottomLine,xiBWidth,iBottomLineiBHeight);绘制窗户intcx3;do{for(intiiBHeight3;i7;iiWDifV){intwinColor;if(rand()40)winColorDARKGRAY;elsewinColorYELLOW;setfillcolor(winColor);solidrectangle(c,iBottomLinei,ciWWidth,iBottomLineiiWHeight);}ciWDifH;}while(cxiBWidth3);xiBWidth2;iCurBuilding;}while(xSCRWIDTH1);giLastBuildingiCurBuilding1;保存最后一栋楼的编号设置随机风力giWindrand()6130;绘制风向箭头if(giWind!0){intwindLinegiWind3(SCRWIDTH320);setlinecolor(EXPLOSIONCOLOR);intarrowDir(giWind0)?2:2;line(SCRWIDTH2,SCRHEIGHT5,SCRWIDTH2windLine,SCRHEIGHT5);line(SCRWIDTH2windLine,SCRHEIGHT5,SCRWIDTH2windLinearrowDir,SCRHEIGHT52);line(SCRWIDTH2windLine,SCRHEIGHT5,SCRWIDTH2windLinearrowDir,SCRHEIGHT52);}} 6。绘制游戏者和太阳的位置将游戏者放到楼宇顶端(从边缘数第二个或第三个楼宇上)参数:aryBCoor〔〕:楼宇数组。保存每栋楼的左上角坐标voidPlaceGorillas(POINTaryBCoor){for(inti0;i1;i){intiBNum(i0)?rand()21:giLastBuilding1rand()2;intiBWidtharyBCoor〔iBNum1〕。xaryBCoor〔iBNum〕。x;gptGorilla〔i〕。xaryBCoor〔iBNum〕。xiBWidth2gimgGorD。getwidth()2;gptGorilla〔i〕。yaryBCoor〔iBNum〕。ygimgGorD。getheight();putimage(gptGorilla〔i〕。x,gptGorilla〔i〕。y,gimgGorD);}}绘制太阳参数:smile:太阳是否微笑voidDoSun(boolsmile){设置太阳的位置intxSCRWIDTH2;intySUNHEIGHT15;绘制太阳脸setlinecolor(SUNATTR);setfillcolor(SUNATTR);fillcircle(x,y,12);光芒for(doublea0;aPI2;aPI8)line(x,y,int(xcos(a)200。5),int(ysin(a)160。5));嘴setlinecolor(BACKATTR);setfillcolor(BACKATTR);if(smile)绘制笑脸arc(x8,y8,x8,y8,(210PI180),(330PI180));else绘制受惊表情(o型嘴)fillcircle(x,y5,3);眼睛fillcircle(x3,y2,1);fillcircle(x3,y2,1);} 7。实现按键操作,实现扔香蕉功能参数:idPlayer:游戏者(准备扔香蕉的)x,y:游戏者的位置boolDoShot(intidPlayer,intx,inty,intwin){清空鼠标消息缓冲区flushmessage(EMMOUSE);攻击的起始位置intstartxx(idPlayer1?gimgGorD。getwidth():0);intstartyy;角度辅助线的位置intmxstartx,mystarty90;intoldmxmx,oldmymy;doubleanglePI2;投掷角度intvelocity2;投掷力度setrop2(R2XORPEN);setlinecolor(RED);line(startx,starty,mx,my);鼠标输入攻击角度ExMessagemsg;while(true){msggetmessage(EMMOUSE);if(msg。messageWMMOUSEMOVE){if(msg。yy){mxstartx(msg。xstartx?90:90);mystarty;anglemsg。xstartx?0:PI;}elseif(msg。x!startx){angleatan((double(starty)msg。y)(double(msg。x)startx));if(angle0)anglePI;mxstartxint(cos(angle)900。5);mystartyint(sin(angle)900。5);}else{mxmsg。x;myy90;anglePI2;}line(startx,starty,oldmx,oldmy);line(startx,starty,mx,my);oldmxmx;oldmymy;}elseif(msg。messageWMLBUTTONDOWN)break;}line(startx,starty,oldmx,oldmy);鼠标输入攻击力度setlinestyle(PSSOLID,8);oldmxmxstartxint(cos(angle)velocity0。5);oldmymystartyint(sin(angle)velocity0。5);line(startx,starty,mx,my);while(true){if(peekmessage(msg)){if(msg。messageWMLBUTTONUP)break;}mxstartxint(cos(angle)velocity0。5);mystartyint(sin(angle)velocity0。5);line(startx,starty,oldmx,oldmy);line(startx,starty,mx,my);oldmxmx;oldmymy;if(velocity90)velocity2;Sleep(20);}velocity2;力度扩大一倍line(startx,starty,oldmx,oldmy);恢复设置setlinestyle(PSSOLID,1);setrop2(R2COPYPEN);实施攻击gbSunHitfalse;intiPlayerHitPlotShot(x,y,angle,velocity,idPlayer);攻击结果if(iPlayerHit1){win1;returnfalse;}else{win(iPlayerHitidPlayer)?1idPlayer:idPlayer;VictoryDance(win);returntrue;}} 8。扔出香蕉,计算坐标,弧度等等进行香蕉攻击,使香蕉划过屏幕参数:startX,startY:游戏者(扔香蕉的)的坐标angle:扔出的方向(弧度)velocity:扔出的力度idPlayer:游戏者(扔香蕉的)intPlotShot(intstartX,intstartY,doubleangle,intvelocity,intidPlayer){投掷力量在x、y方向上的分量doubleinitXVelcos(angle)velocity;doubleinitYVelsin(angle)velocity;doublex,y;doubleoldxstartX;doubleoldystartY;绘制游戏者(投掷动作)putimage(startX,startY,idPlayer0?gimgGorL:gimgGorR);Sleep(100);绘制游戏者(站立动作)putimage(startX,startY,gimgGorD);boolbImpactfalse;是否碰撞boolbShotInSunfalse;是否击中太阳boolbOnScreentrue;香蕉是否在屏幕上intiPlayerHit1;是否击中对手(1:未击中;0、1:被击中者的ID)boolbNeedErasefalse;是否需要擦掉旧香蕉POINTlook〔4〕;碰撞检测的位置(香蕉中心上下左右四个边的中点)look〔2〕。x0;look〔3〕。xgimgBanana〔0〕。getwidth()1;look〔0〕。xlook〔1〕。xlook〔3〕。x2;look〔0〕。y0;look〔1〕。ygimgBanana〔0〕。getheight()1;look〔2〕。ylook〔3〕。ylook〔1〕。y2;intstartXPosstartX;intstartYPosstartYgimgBanana〔0〕。getheight();if(idPlayer1)startXPosstartXPosgimgGorD。getwidth()gimgBanana〔0〕。getwidth();intpointColor0;introt;doublet0;while(!bImpactbOnScreen){擦掉旧香蕉if(bNeedErase){bNeedErasefalse;DrawBanana(int(oldx0。5),int(oldy0。5),1,false);}xstartXPos(initXVelt)(giWind5。0tt);ystartYPos(1(initYVelt)(GRAVITYtt));if((xSCRWIDTH10。0)(x3)(ySCRHEIGHT3。0))bOnScreenfalse;if(bOnScreeny0){检测是否击中(对香蕉中心上下左右四个边的中点做检测)for(inti0;i4;i){pointColorgetpixel(int(xlook〔i〕。x0。5),int(ylook〔i〕。y0。5));if(pointColorBACKATTRpointColorWHITE)目标是背景色或白色字幕,未击中{bImpactfalse;if(bShotInSuntrue(abs(SCRWIDTH2int(x))20ySUNHEIGHT))bShotInSunfalse;}elseif(pointColorSUNATTRySUNHEIGHT)击中太阳{if(!gbSunHit)DoSun(SUNSHOCK);gbSunHittrue;bShotInSuntrue;}elsebImpacttrue;if(bImpact)break;}if(!bShotInSun!bImpact){绘制香蕉rotint(t10)4;DrawBanana(int(x0。5),int(y0。5),rot,true);bNeedErasetrue;}oldxx;oldyy;}t0。1;Sleep(50);}if(pointColor!OBJECTCOLORbImpact)DoExplosion(int(xgimgBanana〔0〕。getwidth()20。5),int(ygimgBanana〔0〕。getheight()20。5));elseif(pointColorOBJECTCOLOR)iPlayerHitExplodeGorilla(int(x0。5),int(y0。5));returniPlayerHit;} 9。当然还是不能忘记不断对香蕉的位置进行刷新参数:x,y:香蕉的位置r:香蕉的旋转位置d:绘制还是擦除(true:绘制;false:擦除)voidDrawBanana(intx,inty,intr,boold){staticIMAGEoldimg;if(d){getimage(oldimg,x,y,gimgBanana〔0〕。getwidth(),gimgBanana〔0〕。getheight());putimage(x,y,gimgBanana〔r〕);}elseputimage(x,y,oldimg);} 10。实现香蕉命中后的爆炸效果以及角色死亡效果香蕉攻击后的爆炸效果参数:x,y:爆炸的位置voidDoExplosion(intx,inty){intr10;inti;setlinecolor(EXPLOSIONCOLOR);for(i0;ir;i){circle(x,y,i);Sleep(16);}setlinecolor(BACKATTR);for(ir;i0;i){circle(x,y,i);Sleep(16);}setfillcolor(BACKATTR);fillcircle(x,y,r);}游戏者死亡后爆炸参数:x,y:攻击的位置intExplodeGorilla(intx,inty){intiPlayerHit(xSCRWIDTH2)?0:1;intiPlayerXgptGorilla〔iPlayerHit〕。xgimgGorD。getwidth()2;intiPlayerYgptGorilla〔iPlayerHit〕。ygimgGorD。getheight()2;inti;setlinecolor(EXPLOSIONCOLOR);for(i1;i10;i){circle(x,y,i);Sleep(10);}for(i1;i16;i){circle(iPlayerX,iPlayerY11,i);Sleep(10);}for(i1;i32;i){setlinecolor((i20)?0x54A8FC:0x5400FC);circle(iPlayerX,iPlayerY,i);Sleep(10);}for(i48;i1;i){setlinecolor(BACKATTR);circle(iPlayerX,iPlayerY,i);Sleep(10);}fillcircle(iPlayerX,iPlayerY,48);returniPlayerHit;} 11。最后还可以添加一下死亡之后的游戏动画(比如跳舞庆祝胜利者)绘制跳舞的大猩猩(胜利后执行)参数:idPlayer:游戏者编号voidVictoryDance(intidPlayer){for(inti0;i4;i){putimage(gptGorilla〔idPlayer〕。x,gptGorilla〔idPlayer〕。y,gimgGorL);Sleep(200);putimage(gptGorilla〔idPlayer〕。x,gptGorilla〔idPlayer〕。y,gimgGorR);Sleep(200);}} 12。主函数(把所有的功能函数放这里来)voidmain(){Init();Intro();PlayGame(T(Player1),T(Player2));} 大家赶紧去动手试试吧! 此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C项目案例,帮助大家在学习C语言的道路上披荆斩棘! 编程学习书籍分享: 编程学习视频分享: 整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦! 对于CC感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些CC的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!