赞
踩
学习内容: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 700
-
-
- IMAGE 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;
- }

总结:实现的内容比较简单,冗余,仅用于学习参考,有兴趣的可以自行添加更多功能,多动手才能有更多的进步哟。
素材:链接:https://pan.baidu.com/s/1XDbXx3C83kyyzkQZL3mmiQ
提取码:65qv
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。