1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 用C语言写一个简单的飞机大战游戏(用到easyx图形库)

用C语言写一个简单的飞机大战游戏(用到easyx图形库)

时间:2023-06-27 21:02:21

相关推荐

用C语言写一个简单的飞机大战游戏(用到easyx图形库)

学习内容:1.背景的运动

2.飞机爆炸效果

3.透明贴图工具

目录

一、需要用到的头文件、全局变量和一些函数、结构体

二、数据初始化以及图片处理

三、主体

四、物体碰撞

五、游戏运行

六、透明贴图工具和定时器

一、需要用到的头文件、全局变量和一些函数、结构体

#include<graphics.h>#include<stdio.h>#include<easyx.h>#include<time.h>#include<stdlib.h>#include<math.h>#include<Windows.h>#include"tool.h"#pragma comment(lib,"winmm.lib")#define WIDTH 480#define HIGHT 700IMAGE img_bk[2];//背景图IMAGE img_myplane[2];//玩家飞机IMAGE img_bullet;//子弹IMAGE img_enemyplane;//敌机IMAGE img_enemyboom[4];//敌机爆炸int bkY[2] = { -700,0 };//两张背景位置int score = 0;//得分int enemy_num = 4;//敌机数量int enemy_add = 0;//敌机需要增加数//坐标结构体struct Point{int x;int y;};//玩家飞机结构坐标,速度,是否存在struct Plane {int px;int py;int speed;int frame;//用于切换玩家飞机图片bool exis;}gamer;//子弹结构体包括坐标和是否存在(可自行添加子弹种类,速度,方向等属性)typedef struct Bullet{int x;int y;bool exis;Bullet* next;}mybullet;mybullet* one_mybullet;//敌机结构体(可自行添加其他类飞机,boss等)typedef struct Enemy{int posx;//坐标int posy;int boom;//爆炸图片帧数//int type;//飞机类型bool exis;//是否存活Enemy* next;}enemy;enemy* one_enemy;void loadImage(); //加载图片void InitPlayer(Plane* pthis, int x, int y);//初始玩家飞机void DrawImg(); //绘制图片void DrawPlayer(Plane* pthis); //绘制玩家飞机void PlayerMove();//玩家飞机运动void RunBk(); //背景运动void CreateBullet(); //创建子弹void AddMybullet();//增加子弹并初始化void MybulletMove(); //子弹移动void CreatEnemy();//创建敌机void AddEnemy(); //增加敌机并初始化void EnemyMove(); //敌机移动void HitEnemy(); //击中敌机void LoadBoom(); //加载爆炸图片void AnimalBoom(IMAGE *picture, Enemy* pthis) //飞机爆炸效果bool overlapationa(enemy* pthis); //判断是否飞机与飞机重叠bool overlapationb(enemy* pthis); //判断是否子弹与飞机重叠bool collisiona(enemy* e1, enemy* e2);//判断飞机与飞机是否碰撞bool collisionb(mybullet* b, enemy* e);//判断飞机与子弹是否碰撞

二、数据初始化以及图片处理

//初始化数据void InitData(){mciSendString("open music/bgm1.mp3 alias bkmusic", NULL, 0, NULL);mciSendString("play bkmusic repeat", NULL, 0, NULL);initgraph(WIDTH, HIGHT,SHOWCONSOLE);//图形窗口InitPlayer(&gamer, (getwidth() - img_myplane->getwidth()) / 2, getheight() / 2 + img_myplane->getheight());CreateBullet();CreatEnemy();loadImage();}//加载图片资源void loadImage(){loadimage(img_bk + 0, "images/background1.png");//加载背景图片loadimage(img_bk + 1, "images/background2.png");//加载背景图片loadimage(img_myplane + 0, "images/me1.png");//加载玩家飞机loadimage(img_myplane + 1, "images/me2.png");//加载玩家飞机loadimage(&img_bullet, "images/bullet1.png");//加载玩家子弹loadimage(&img_enemyplane, "images/enemy1.png");//加载敌机图片LoadBoom();}//加载敌机爆炸效果(可以给多个飞机做接口,只演示一种飞机爆炸)void LoadBoom(){for (int i = 0; i <= 3; i++){char fileName[30] = {0};sprintf(fileName, "images/enemy1_down%d.png", i);loadimage(&img_enemyboom[i], fileName);}}//敌机爆炸效果(避免使用循环语句、会出现卡顿现象)void AnimalBoom(IMAGE *picture, Enemy* pthis){if (pthis->exis == false && timer(20, 3))//控制帧率{drawImg(pthis->posx, pthis->posy, &picture[pthis->boom] );if (pthis->boom == 3)//当三张爆炸图片全部显示完之后,归零{pthis->boom = 0;pthis->exis = true;//当创建的敌机与其他敌机重叠时,重新创建,直至不重合do{pthis->posx = rand() % (getheight() / 2);pthis->posy = -img_enemyplane.getheight();} while ( overlapationa(pthis));}else{pthis->boom++;//用于切换下一张图片}}}//让背景连续滚动(用两张上下连接的背景图,循环运动)void RunBk(){putimage(0, bkY[0], &img_bk[0]);putimage(0, bkY[1], &img_bk[1]);//打印出背景图片if (timer(50, 1)){bkY[0] ++;bkY[1] ++;if (bkY[0] >= 700){bkY[0] = -700;}else if (bkY[1] >= 700){bkY[1] = -700;}}}//绘制图片void DrawImg(){RunBk();//背景滚动DrawPlayer(&gamer);//打印玩家飞机图片//打印子弹mybullet* bt = one_mybullet->next;while (bt != NULL&&bt->exis == true){drawImg(bt->x, bt->y, &img_bullet);//printf("%d %d\n", bt->x, bt->y);bt = bt->next;}//打印敌机enemy* et = one_enemy->next;while (et != NULL){if (et->exis == true)//飞机不存在时打印爆炸图片{drawImg(et->posx, et->posy, &img_enemyplane);}else{AnimalBoom(img_enemyboom, et);}et=et->next;}//显示得分setcolor(BLACK);settextstyle(25, 0, "黑体");TCHAR s[5];_stprintf(s,_T("%d"),score);outtextxy(20, 20, s);setbkmode(0);}

三、主体

玩家、子弹和敌机的初始化,增加数量和运动等

//飞机初始化void InitPlayer(Plane* pthis,int x,int y){pthis->px = x;pthis->py = y;pthis->exis = true;pthis->frame = 0;}//绘制玩家飞机,(让玩家飞机有运动效果)void DrawPlayer(Plane* pthis){drawImg(pthis->px, pthis->py, img_myplane + pthis->frame);//打印玩家飞机pthis->frame = (pthis->frame + 1) % 2;}//玩家飞机移动void PlayerMove()//用鼠标移动玩家飞机{int startclock = clock();MOUSEMSG m;//鼠标结构体while (MouseHit()){m = GetMouseMsg();if (m.uMsg == WM_MOUSEMOVE){gamer.px = m.x - img_myplane->getwidth() / 2;gamer.py = m.y - img_myplane->getheight() / 2;}}if (timer(200,0) ){AddMybullet();}}//创建玩家飞机子弹void CreateBullet(){one_mybullet = (mybullet*)malloc(sizeof(mybullet));if (one_mybullet == NULL){return;}else{one_mybullet->next = NULL;}}//加载子弹void AddMybullet(){mybullet* pnew = (mybullet*)malloc(sizeof(mybullet));if (pnew == NULL){return;}else{pnew->next = NULL;pnew->x = gamer.px + 51;pnew->y = gamer.py ;pnew->exis = true;pnew->next = one_mybullet->next;one_mybullet->next = pnew;}}//让玩家子弹移动void MybulletMove(){mybullet* P1 = one_mybullet->next;mybullet* P2 = one_mybullet;for (; P1 != NULL; P1 = P1->next){if (P1->y <= 0 || P1->exis == false)//当子弹越界或者死亡时,释放掉子弹{P2->next = P1->next;free(P1);return;}else{P1->y -= 9;}P2 = P1;}}//创建敌机void CreatEnemy(){one_enemy = (enemy*)malloc(sizeof(enemy));if (one_enemy == NULL){return;}one_enemy->next = NULL;}增加敌机并初始化void AddEnemy(){//srand((unsigned int)time(NULL));enemy* ep= (enemy*)malloc(sizeof(enemy));if (ep == NULL){return;}ep->next = NULL;ep->exis = true;ep->boom = 0;ep->next = one_enemy->next;one_enemy->next = ep;do{ep->posx = rand() % (getheight() / 2);ep->posy = -img_enemyplane.getheight() / 2;} while (ep->next != NULL &&overlapationa(ep));//创建的飞机不与其他飞机重叠,否则重新生成}// 敌机移动void EnemyMove(){srand((unsigned int)time(NULL));enemy* pt = one_enemy->next;while (pt){if (pt->posy >= getheight()){do{pt->posx = rand() % (getheight() / 2);pt->posy = -img_enemyplane.getheight();} while (overlapationa(pt));}else{pt->posy += 2;}pt = pt->next;}}

四、物体碰撞

//击中敌机void HitEnemy(){enemy* e = NULL;mybullet* b = NULL;e = one_enemy->next;while (e != NULL){if (e->exis == false){e = e->next;continue;}b = one_mybullet->next;while (b != NULL){if (b->exis == true && collisionb(b, e)){score++;e->exis = false;b->exis = false;}else{b = b->next;continue;}b = b->next;}e = e->next;}}//用碰撞物体的四个点的任意点判断是否在被碰撞物范围内//判断飞机与飞机是否碰撞bool collisiona(enemy* e1,enemy* e2 ){struct Point ap[4] ={{e1->posx,e1->posy},{e1->posx,e1->posy+img_enemyplane.getheight()},{e1->posx+img_enemyplane.getwidth(),e1->posy},{ e1->posx + img_enemyplane.getwidth() ,e1->posy + img_enemyplane.getheight() }};for (int i = 0; i < 4; i++){if (ap[i].x >= e2->posx&&ap[i].x <= e2->posx + img_enemyplane.getwidth() &&ap[i].y >= e2->posy&&ap[i].y <= e2->posy + img_enemyplane.getwidth()){return true;}}return false;}//判断子弹与飞机是否碰撞bool collisionb(mybullet* b, enemy* e){const struct Point ap[4] ={{ b->x ,b->y },{ b->x,b->y + img_bullet.getheight() },{ b->x + img_bullet.getwidth(),b->y },{ b->x + img_bullet.getwidth() ,b->y + img_bullet.getheight() }};for (int i = 0; i < 4; i++){if (ap[i].x >= e->posx&&ap[i].x <= e->posx + img_enemyplane.getwidth() &&ap[i].y >= e->posy&&ap[i].y <= e->posy + img_enemyplane.getwidth()) {return true;}}return false;}//判断飞机与飞机是否重叠(避免生成飞机堆叠)bool overlapationa(enemy* pthis){enemy* a = NULL;a = one_enemy->next;while (a != NULL){if (pthis == a || a->exis == false){a = a->next;continue;}if (collisiona(pthis, a)){return true;}a = a->next;}return false;}bool overlapationb(enemy* pthis){mybullet* a = NULL;a = one_mybullet->next;while (a != NULL){if (collisionb(a, pthis)){return true;}a = a->next;}return false;}

五、游戏运行

//运行游戏void RunGame(){BeginBatchDraw();//防止闪屏if (enemy_add <= enemy_num)//可以设计关卡来增加敌机数量{AddEnemy();enemy_add++;}DrawImg();PlayerMove();MybulletMove();HitEnemy();EnemyMove();int startTime = clock();int frameTime = clock() - startTime;if (1000 / 60 - frameTime > 0){Sleep(1000 / 30 - frameTime);//控制运行速度}EndBatchDraw();//结束绘制}//====================================== 主程序===============================//主程序int main(){InitData();while (true){RunGame();}getchar();closegraph();return 0;}

六、透明贴图工具和定时器

drawImg()用于贴无背景图片与putimage()相似

#pragma once#include<easyx.h>void drawImg(int x, int y, IMAGE *src);void drawImg(int x, int y,int dstw, int dstH, IMAGE *src, int srcX, int srcY);void drawImg(int x, int y, IMAGE *src){DWORD* pwin = GetImageBuffer();DWORD* psrc = GetImageBuffer(src);int win_w = getwidth();int win_h = getheight();int src_w = src->getwidth();int src_h = src->getheight();int real_w = (x + src_w > win_w) ? win_w - x : src_w;int real_h = (y + src_h > win_h) ? win_h - y: src_h;if (x < 0) { psrc += -x; real_w -= -x; x = 0; }if (y < 0) { psrc += (src_w*-y); real_h -= -y; y = 0; }pwin +=(win_w*y + x);for (int iy = 0; iy < real_h; iy++){for (int ix = 0; ix < real_w; ix++){byte a = (byte)(psrc[ix] >> 24);if (a > 100){pwin[ix] = psrc[ix];}}pwin += win_w;psrc += src_w;}}void drawImg(int x, int y, int dstW, int dstH, IMAGE* src, int srcX, int srcY){DWORD* pwin = GetImageBuffer();DWORD* psrc = GetImageBuffer(src);int win_w = getwidth();int win_h = getheight();int src_w = src->getwidth();int src_h = src->getheight();int real_w = (x + dstW> win_w) ? win_w - x : dstW;int real_h = (y + dstH > win_h) ? win_h - y : dstH;if (x < 0) { psrc += -x;real_w -= -x; x = 0; }if (y < 0) { psrc += (dstW*-y); real_h -= -y; y = 0; }pwin += (win_w*y + x);for (int iy = 0; iy < real_h; iy++){for (int ix = 0; ix < real_w; ix++){byte a = (byte)(psrc[ix + srcX + srcY*src_w] >> 24);if (a > 100){pwin[ix] = psrc[ix + srcX + srcY*src_w];}}pwin += win_w;psrc += src_w;}}//定时器bool timer(int ms, int id){static int start[5];int end = clock();if (end - start[id] >= ms){start[id] = end;return true;}return false;}

总结:实现的内容比较简单,冗余,仅用于学习参考,有兴趣的可以自行添加更多功能,多动手才能有更多的进步哟。

素材:链接:/s/1XDbXx3C83kyyzkQZL3mmiQ

提取码:65qv

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。