zoukankan      html  css  js  c++  java
  • 《C语言课程设计与游戏开发实践课程》45章总结

    目录

    一、知识点总结

      第四章

        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双人反弹球
  • 相关阅读:
    JS对象—字符串总结(创建、属性、方法)
    vue过滤器(filter)
    mac快捷键大全
    mac版 sublime快捷键大全
    mysql数据库—表的查询排序操作大全
    emmet的html和css使用技巧大全
    Java多线程——ReentrantLock源码阅读
    你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识
    Java多线程——AQS框架源码阅读
    Java多线程——ReentrantReadWriteLock源码阅读
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/15603716.html
Copyright © 2011-2022 走看看