《C语言课程设计与游戏开发实践课程》4-5章总结

目录

一、知识点总结

  第四章

    4.2多球反弹

    4.3实时钟表

    4.5鼠标交互的消砖块

  第五章 图片和声音素材在游戏的应用

二、代码实现

  第五章

  5.1flappy bird

  5.2飞机大战

  5.3复杂动画效果

  5.4双人反弹球

 

一、知识点总结

  第四章 绘图游戏开发

 1 4.2多球反弹
 2 多球反弹,不仅要判断多球与墙壁是否碰撞,还要判断球与球是否碰撞。球球碰撞的实现方法是:记录离每个球最近的球,判断球距(球心与球心)是否大于两倍半径。
公式为(x1-x2)2+(y1-y2)2<=4r2 碰撞后速度交换。 3 float minDistances2[BallNum][2]; // 记录某个小球,距离它最近的小球的距离,这个小球的下标 4 for (i=0;i<BallNum;i++) 5 { 6 minDistances2[i][0] = 9999999; 7 minDistances2[i][1] = -1; 8 } 9 10 // 求解所有小球两两之间的距离平方 11 for (i=0;i<BallNum;i++) 12 { 13 for (j=0;j<BallNum;j++) 14 { 15 if (i!=j) // 自己和自己不需要比 16 { 17 float dist2; 18 dist2 = (ball_x[i] - ball_x[j])*(ball_x[i] - ball_x[j]) 19 + (ball_y[i] - ball_y[j])*(ball_y[i] - ball_y[j]); 20 if (dist2<minDistances2[i][0]) 21 { 22 minDistances2[i][0] = dist2; 23 minDistances2[i][1] = j; 24 } 25 } 26 } 27 } 28 29 // 判断球之间是否碰撞 30 for (i=0;i<BallNum;i++) 31 { 32 if (minDistances2[i][0]<=4*radius*radius) // 最小距离小于阈值,发生碰撞 33 { 34 j = minDistances2[i][1]; 35 // 交换速度 36 int temp; 37 temp = ball_vx[i]; ball_vx[i] = ball_vx[j]; ball_vx[j] = temp; 38 temp = ball_vy[i]; ball_vy[i] = ball_vy[j]; ball_vy[j] = temp; 39 40 minDistances2[j][0] = 999999999; // 避免交换两次速度,又回去了 41 minDistances2[j][1] = -1; 42 } 43 } 44 45 4.3实时钟表 46 表盘上写文本 47 outtextxy(center_x - 25, center_y + Width/6, "我的时钟"); 48 49 重点:获取电脑时间,并显示在表盘上 50 SYSTEMTIME ti; // 定义变量保存当前时间 51 GetLocalTime(&ti); // 获取当前时间 52 // 秒钟角度变化 53 secondAngle = ti.wSecond * 2*PI/60; // 一圈一共2*PI,一圈60秒,一秒钟秒钟走过的角度为2*PI/60 54 // 由角度决定的秒针端点坐标,用到三角函数,需要引入#include <math.h> 55 secondEnd_x = center_x + secondLength*sin(secondAngle); 56 secondEnd_y = center_y - secondLength*cos(secondAngle); 57 58 可以用于日期的比较: 59 SYSTEMTIME st1,st2; 60 GetSystemTime(&st1); 61 GetSystemTime(&st2); 62 int re=memcmp(&st1,&st2,sizeof(SYSTEMTIME)); 63 一条秒针的绘制,和隐藏 64 setlinestyle(PS_SOLID, 2); 65 setcolor(YELLOW); 66 line(center_x, center_y, secondEnd_x, secondEnd_y); // 画秒针 67 68 setcolor(BLACK); 69 setlinestyle(PS_SOLID, 2); 70 line(center_x, center_y, secondEnd_x, secondEnd_y); // 隐藏前一帧的秒针
  1 #include <graphics.h>
  2 #include <conio.h>
  3 #include <math.h>
  4 
  5 #define High 480  // 游戏画面尺寸
  6 #define Width 640
  7 #define    PI    3.14159
  8 
  9 int main()
 10 {
 11     initgraph(Width, High);        // 初始化 640 x 480 的绘图窗口    
 12     int center_x,center_y;      // 中心点的坐标,也是表的中心
 13     center_x = Width/2;
 14     center_y = High/2;
 15     int secondLength = Width/5;           // 秒针的长度
 16     int minuteLength = Width/6;           // 分针的长度
 17     int hourLength = Width/7;             // 时针的长度
 18     
 19     int secondEnd_x,secondEnd_y;    // 秒针的终点
 20     int minuteEnd_x,minuteEnd_y;    // 分针的终点
 21     int hourEnd_x,hourEnd_y;    // 时针的终点
 22     float secondAngle;       // 秒钟对应的角度
 23     float minuteAngle;       // 分钟对应的角度
 24     float hourAngle;         // 时钟对应的角度
 25     
 26     SYSTEMTIME ti;                // 定义变量保存当前时间
 27     
 28     BeginBatchDraw();
 29     while (1)
 30     {
 31         // 绘制一个简单的表盘
 32         setlinestyle(PS_SOLID, 1);
 33         setcolor(WHITE);
 34         circle(center_x, center_y, Width/4);
 35         
 36         // 画刻度
 37         int x, y,i;
 38         for (i=0; i<60; i++)
 39         {
 40             x = center_x + int(Width/4.3 * sin(PI * 2 * i / 60));
 41             y = center_y + int(Width/4.3 * cos(PI * 2 * i / 60));
 42             
 43             if (i % 15 == 0)
 44                 bar(x - 5, y - 5, x + 5, y + 5);
 45             else if (i % 5 == 0)
 46                 circle(x, y, 3);
 47             else
 48                 putpixel(x, y, WHITE);
 49         }
 50         
 51         outtextxy(center_x - 25, center_y + Width/6, "我的时钟");
 52         
 53         GetLocalTime(&ti);        // 获取当前时间
 54         // 秒钟角度变化
 55         secondAngle = ti.wSecond * 2*PI/60;  // 一圈一共2*PI,一圈60秒,一秒钟秒钟走过的角度为2*PI/60
 56         // 分钟角度变化
 57         minuteAngle = ti.wMinute * 2*PI/60 + secondAngle/60;  // 一圈一共2*PI,一圈60分,一分钟分钟走过的角度为2*PI/60
 58         // 时钟角度变化
 59         hourAngle = ti.wHour * 2*PI/12 + minuteAngle/12;  // 一圈一共2*PI,一圈12小时,一小时时钟走过的角度为2*PI/12        
 60         // 由角度决定的秒针端点坐标
 61         secondEnd_x = center_x + secondLength*sin(secondAngle);
 62         secondEnd_y = center_y - secondLength*cos(secondAngle);
 63         
 64         // 由角度决定的分针端点坐标
 65         minuteEnd_x = center_x + minuteLength*sin(minuteAngle);
 66         minuteEnd_y = center_y - minuteLength*cos(minuteAngle);
 67         
 68         // 由角度决定的时针端点坐标
 69         hourEnd_x = center_x + hourLength*sin(hourAngle);
 70         hourEnd_y = center_y - hourLength*cos(hourAngle);        
 71         
 72         setlinestyle(PS_SOLID, 2);  
 73         setcolor(YELLOW);
 74         line(center_x, center_y, secondEnd_x, secondEnd_y); // 画秒针
 75         
 76         setlinestyle(PS_SOLID, 5);  
 77         setcolor(BLUE);
 78         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 画分针
 79         
 80         setlinestyle(PS_SOLID, 10);  
 81         setcolor(RED);
 82         line(center_x, center_y, hourEnd_x, hourEnd_y); // 画时针
 83         
 84         FlushBatchDraw();        
 85         Sleep(10);
 86         
 87         setcolor(BLACK);
 88         setlinestyle(PS_SOLID, 2); 
 89         line(center_x, center_y, secondEnd_x, secondEnd_y);  // 隐藏前一帧的秒针
 90         setlinestyle(PS_SOLID, 5);  
 91         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 隐藏前一帧的分针
 92         setlinestyle(PS_SOLID, 10);  
 93         line(center_x, center_y, hourEnd_x, hourEnd_y); // 隐藏前一帧的时针
 94     }
 95     
 96     EndBatchDraw();
 97     getch();                // 按任意键继续    
 98     closegraph();            // 关闭绘图窗口
 99     return 0;
100 }
实时钟表
72 
73 4.5鼠标交互的消砖块
74 
75 MOUSEMSG m;        // 定义鼠标消息
76 if (MouseHit())  //这个函数用于检测当前是否有鼠标消息
77 {
78     m = GetMouseMsg();      // 获取一条鼠标消息
79     if(m.uMsg == WM_MOUSEMOVE)//鼠标移动时,在鼠标位置画白点
80     {
81                putpixel(m.x,m.y,WHITE);
82         }
83         else if(m.uMsg == WM_LBUTTONDOWN)//鼠标左键按下时,画方块
84         {
85                 retangle(m.x-5,m.y-5,m.x+5,m.y+5);
86         }
87         else if(m.uMsg == WM_RBUTTONUP)//鼠标右键抬起时,画圆
88         {
89                 circle(m.x,m.y,10);
90         }
91 }
92 砖块和挡板的消失出现,与4.3时钟一样,绘制黑色的圆,黑色的挡板和砖

  第五章 图片和声音素材在游戏的应用

 1 5.1图片和声音的应用
 2 图片:
 3 IMAGE img_bk;//定义图片
 4 loadimage(&img_bk, "D:\\background.jpg");//绝对地址读取图片
 5 putimage(0, 0, &img_bk);    // 在坐标(0,0)显示图片
 6 遮盖图运用:
 7 //用黑色的区域将白边隐藏,黑色具有变成透明
 8 IMAGE img_bd1,img_bd2
 9 loadimage(&img_bd1, "D:\\bird1.jpg");
10 loadimage(&img_bd2, "D:\\bird2.jpg");
11 putimage(bird_x, bird_y, &img_bd1,NOTSRCERASE); // 显示小鸟    
12 putimage(bird_x, bird_y, &img_bd2,SRCINVERT);    
13 
14 声音:
15 mciSendString():使用API函数向windows发指令,播放MAP3,使用前,需要在函数外加引用Windows Multimedia API 即:
16 #pragma comment(lib,"Winmm.lib")
17 循环播放:repeat
18 mciSendString("open D:\\background.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
19 mciSendString("play bkmusic repeat", NULL, 0, NULL);  // 循环播放
20 播放单次(多次播放时,加第一句,关闭上一次,再打开播放)
21 mciSendString("close jpmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
22 mciSendString("open D:\\Jump.mp3 alias jpmusic", NULL, 0, NULL); // 打开跳动音乐
23 mciSendString("play jpmusic", NULL, 0, NULL); // 仅播放一次
24 
25 5.2飞机大战
26 与之前C语言的飞机大战逻辑相同,只需使用EasyX的语句就行。整体逻辑如下:
27 1.首先导入图片(背景,飞机)
28 2.用遮盖图法导入飞机,使坐标位于画面中心。
29 3.加入鼠标交互代码,鼠标移动时,更新飞机坐标
30 4.导入子弹图片,加入子弹向上移动的动作,将子弹与鼠标交互结合,使子弹出现在飞机上方。起始时隐藏子弹到画面外。
31 5.导入敌机图片,加入自动下落动作,用浮点数定义速度。任意位置重新生成敌机。加判断,敌机被子弹击中消失,得分++,敌机击中飞机,显示爆炸效果,游戏结束
32 6.加音乐,初始时加背景音乐,发送子弹加发射音乐。
33 outtextxy(Width*0.48, High*0.95, "得分:");//记录得分
34 判断击中,比较简陋至今判断一个大致的距离。可以用unity的胶囊碰撞体改良。
35 if (abs(bullet_x-enemy_x)+abs(bullet_y-enemy_y) < 80)  // 子弹击中敌机
36 
37 鼠标交互代码:
 1 if (isExpolde==0)
 2     {
 3         MOUSEMSG m;        // 定义鼠标消息
 4         while (MouseHit())  //这个函数用于检测当前是否有鼠标消息
 5         {
 6             m = GetMouseMsg();
 7             if(m.uMsg == WM_MOUSEMOVE)
 8             {
 9                 // 飞机的位置等于鼠标所在的位置
10                 position_x = m.x;
11                 position_y = m.y;            
12             }
13             else if (m.uMsg == WM_LBUTTONDOWN)
14             {
15                 // 按下鼠标左键,发射子弹
16                 bullet_x = position_x;
17                 bullet_y = position_y-85;
18                 mciSendString("close fgmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
19                 mciSendString("open D:\\f_gun.mp3 alias fgmusic", NULL, 0, NULL); // 打开音乐
20                 mciSendString("play fgmusic", NULL, 0, NULL); // 仅播放一次
21             }
22         }    
23     }
鼠标交互代码
39 
40 音效交互代码:
 1 if (isExpolde==0)
 2     {        
 3         if (bullet_y>-25)
 4             bullet_y = bullet_y-2;
 5         
 6         if (enemy_y<High-25)
 7             enemy_y = enemy_y+0.5;
 8         else
 9             enemy_y = 10;        
10         if (abs(bullet_x-enemy_x)+abs(bullet_y-enemy_y) < 80)  // 子弹击中敌机
11         {
12             enemy_x = rand()%Width;
13             enemy_y = -40;
14             bullet_y = -85;    
15             mciSendString("close gemusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
16             mciSendString("open D:\\gotEnemy.mp3 alias gemusic", NULL, 0, NULL); // 打开音乐
17             mciSendString("play gemusic", NULL, 0, NULL); // 仅播放一次
18             score++;
19             if (score>0 && score%5==0 && score%2!=0)
20             {
21                 mciSendString("close 5music", NULL, 0, NULL); // 先把前面一次的音乐关闭
22                 mciSendString("open D:\\5.mp3 alias 5music", NULL, 0, NULL); // 打开音乐
23                 mciSendString("play 5music", NULL, 0, NULL); // 仅播放一次
24             }
25             if (score%10==0)
26             {
27                 mciSendString("close 10music", NULL, 0, NULL); // 先把前面一次的音乐关闭
28                 mciSendString("open D:\\10.mp3 alias 10music", NULL, 0, NULL); // 打开音乐
29                 mciSendString("play 10music", NULL, 0, NULL); // 仅播放一次
30             }
31         }
32         
33         if (abs(position_x-enemy_x)+abs(position_y-enemy_y) < 150)  // 敌机击中我们
34         {
35             isExpolde = 1;
36             mciSendString("close exmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
37             mciSendString("open D:\\explode.mp3 alias exmusic", NULL, 0, NULL); // 打开音乐
38             mciSendString("play exmusic", NULL, 0, NULL); // 仅播放一次        
39         }
40     }
音效交互代码
42 
43 5.3复杂的动画效果
44 整体逻辑是:几张图片循环播放+人物整体移动
45 图片导入函数分析:
46 void putimage(
47     int dstX,                //绘制位置的X坐标
48     int dstY,                // 绘制位置的Y坐标 
49     int dstWidth,            // 绘制的宽度
50     int dstHeight,            // 绘制的高度
51     IMAGE *pSrcImg,            // 要绘制的IMAGE对象指针
52     int srcX,                // 绘制内容在IMAGE对象中的左上角X坐标
53     int srcY,                // 绘制内容在IMAGE对象中的左上角Y坐标
54     DWORD dwRop = SRCCOPY    // The three-element grating operating code
55 );
56 例如:
57 !!区别:人物在素材图中的位置  VS  在游戏画布上的整体位置
58 putimage(0,0,75,130,&img_human,0,0);//从(0,0)点开始绘制75*130大小的图,指向img_human对象,IMAGE对象的(0,0)开始
59 
60 putimage(0,0,75,130,&img_human,left_i*75,0);//加入图片切割,不同的left_i*75,对应不同动作素材,可以使人物原地动起来
61 
62 putimage(x,y,75,130,&img_human,left_i*75,0);//加入x,y坐标,整个图像在游戏画面中移动。
63 同时要注意需要消除上一个动画,
64 clearrectangle(x,y,x+75,y+130);    // 清空画面全部矩形区域
65 
66 
67 实现人物移动的代码:
 1 while (1)
 2             {
 3                 if(kbhit())  // 判断是否有输入
 4                 {
 5                     input = getch();  // 根据用户的不同输入来移动,不必输入回车
 6                     if (input == 'a') // 左移
 7                     {   
 8                         clearrectangle(x,y,x+75,y+130);    // 清空画面全部矩形区域
 9                         left_i++;
10                         if (x>60) // 没有达到左边的墙,才移动小人的坐标
11                             x = x-10;
12                         putimage(x,y,75,130,&img_human,left_i*75,0);    
13                         FlushBatchDraw();
14                         Sleep(1);
15                         if (left_i==3)
16                             left_i = 0;
17                     }
18                     else if (input == 'd')  // 右移
19                     {
20                         clearrectangle(x,y,x+75,y+130);    // 清空画面全部矩形区域
21                         right_i++;
22                         if (x<340) // 没有达到右边的墙,才移动小人的坐标
23                             x = x+10;
24                         putimage(x,y,75,130,&img_human,right_i*75,120);    
25                         FlushBatchDraw();
26                         Sleep(1);
27                         if (right_i==3)
28                             right_i = 0;                
29                     }
30                 }
人物移动代码
70 
71 构建游戏中的地图
72 思路:采用二维数组存地图,初始化使设置四周为墙。显示时,判断为墙,显示墙的图片。
73 loadimage(&img_walls, "D:\\walls.gif");
74 int maps[8][5] = {0}; // 存储地图信息,0为空地,1为墙
75 // 显示地图图案
76     for (i=0;i<8;i++)
77         for (j=0;j<5;j++)
78             if (maps[i][j]==1)
79                 putimage(i*60,j*60,&img_walls);
80 
81 
82 5.4双人反弹球
83 知识点:异步输入函数的使用
84 用getch()每次只能读一个字符。用windows API中GetAsyncKeyState()函数,同时识别两个按键被按下的情况。参数的对应按键的ASCII码。
85 例如:
86 上箭头:VK_UP,下箭头:VK_DOWN,左箭头←:VK_LEFT,右箭头→:VK_RIGHT
87 if (GetAsyncKeyState(0x57) & 0x8000 )  // w
88             bar1_top-=step;
89 if ((GetAsyncKeyState(0x53) & 0x8000)) //s
90             bar1_top+=step;
91 if ((GetAsyncKeyState(VK_UP) & 0x8000))     // 上方向键
92             bar2_top-=step;
93 if ((GetAsyncKeyState(VK_DOWN) & 0x8000))  // 下方向键
94             bar2_top+=step;    

 

二、代码实现

  第五章

       注意:项目资源应该放该工程文件下

  5.1flappy bird

 1 #pragma warning(disable:4996);
 2 #include <graphics.h>
 3 #include <conio.h>
 4 
 5 // 引用 Windows Multimedia API
 6 #pragma comment(lib,"Winmm.lib")
 7 
 8 IMAGE img_bk, img_bd1, img_bd2, img_bar_up1, img_bar_up2, img_bar_down1, img_bar_down2;int bird_x;
 9 int bird_y;
10 
11 void startup()
12 {
13     initgraph(350, 600);
14     loadimage(&img_bk, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\background.jpg");
15     loadimage(&img_bd1, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bird1.jpg");
16     loadimage(&img_bd2, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bird2.jpg");
17     loadimage(&img_bar_up1, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bar_up1.gif");
18     loadimage(&img_bar_up2, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bar_up2.gif");
19     loadimage(&img_bar_down1, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bar_down1.gif");
20     loadimage(&img_bar_down2, "D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\bar_down2.gif");
21     bird_x = 50;
22     bird_y = 200;
23     BeginBatchDraw();
24 
25     mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\background.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
26     mciSendString("play bkmusic repeat", NULL, 0, NULL);  // 循环播放
27 }
28 
29 void show()
30 {
31     putimage(0, 0, &img_bk);    // 显示背景    
32     putimage(150, -300, &img_bar_up1, NOTSRCERASE); // 显示上一半的障碍物
33     putimage(150, -300, &img_bar_up2, SRCINVERT);
34     putimage(150, 400, &img_bar_down1, NOTSRCERASE); // 显示下一半的障碍物
35     putimage(150, 400, &img_bar_down2, SRCINVERT);
36     putimage(bird_x, bird_y, &img_bd1, NOTSRCERASE); // 显示小鸟    
37     putimage(bird_x, bird_y, &img_bd2, SRCINVERT);
38     FlushBatchDraw();
39     Sleep(50);
40 }
41 
42 void updateWithoutInput()
43 {
44     if (bird_y < 500)
45         bird_y = bird_y + 3;
46 }
47 
48 void updateWithInput()
49 {
50     char input;
51     if (kbhit())  // 判断是否有输入
52     {
53         input = getch();
54         if (input == ' ' && bird_y > 20)
55         {
56             bird_y = bird_y - 60;
57             mciSendString("close jpmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
58             mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\flappy bird图片音乐素材\\Jump.mp3 alias jpmusic", NULL, 0, NULL); // 打开跳动音乐
59             mciSendString("play jpmusic", NULL, 0, NULL); // 仅播放一次
60         }
61     }
62 }
63 
64 void gameover()
65 {
66     EndBatchDraw();
67     getch();
68     closegraph();
69 }
70 
71 int main()
72 {
73     startup();  // 数据初始化    
74     while (1)  //  游戏循环执行
75     {
76         show();  // 显示画面
77         updateWithoutInput();  // 与用户输入无关的更新
78         updateWithInput();     // 与用户输入有关的更新
79     }
80     gameover();     // 游戏结束、后续处理
81     return 0;
82 }
5.1flappy bird

  

  5.2飞机大战

  1 #pragma warning(disable:4996);
  2 #include <graphics.h>
  3 #include <conio.h>
  4 #include <math.h>
  5 #include <stdio.h>
  6 
  7 // 引用 Windows Multimedia API
  8 #pragma comment(lib,"Winmm.lib")
  9 
 10 #define High 800  // 游戏画面尺寸
 11 #define Width 590
 12 
 13 IMAGE img_bk; // 背景图片
 14 float position_x,position_y; // 飞机位置
 15 float bullet_x,bullet_y; // 子弹位置
 16 float enemy_x,enemy_y; // 敌机位置
 17 IMAGE img_planeNormal1,img_planeNormal2; // 正常飞机图片
 18 IMAGE img_planeExplode1,img_planeExplode2; // 爆炸飞机图片
 19 IMAGE img_bullet1,img_bullet2; // 子弹图片
 20 IMAGE img_enemyPlane1,img_enemyPlane2; // 敌机图片
 21 int isExpolde = 0; // 飞机是否爆炸
 22 int score = 0; // 得分
 23 
 24 void startup()
 25 {
 26     mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\game_music.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
 27     mciSendString("play bkmusic repeat", NULL, 0, NULL);  // 循环播放
 28     initgraph(Width,High);
 29     loadimage(&img_bk, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\background.jpg");
 30     loadimage(&img_planeNormal1, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\planeNormal_1.jpg");
 31     loadimage(&img_planeNormal2, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\planeNormal_2.jpg");
 32     loadimage(&img_bullet1, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\bullet1.jpg");
 33     loadimage(&img_bullet2, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\bullet2.jpg");
 34     loadimage(&img_enemyPlane1, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\enemyPlane1.jpg");
 35     loadimage(&img_enemyPlane2, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\enemyPlane2.jpg");
 36     loadimage(&img_planeExplode1, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\planeExplode_1.jpg");
 37     loadimage(&img_planeExplode2, "D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\planeExplode_2.jpg");
 38     position_x = Width*0.5;
 39     position_y = High*0.7;
 40     bullet_x = position_x;
 41     bullet_y = -85;
 42     enemy_x = Width*0.5;
 43     enemy_y = 10;    
 44     BeginBatchDraw();    
 45 }
 46 
 47 void show()
 48 {
 49     putimage(0, 0, &img_bk);    // 显示背景    
 50     if (isExpolde==0)
 51     {
 52         putimage(position_x-50, position_y-60, &img_planeNormal1,NOTSRCERASE); // 显示正常飞机    
 53         putimage(position_x-50, position_y-60, &img_planeNormal2,SRCINVERT);
 54 
 55         putimage(bullet_x-7, bullet_y, &img_bullet1,NOTSRCERASE); // 显示子弹    
 56         putimage(bullet_x-7, bullet_y, &img_bullet2,SRCINVERT);
 57         putimage(enemy_x, enemy_y, &img_enemyPlane1,NOTSRCERASE); // 显示敌机    
 58         putimage(enemy_x, enemy_y, &img_enemyPlane2,SRCINVERT);
 59     }
 60     else
 61     {
 62         putimage(position_x-50, position_y-60, &img_planeExplode1,NOTSRCERASE); // 显示爆炸飞机    
 63         putimage(position_x-50, position_y-60, &img_planeExplode2,SRCINVERT);
 64     }
 65     outtextxy(Width*0.48, High*0.95, "得分:");
 66     char s[5];
 67     sprintf(s, "%d", score);
 68     outtextxy(Width*0.55, High*0.95, s);
 69     FlushBatchDraw();
 70     Sleep(2);
 71 }
 72 
 73 void updateWithoutInput()
 74 {
 75     if (isExpolde==0)
 76     {        
 77         if (bullet_y>-25)
 78             bullet_y = bullet_y-2;
 79         
 80         if (enemy_y<High-25)
 81             enemy_y = enemy_y+0.5;
 82         else
 83             enemy_y = 10;        
 84         if (fabs(bullet_x-enemy_x)+fabs(bullet_y-enemy_y) < 80)  // 子弹击中敌机
 85         {
 86             enemy_x = rand()%Width;
 87             enemy_y = -40;
 88             bullet_y = -85;    
 89             mciSendString("close gemusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
 90             mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\gotEnemy.mp3 alias gemusic", NULL, 0, NULL); // 打开音乐
 91             mciSendString("play gemusic", NULL, 0, NULL); // 仅播放一次
 92             score++;
 93             if (score>0 && score%5==0 && score%2!=0)
 94             {
 95                 mciSendString("close 5music", NULL, 0, NULL); // 先把前面一次的音乐关闭
 96                 mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\5.mp3 alias 5music", NULL, 0, NULL); // 打开音乐
 97                 mciSendString("play 5music", NULL, 0, NULL); // 仅播放一次
 98             }
 99             if (score%10==0)
100             {
101                 mciSendString("close 10music", NULL, 0, NULL); // 先把前面一次的音乐关闭
102                 mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\10.mp3 alias 10music", NULL, 0, NULL); // 打开音乐
103                 mciSendString("play 10music", NULL, 0, NULL); // 仅播放一次
104             }
105         }
106         
107         if (fabs(position_x-enemy_x)+fabs(position_y-enemy_y) < 150)  // 敌机击中我们
108         {
109             isExpolde = 1;
110             mciSendString("close exmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
111             mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\explode.mp3 alias exmusic", NULL, 0, NULL); // 打开音乐
112             mciSendString("play exmusic", NULL, 0, NULL); // 仅播放一次        
113         }
114     }
115 }
116 
117 void updateWithInput()
118 {
119     if (isExpolde==0)
120     {
121         MOUSEMSG m;        // 定义鼠标消息
122         while (MouseHit())  //这个函数用于检测当前是否有鼠标消息
123         {
124             m = GetMouseMsg();
125             if(m.uMsg == WM_MOUSEMOVE)
126             {
127                 // 飞机的位置等于鼠标所在的位置
128                 position_x = m.x;
129                 position_y = m.y;            
130             }
131             else if (m.uMsg == WM_LBUTTONDOWN)
132             {
133                 // 按下鼠标左键,发射子弹
134                 bullet_x = position_x;
135                 bullet_y = position_y-85;
136                 mciSendString("close fgmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
137                 mciSendString("open D:\\新建文件夹\\游戏项目\\多球反弹\\飞机大战图片音乐素材\\f_gun.mp3 alias fgmusic", NULL, 0, NULL); // 打开音乐
138                 mciSendString("play fgmusic", NULL, 0, NULL); // 仅播放一次
139             }
140         }    
141     }
142 }
143 
144 void gameover()
145 {
146     EndBatchDraw();
147     getch();
148     closegraph();
149 }
150 
151 int main()
152 {
153     startup();  // 数据初始化    
154     while (1)  //  游戏循环执行
155     {
156         show();  // 显示画面
157         updateWithoutInput();  // 与用户输入无关的更新
158         updateWithInput();     // 与用户输入有关的更新
159     }
160     gameover();     // 游戏结束、后续处理
161     return 0;
162 }
5.2飞机大战

  

  5.3复杂动画效果

 1 #pragma warning(disable:4996);
 2 #include <graphics.h>
 3 #include <conio.h>
 4 int main()
 5 {
 6     initgraph(480, 300);
 7     IMAGE img_human, img_walls;    // 定义 IMAGE 对象
 8     loadimage(&img_human, "D:\\新建文件夹\\游戏项目\\多球反弹\\复杂动画效果\\行走素材图.jpg");
 9     //putimage(0, 0, &img_human);
10     //clearrectangle(0, 0, 300, 300);
11     loadimage(&img_walls, "D:\\新建文件夹\\游戏项目\\多球反弹\\复杂动画效果\\walls.jpg");
12     //putimage( 0, 0, &img_walls);
13     int x, y; // 小人整体的坐标位置
14     x = 250;
15     y = 80;
16     int left_i = 0;  // 向左行走动画的序号
17     int right_i = 0; // 向右行走动画的序号
18     char input;
19 
20     int maps[8][5] = { 0 }; // 存储地图信息,0为空地,1为墙
21     int i, j;
22     // 以下让地图四个边界为墙
23     for (i = 0;i < 8;i++)
24     {
25         maps[i][0] = 1;
26         maps[i][4] = 1;
27     }
28     for (j = 0;j < 5;j++)
29     {
30         maps[0][j] = 1;
31         maps[7][j] = 1;
32     }
33 
34     // 显示地图图案
35     for (i = 0;i < 8;i++)
36         for (j = 0;j < 5;j++)
37             if (maps[i][j] == 1)
38                 putimage(i * 60, j * 60, &img_walls);
39 
40     putimage(x, y, 75, 130, &img_human, 0, 0);
41     BeginBatchDraw();
42 
43     while (1)
44     {
45         if (kbhit())  // 判断是否有输入
46         {
47             input = getch();  // 根据用户的不同输入来移动,不必输入回车
48             if (input == 'a') // 左移
49             {
50                 clearrectangle(x, y, x + 75, y + 130);    // 清空画面全部矩形区域
51                 left_i++;
52                 if (x > 60) // 没有达到左边的墙,才移动小人的坐标
53                     x = x - 10;
54                 putimage(x, y, 75, 130, &img_human, left_i * 75, 0);
55                 FlushBatchDraw();
56                 Sleep(1);
57                 if (left_i == 3)
58                     left_i = 0;
59             }
60             else if (input == 'd')  // 右移
61             {
62                 clearrectangle(x, y, x + 75, y + 130);    // 清空画面全部矩形区域
63                 right_i++;
64                 if (x < 340) // 没有达到右边的墙,才移动小人的坐标
65                     x = x + 10;
66                 putimage(x, y, 75, 130, &img_human, right_i * 75, 120);
67                 FlushBatchDraw();
68                 Sleep(1);
69                 if (right_i == 3)
70                     right_i = 0;
71             }
72         }
73     }
74 
75     return 0;
76 }
5.3复杂动画效果

 

  5.4双人反弹球

  1 #pragma warning(disable:4996);
  2 #include <conio.h>
  3 #include <graphics.h>
  4 #include<windows.h>
  5 #define High 480  // 游戏画面尺寸
  6 #define Width 640
  7 // 全局变量
  8 int ball_x, ball_y; // 小球的坐标
  9 int ball_vx, ball_vy; // 小球的速度
 10 int radius; // 小球的半径
 11 int bar1_left, bar1_right, bar1_top, bar1_bottom; // 挡板1的上下左右位置坐标
 12 int bar2_left, bar2_right, bar2_top, bar2_bottom; // 挡板2的上下左右位置坐标
 13 int bar_height, bar_width; // 挡板的高度、宽度
 14 
 15 void startup()  // 数据初始化
 16 {
 17     ball_x = Width / 2;
 18     ball_y = High / 2;
 19     ball_vx = 1;
 20     ball_vy = 1;
 21     radius = 20;
 22 
 23     bar_width = Width / 30;
 24     bar_height = High / 2;
 25 
 26     bar1_left = Width * 1 / 20;
 27     bar1_top = High / 4;
 28     bar1_right = bar1_left + bar_width;
 29     bar1_bottom = bar1_top + bar_height;
 30 
 31     bar2_left = Width * 18.5 / 20;
 32     bar2_top = High / 4;
 33     bar2_right = bar2_left + bar_width;
 34     bar2_bottom = bar2_top + bar_height;
 35 
 36     initgraph(Width, High);
 37     BeginBatchDraw();
 38 }
 39 
 40 void clean()  // 消除画面
 41 {
 42     setcolor(BLACK);
 43     setfillcolor(BLACK);
 44     fillcircle(ball_x, ball_y, radius);
 45     fillcircle(ball_x, ball_y, radius);
 46     bar(bar1_left, bar1_top, bar1_right, bar1_bottom);
 47     bar(bar2_left, bar2_top, bar2_right, bar2_bottom);
 48 }
 49 
 50 void show()  // 显示画面
 51 {
 52     setcolor(GREEN);
 53     setfillcolor(GREEN);
 54     fillcircle(ball_x, ball_y, radius);    // 绘制绿圆    
 55 
 56     setcolor(YELLOW);
 57     setfillcolor(YELLOW);
 58     bar(bar1_left, bar1_top, bar1_right, bar1_bottom);    // 绘制黄色挡板
 59     bar(bar2_left, bar2_top, bar2_right, bar2_bottom);
 60 
 61     FlushBatchDraw();
 62     // 延时
 63     Sleep(3);
 64 }
 65 
 66 void updateWithoutInput()  // 与用户输入无关的更新
 67 {
 68     // 挡板和小圆碰撞,小圆反弹
 69     if (ball_x + radius >= bar2_left && ball_y + radius >= bar2_top && ball_y + radius <= bar2_bottom)
 70         ball_vx = -ball_vx;
 71     else if (ball_x - radius <= bar1_right && ball_y + radius >= bar1_top && ball_y + radius <= bar1_bottom)
 72         ball_vx = -ball_vx;
 73 
 74     // 更新小圆坐标
 75     ball_x = ball_x + ball_vx;
 76     ball_y = ball_y + ball_vy;
 77 
 78     if ((ball_x <= radius) || (ball_x >= Width - radius))
 79         ball_vx = -ball_vx;
 80     if ((ball_y <= radius) || (ball_y >= High - radius))
 81         ball_vy = -ball_vy;
 82 }
 83 
 84 void updateWithInput()  // 与用户输入有关的更新
 85 {
 86     int step = 1;
 87     if (GetAsyncKeyState(0x57) & 0x8000)  // w
 88         bar1_top -= step;
 89     if ((GetAsyncKeyState(0x53) & 0x8000)) //s
 90         bar1_top += step;
 91     if ((GetAsyncKeyState(VK_UP) & 0x8000))     // 上方向键
 92         bar2_top -= step;
 93     if ((GetAsyncKeyState(VK_DOWN) & 0x8000))  // 下方向键
 94         bar2_top += step;
 95 
 96     bar1_bottom = bar1_top + bar_height;
 97     bar2_bottom = bar2_top + bar_height;
 98 }
 99 
100 void gameover()
101 {
102     EndBatchDraw();
103     closegraph();
104 }
105 
106 int main()
107 {
108     startup();  // 数据初始化    
109     while (1)  //  游戏循环执行
110     {
111         clean();  // 把之前绘制的内容取消
112         updateWithoutInput();  // 与用户输入无关的更新
113         updateWithInput();     // 与用户输入有关的更新
114         show();  // 显示新画面
115     }
116     gameover();     // 游戏结束、后续处理
117     return 0;
118 }
5.4双人反弹球

 

posted @ 2021-11-25 17:26  sylvia11  阅读(263)  评论(0编辑  收藏  举报