本
文
摘
要
今天给大家带来一个青蛙过河小游戏代码,先看看效果吧!
开始界面:
游戏界面:
胜利界面:
失败界面:
接下来是这个游戏的代码,代码我们分了几个模块来写,这样不容易写乱,也方便后续修改
木板模块:
#include "stdafx.h" void createBoard(BoardType board[],int channel,int interval) { for(int i=0;i<BOARD_AMOUNT;i++) { if(0==board[channel].b[i].onMap)//不在地图上 { if(1==(channel+1)%2)//第一和第三道,从右来 { if(0==i)//第一个 {board[channel].b[i].x=board[channel].b[BOARD_AMOUNT-1].x+BOARD_LEN+interval;} else {board[channel].b[i].x=board[channel].b[i-1].x+BOARD_LEN+interval;} } else//第二和第四道,从左来 { if(0==i)//第一个 {board[channel].b[i].x=board[channel].b[BOARD_AMOUNT-1].x-BOARD_LEN-interval;} else {board[channel].b[i].x=board[channel].b[i-1].x-BOARD_LEN-interval;} } board[channel].b[i].onMap=1;//注册为在地图上 break; } } } void initBoard(BoardType b[])//给每个木版分配坐标 { int ch;//河道数 int i=0;//只创建第一条船 for(ch=0;ch<CHANNEL_AMOUNT;ch++) { if(1==(ch+1)%2)//第一和第三道,从右来 { b[ch].b[i].x=WINDOW_LEN+(i+1)*(BOARD_INTERVAL+BOARD_LEN); b[ch].b[i].onMap=1; } else//第二和第四道 { b[ch].b[i].x=0-((i+1)*(BOARD_INTERVAL+BOARD_LEN)); b[ch].b[i].onMap=1; } } //初始化其他木板 for(ch=0;ch<CHANNEL_AMOUNT;ch++) { if(1==(ch+1)%2)//第一和第三道,从右来 { for(i=1;i<BOARD_AMOUNT;i++) { b[ch].b[i].x=b[ch].b[i-1].x+(BOARD_INTERVAL+BOARD_LEN); b[ch].b[i].onMap=1; } } else//第二和第四道 for(i=1;i<BOARD_AMOUNT;i++) { b[ch].b[i].x=b[ch].b[i-1].x-(BOARD_INTERVAL+BOARD_LEN); b[ch].b[i].onMap=1; } } } void moveBoard(BoardType board[],int speed[],FrogType *frog)//移动木板 { if(frog->state!=DEAD){//死亡延时期间不移动木板 for(int ch=0;ch<CHANNEL_AMOUNT;ch++) { if(1==(ch+1)%2) { for(int i=0;i<BOARD_AMOUNT;i++) { board[ch].b[i].x-=speed[ch];//一三道 } } else { for(int i=0;i<BOARD_AMOUNT;i++) { board[ch].b[i].x+=speed[ch];//二四道 } } } } } void boardOutRange(BoardType board[])//木板出界判定 { for(int ch=0;ch<CHANNEL_AMOUNT;ch++) { if(1==(ch+1)%2)//一三道 { for(int i=0;i<BOARD_AMOUNT;i++) { if(board[ch].b[i].x<0-BOARD_LEN) {board[ch].b[i].onMap=0;} } } else//二四道 { for(int i=0;i<BOARD_AMOUNT;i++) { if(board[ch].b[i].x>WINDOW_LEN) {board[ch].b[i].onMap=0;} } } } } void outRangeBoardReset(BoardType board[],int interval)//重置出界的木板 { for(int ch=0;ch<CHANNEL_AMOUNT;ch++) { for(int i=0;i<BOARD_AMOUNT;i++) { if(0==board[ch].b[i].onMap) { createBoard(board,ch,interval); } } } } void drawBoard(BoardType board[],ImageType *img)//画木板 { setfillstyle(BROWN); int x1,y1; for(int ch=0;ch<CHANNEL_AMOUNT;ch++) { for(int i=0;i<BOARD_AMOUNT;i++) { x1=board[ch].b[i].x; y1=(int)(STREAM_INIT_Y+STREAM_WID-CHANNEL_WID*(ch+1)+(CHANNEL_WID-BOARD_WID)/2); putimage(x1,y1,&(img->woodMask),SRCAND);//位与 putimage(x1,y1,&(img->wood),SRCPAINT);//位或 //背景透明\(^o^)/~ } } } void excuteBoardFunc(BoardType board[],int ChannelSpeed[],FrogType *frog) { moveBoard(board,ChannelSpeed,frog);//移动 boardOutRange(board);//出界判定 outRangeBoardReset(board,BOARD_INTERVAL);//重置出界的木板 }青蛙模块:
#include "stdafx.h" #define PI 3.1415926535 #define UNIT PI/180 #include<math.h>//旋转加速度用到x平方 void initFrog(FrogType *frog) { frog->ch=-1; frog->x=WINDOW_LEN/2; frog->speed=8; frog->life=5; frog->passed=0; frog->state=NORMAL;//正常 frog->coin=0; frog->score=0; frog->esc=0; } void resetFrog(FrogType *frog) { frog->ch=-1; frog->x=WINDOW_LEN/2; frog->state=NORMAL; while(_kbhit()){_getch();}//清键盘缓存防止在死亡动画播放时按键。 } void moveFrog(FrogType *frog,int ChannelSpeed[]) { if(frog->state==NORMAL){//死亡则不再允许操作,也不随着河飘走 //与模板同步产生的移动 if(frog->ch>-1&&frog->ch<CHANNEL_AMOUNT) { if(1==((frog->ch+1)%2)) {frog->x-=ChannelSpeed[frog->ch];} else {frog->x+=ChannelSpeed[frog->ch];} } //通过键盘的移动 if(GetAsyncKeyState(A))//获取键盘状态而非事件。 { if(!((-1==(frog->ch))&&((frog->x)-(frog->speed)<2)))//-1道左右出界保护 { frog->x-=frog->speed; } } if(GetAsyncKeyState(D)) { if(!((-1==(frog->ch))&&((frog->x)+(frog->speed)>WINDOW_LEN-2)))//-1道左右出界保护 {frog->x+=frog->speed;} } if(GetAsyncKeyState(27)) {frog->esc=1;} int key; if(_kbhit())//当键盘按键事件时 { key=_getch(); switch(key) { case w:frog->ch+=1; break; case s: { if((frog->ch)>-1)//下出界保护 { frog->ch-=1; } break; } } } } } void frogOutRange(FrogType *frog,BoardType board[])//青蛙出界(或死亡、过关)判定 { int ch=frog->ch; if((frog->x)<0||(frog->x)>WINDOW_LEN)//1234道出界 {frog->state=DEAD;} if((ch>-1)&&(ch<CHANNEL_AMOUNT))//在河道里 { int fall=1;//落水判定 int boardPosi;//木板左上角坐标 for(int i=0;i<BOARD_AMOUNT;i++)//落水判定 { boardPosi=board[ch].b[i].x; if(frog->x>boardPosi&&frog->x<boardPosi+BOARD_LEN)//在木板上 { fall=0; break; } } if(1==fall) { frog->state=DEAD; }//落水则死亡 } if(CHANNEL_AMOUNT==ch)//上岸判定,河道数量就是河道下标+1,实际上是最后一道 {frog->state=PASSED;}//上岸 } void excuteFrogFunc(FrogType *frog,int ChannelSpeed[],BoardType board[])//青蛙操作综合 { moveFrog(frog,ChannelSpeed); frogOutRange(frog,board); } void channelSpeedUp(int ChannelSpeed[])//河加速 { static int channel=0; if(4==channel){channel=0;}//重置 ChannelSpeed[channel]+=2;//2是速度提升基数 channel++; } void drawFrog(FrogType *frog,ImageType *img) { int x1=frog->x;//右上角(判定用)坐标 int y1=WINDOW_WID-(CHANNEL_WID/2)-(frog->ch+1)*CHANNEL_WID; int x2=x1-FROG_LEN/2; int y2=y1-FROG_WID/2; static double radian;//旋转用的弧度 static double var=1;//变量,理解成log10x的x static double x=0;//变量,过关的sin函数用的 static IMAGE f,fm; if(frog->state==NORMAL){ //三元光栅,计算背景透明色 putimage(x2,y2,&(img->frog0Mask),SRCAND);//掩码和背景按位与 putimage(x2,y2,&(img->frog0),SRCPAINT);//图像与(掩码和背景按位与的结果)按位或 var=1;//变量重置 x=0; } else if(frog->state==DEAD){//旋转 radian=UNIT*(pow(var,2.4));//增加量扩大的系数,用的是平方图像 var+=0.2; rotateimage(&f,&img->frog0,radian,BLACK);//黑背景 rotateimage(&fm,&img->frog0Mask,radian,WHITE);//掩码白背景 putimage(x2,y2,&fm,SRCAND);//掩码和背景按位与 putimage(x2,y2,&f,SRCPAINT);//图像与(掩码和背景按位与的结果)按位或 } else if(frog->state==PASSED)//过关 { radian=(PI/1.5)*sin(1.5*x); x+=PI/30; rotateimage(&f,&img->frog0,radian,BLACK);//黑背景 rotateimage(&fm,&img->frog0Mask,radian,WHITE);//掩码白背景 putimage(x2,y2,&fm,SRCAND);//掩码和背景按位与 putimage(x2,y2,&f,SRCPAINT);//图像与(掩码和背景按位与的结果)按位或 } } void excuteEvent(FrogType *frog,int ChannelSpeed[],ImageType *img)//执行过关或重置等EVENT { int state=frog->state; switch(state) { case DEAD: { static int dTimer=0;//死亡时显示位置 if(DEATH_DELAY==dTimer){ resetFrog(frog); dTimer=0; frog->life-=1; frog->score-=10; int flag=1;//是否减速 for(int i=0;i<CHANNEL_AMOUNT;i++) { if(1==ChannelSpeed[i]) { flag=0;//有速度是1的河道 break; } } if(flag)//减速 { for(int i=0;i<CHANNEL_AMOUNT;i++)//死亡导致河流减速 {ChannelSpeed[i]-=1;} } } else {dTimer++;} if(0==frog->life){frog->esc=1;}//生命为0则退出 break;//switch case的break } case PASSED: { static int pTimer=0;//过关时显示位置 if(PASS_DELAY==pTimer){ pTimer=0;//计时器重置 int CSSum=0; for(int i=0;i<CHANNEL_AMOUNT;i++)//河流速度总和 {CSSum+=ChannelSpeed[i];} frog->passed+=1; frog->coin+=CSSum; frog->score+=(CSSum); channelSpeedUp(ChannelSpeed); resetFrog(frog); } else {pTimer++;} break; } } }定义控制台应用程序的入口点:
#include "stdafx.h" #include "funcdef.h"//自定义的函数 int _tmain(int argc, _TCHAR* argv[]) { //图像对象 ImageType img; initImage(&img);//加载图像 int ChannelSpeed[CHANNEL_AMOUNT];//={2,2,2,2};//河道水流速度 BoardType board[CHANNEL_AMOUNT];//木板类型 FrogType frog;//青蛙对象 initgraph(WINDOW_LEN+STATE_BAR_LEN,WINDOW_WID);//初始化图形界面 while(initWelcome(&img))//欢迎界面 { //开始游戏 for(int i=0;i<CHANNEL_AMOUNT;i++){ ChannelSpeed[i]=2;//河道水流速度重置 } initBoard(board); initFrog(&frog); initFont(); while(!frog.esc) { BeginBatchDraw();//批量绘图开始 //对木板的操作 excuteBoardFunc(board,ChannelSpeed,&frog); //对青蛙的操作 excuteFrogFunc(&frog,ChannelSpeed,board); //状态栏 excuteStateBarFunc(&frog,ChannelSpeed); //关卡事件 excuteEvent(&frog,ChannelSpeed,&img); drawStream(&img);//画河 drawBackground(&img);//画背景 drawBoard(board,&img);//画船 drawFrog(&frog,&img);//画青蛙 excuteStateBarFunc(&frog,ChannelSpeed);//状态栏 FlushBatchDraw();//批量绘图输出 Sleep(TICK); } EndBatchDraw(); } closegraph(); return 0; } void initImage(ImageType *img)//加载图片 { loadimage(&(img->frog0),"res\\frog.jpg",FROG_LEN,FROG_WID,true); loadimage(&(img->frog0Mask),"res\\frogMask.gif",FROG_LEN,FROG_WID,true); loadimage(&(img->wood),"res\\wood.jpg",BOARD_LEN,int(BOARD_WID),true); loadimage(&(img->woodMask),"res\\woodMask.gif",BOARD_LEN,int(BOARD_WID),true); loadimage(&(img->stream),"res\\stream.jpg",WINDOW_LEN,WINDOW_WID,true); loadimage(&(img->grass1),"res\\grass.jpg",WINDOW_LEN,STREAM_INIT_Y,true); loadimage(&(img->grass2),"res\\grass.jpg",WINDOW_LEN,WINDOW_WID-(STREAM_INIT_Y+STREAM_WID),true); loadimage(&(img-> *** ),"res\\ *** .jpg",WINDOW_LEN+STATE_BAR_LEN,WINDOW_WID,true); }计分模块:
#include "stdafx.h" #include "string.h" #include <stdlib.h>//_itoa,整形转字符串 void printText(char str[],int value,int *line)//输出文本 { char strValue[6];//中间变量,放数字用. _itoa_s(value,strValue,10);//_itoa,整型转字符串 strcat_s(str,30,strValue); outtextxy(WORD_START_X,WORD_START_Y+(*line-1)*WORD_LINE_SPACING,str); (*line)++; } void drawStateBar() { setfillstyle(DARKGRAY); bar(WINDOW_LEN,0,WINDOW_LEN+STATE_BAR_LEN,STATE_BAR_WID); } void drawBarValue(FrogType *frog,int ChannelSpeed[]) { int line=0;//行数 setcolor(LIGHTRED); char str[30]; strcpy_s(str,"生命值:"); printText(str,frog->life,&line); strcpy_s(str,"金币:"); printText(str,frog->coin,&line); strcpy_s(str,"积分:"); printText(str,frog->score,&line); strcpy_s(str,"渡河次数:"); printText(str,frog->passed,&line); int ch=0; strcpy_s(str,"河道一速度:"); printText(str,ChannelSpeed[ch++],&line); strcpy_s(str,"河道二速度:"); printText(str,ChannelSpeed[ch++],&line); strcpy_s(str,"河道三速度:"); printText(str,ChannelSpeed[ch++],&line); strcpy_s(str,"河道四速度:"); printText(str,ChannelSpeed[ch++],&line); } void excuteStateBarFunc(FrogType *frog,int ChannelSpeed[]) { drawStateBar(); drawBarValue(frog,ChannelSpeed); } void initFont() { setbkmode(TRANSPARENT); LOGFONT f; getfont(&f); // 获取当前字体设置 f.lfHeight = 24; // 设置字体高度为 48(包含行距) strcpy_s(f.lfFaceName, "华文中宋"); // 设置字体为“黑体” f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿 f.lfWeight=500; // 粗细 setfont(&f); // 设置字体样式 }头文件:
// stdafx.cpp : 只包括标准包含文件的源文件 // Frogger2.pch 将作为预编译头 // stdafx.obj 将包含预编译类型信息 #include "stdafx.h" // TODO: 在 STDAFX.H 中 // 引用任何所需的附加头文件,而不是在此文件中引用游戏背景,美工模块:
#include "stdafx.h" void drawStream(ImageType *img)//画河 { setfillstyle(LIGHTBLUE);//填充色:蓝 int x1=0; int y1=STREAM_INIT_Y; putimage(x1,y1,&(img->stream)); } void drawBackground(ImageType *img) { setfillstyle(LIGHTGREEN); putimage(0,0,&(img->grass1)); putimage(0,STREAM_INIT_Y+STREAM_WID,&(img->grass2)); }游戏开始界面:
#include "stdafx.h" int initWelcome(ImageType *img) { putimage(0,0,&(img-> *** )); while(!_kbhit()) { Sleep(TICK); } char key=_getch(); if(27==key){return 0;} else{return 1;} }游戏资源包:
7770】领取源码,与大家一起学习哦!
更多C语言青年歌手大奖赛,有7名评委进行打分(C语言青年歌手参加歌曲大奖赛,有10个评委)相关信息请关注本站,本文仅仅做为展示!