• 《C语言课程设计与游戏开发实践课程》34章总结,EasyX常用函数


    目录

    一、知道点归纳

      第三章 数组在游戏的使用

      第四章  easyX总结

    二、代码实现

      第三章  

        3.2消砖块

        3.3空战游戏

        3.4贪吃蛇

      第四章 

        4.2多球反弹

        4.3实时钟表

        4.4Easy实现消砖块

    一、知识点归纳

      第三章 数组在游戏的使用

      1 数组的使用
      2 3.1生命游戏
      3 将画面当二维数组,每次循环更新一遍数组的值
      4 int cells[High][Width]; // 所有位置细胞生1或死0
      5 
      6 3.2消砖块
      7 将整个画面当作二维数组,填充要素:砖块、球、挡板。
      8 需要用到大量判断语句,每次循环都要重新执行,对时间复杂度上不够优秀,可以单独维护砖块的二维数组,减少show()的判断次数
      9 int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
     10 void startup()  // 数据初始化
     11 {
     12        canvas[ball_x][ball_y] = 1;    
     13     int k,i;
     14     for (k=left;k<=right;k++)  // 挡板
     15         canvas[position_x][k] = 2;    
     16     for (k=0;k<Width;k++)  // 加几排砖块
     17         for (i=0;i<High/4;i++)  
     18             canvas[i][k] = 3;
     19 }
     20 void updateWithoutInput()  // 与用户输入无关的更新
     21 {
     22         if (canvas[ball_x-1][ball_y]==3)//有砖块消砖块
     23         {
     24             ball_vx = -ball_vx;
     25             canvas[ball_x-1][ball_y] = 0;
     26             printf("\a");
     27         }
     28 }
     29 
     30 3.3空战游戏
     31 用数组存储多台敌机,enemy_x[i],enemy_y[i],i号敌机的xy坐标。
     32 这里可以运用结构体数组,会让结构更紧凑。
     33 typedef struct
     34 {
     35     int x,y;
     36 } enemy[10];
     37 
     38 用二维数组,方便对画面进行大改动例如发射散弹,积分增加,散弹半径增加,触发敌机变快。同时可以做到连续发射子弹。
     39 对画面遍历一遍,在有子弹的位置,遍历一遍敌机数组,判断是否击中,没有则向上移动。
     40 for (k=0;k<EnemyNum;k++)
     41                 {
     42                     if ((i==enemy_x[k]) && (j==enemy_y[k]))  // 子弹击中敌机
     43                     {
     44                         score++;                // 分数加1
     45                         if (score%5==0 && EnemyMoveSpeed>3)   // 达到一定积分后,敌机变快
     46                             EnemyMoveSpeed--;
     47                         if (score%5==0)   // 达到一定积分后,子弹变厉害
     48                             BulletWidth++;
     49                         canvas[enemy_x[k]][enemy_y[k]] = 0;
     50                         enemy_x[k] = rand()%2;           // 产生新的飞机
     51                         enemy_y[k] = rand()%Width;
     52                         canvas[enemy_x[k]][enemy_y[k]] = 3;
     53                         canvas[i][j] = 0;      // 子弹消失
     54                     }
     55                 }
     56 
     57 多台敌机,统一的逻辑,都自动下落,当任一台跑出都要重新生成。
     58 EnemyMoveSpeed用于更改敌机移动速度,当得分到一定值,该值减小,敌机移动速度变快
     59 if (enemy_x[k]>High)   // 敌机跑出显示屏幕
     60         {
     61             canvas[enemy_x[k]][enemy_y[k]] = 0;
     62             enemy_x[k] = rand()%2;           // 产生新的飞机
     63             enemy_y[k] = rand()%Width;
     64             canvas[enemy_x[k]][enemy_y[k]] = 3;
     65             score--;  // 减分
     66         }
     67 
     68         if (speed == EnemyMoveSpeed)
     69         {
     70             // 敌机下落
     71             for (k=0;k<EnemyNum;k++)
     72             {
     73                 canvas[enemy_x[k]][enemy_y[k]] = 0;
     74                 enemy_x[k]++;            
     75                 speed = 0;
     76                 canvas[enemy_x[k]][enemy_y[k]] = 3;
     77             }
     78         }
     79 怎么实现发射散弹
     80     else if (input == ' ')  // 发射子弹
     81         {
     82             int left = position_y-BulletWidth;//发射一排子弹
     83             int right = position_y+BulletWidth;
     84             if (left<0)    left = 0; //这防止子弹溢出
     85             if (right>Width-1)
     86                 right = Width-1;
     87             int k;
     88             for (k=left;k<=right;k++) // 发射闪弹
     89                 canvas[position_x-1][k] = 2; // 发射子弹的初始位置在飞机的正上方
     90         }
     91 
     92 当得分到5 10 15 时子弹宽带增加,但是,我觉得这里可能有一点不会逻辑,因为存在敌机跑出屏幕减分的情况,单纯判断mod5,会出现5 10 5 的情况,按原文代码还是会使得子弹宽度增加。
     93 原文:
     94  if (score%5==0)   // 达到一定积分后,子弹变厉害
     95         BulletWidth++;
     96 
     97 我的想法:
     98 方法一:用一个全局变量记录得分最大值
     99 int scoremax=0;
    100 if(score%5==0&&scoremax<score)
    101 {
    102          BulletWidth++;
    103          scoremax=score;
    104 }
    105 方法二:BulletWidth = score/5,使得直接关联。
    106 
    107 3.4贪吃蛇
    108 用数组实现蛇:
    109 canvas[High/2][Width/2] = 1;//定蛇头
    110 for (i=1;i<=4;i++)
    111     canvas[High/2][Width/2-i] = i+1;
    112 蛇移动:逻辑是>0的值加一,将最大值改为0,对应移动方向(上下左右)0改为1。这里不能直接判断蛇尾为6(吃食物后,最值会改变)
    113 void moveSnakeByDirection()
    114 {
    115     int i,j;
    116     for (i=1;i<High-1;i++)
    117         for (j=1;j<Width-1;j++)
    118             if (canvas[i][j]>0)
    119                 canvas[i][j]++; //全加一
    120 
    121     int oldTail_i,oldTail_j,oldHead_i,oldHead_j;
    122     int max = 0;
    123 
    124     for (i=1;i<High-1;i++)
    125         for (j=1;j<Width-1;j++)
    126             if (canvas[i][j]>0)
    127             {
    128                 if (max<canvas[i][j])
    129                 {
    130                     max = canvas[i][j];//找最值,更新蛇尾
    131                     oldTail_i = i;
    132                     oldTail_j = j;
    133                 }
    134                 if (canvas[i][j]==2)//记录旧蛇头
    135                 {
    136                     oldHead_i = i;
    137                     oldHead_j = j;
    138                 }
    139             }
    140 
    141     int newHead_i,newHead_j;
    142 
    143     if (moveDirection==1) // 向上移动
    144     {
    145         newHead_i = oldHead_i-1;
    146         newHead_j = oldHead_j;
    147     }
    148     if (moveDirection==2) // 向下移动
    149     {
    150         newHead_i = oldHead_i+1;
    151         newHead_j = oldHead_j;
    152     }
    153     if (moveDirection==3) // 向左移动
    154     {
    155         newHead_i = oldHead_i;
    156         newHead_j = oldHead_j-1;
    157     }
    158     if (moveDirection==4) // 向右移动
    159     {
    160         newHead_i = oldHead_i;
    161         newHead_j = oldHead_j+1;
    162     }
    163 }
    164 判断游戏结束:只看新蛇头的位置,碰到自身(>0),或者碰到墙壁(-1165 if (canvas[newHead_i][newHead_j]>0 || canvas[newHead_i][newHead_j]==-1)
    166     {
    167         printf("游戏失败!\n");
    168         Sleep(2000);
    169         system("pause");
    170         exit(0);
    171     }
    172 吃食物后,蛇身变长,出现新食物
    173 if (canvas[newHead_i][newHead_j]==-2)
    174     {
    175         canvas[food_x][food_y] = 0;
    176         // 产生一个新的食物
    177         food_x = rand()%(High-5) + 2;
    178         food_y = rand()%(Width-5) + 2;
    179         canvas[food_x][food_y] = -2;
    180         // 原来的旧蛇尾留着,长度自动+1
    181     }
    182 
    183     

      第四章  easyX总结

     1 EasyX常用函数
     2 
     3 cleardevice();//用背景色清空屏幕
     4 initgraph(width,height) ;//初始化绘图窗口
     5 closegraph();//关窗口
     6 
     7 RGB(byRed,byGreen,byBlue);//RGB三原色的值设颜色
     8 getbkcolor();//获取当前背景色
     9 setbkcolor();//设置背景颜色
    10 getbkmode();//获取当前文字背景样式
    11 setbkmode();//设置文字背景
    12 getfillcolor();//获取填充颜色
    13 setfillcolor();//设置填充颜色,可以填写BALCK,WHITE,BLUE,GREEN,RED,BROWN,YELLOW
    14 setlinecolor();//设置线条颜色,填写内容同上
    15 setcolor();//设置前景色
    16 setfillstyle();//设置填充样式
    17 void setfillstyle(
    18     int style,
    19     long hatch = NULL,
    20     IMAGE* ppattern = NULL
    21 );
    22 style可以填写
    23 Macro               Value    Description
    24 BS_SOLID                0             全填
    25 BS_NULL               1             不填充
    26 BS_HATCHED        2             图案填充
    27 BS_PATTERN        3             自定义填充样式hatch
    28 BS_DIBPATTERN    5             自定义图像填充
    29 
    30 setlinestyle();//设置线条样式
    31 Value             Description
    32 PS_SOLID             The line is solid.
    33 PS_DASH             Line is:------------
    34 PS_DOT             Line is:············
    35 PS_DASHDOT     Line is:-·-·-·-·-·-·
    36 PS_DASHDOTDOT    Line is:-··-··-··-··
    37 
    38 circle( x,y, radius);//画一个坐标(x,y)半径为radius的圆
    39 line(x1,y1,x2,y2);//画直线(x1,y1),(x2,y2)为直线的两端点的线
    40 putpixel(x,y,c);//画点(x,y),像素的颜色为c
    41 solidrectangle(x1,y1,x2,y2);//画填充矩形,(x1,y1)为左上角,(x2,y2)右下角
    42 
    43 对文字的操作
    44 gettextcolor();//获取文字颜色
    45 settextcolor(COLORREF color);//设置文字颜色,BLUE等
    46 
    47 对图片的操作
    48 {
    49     initgraph(640, 480);
    50     IMAGE img(200, 200);//创建200*200的图片对象
    51     SetWorkingImage(&img);//用于设置当前绘图设备
    52     line(0, 100, 200, 100);
    53     line(100, 0, 100, 200);
    54     circle(100, 100, 50);//绘制一个图案
    55     SetWorkingImage();//设置绘图对象到窗口
    56     putimage(220, 140, &img);//显示图片对象到窗口
    57     _getch();
    58    closegraph();}
     1 Sleep有明显画面闪烁
     2 用 BeginBatchDraw();FlushBatchDraw();EndBatchDraw();
     3 BeginBatchDraw();//开始批量绘图
     4     while (1)
     5     {
     6         FlushBatchDraw();//执行批量绘制
     7         
     8         // 延时
     9         Sleep(3);
    10     }
    11     EndBatchDraw();//结束批量绘制

    调用outtextxy()函数会报错
    原因:Unicode编码,不论中文还是英文都是用2个字节表示;
    解决方法:项目属性——字符集———使用多字节字符集

    二、代码实现

      第三章  

        3.2消砖块 

      1 #pragma warning(disable:4996);
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <conio.h>
      5 #include <windows.h>
      6 
      7 #define High 15  // 游戏画面尺寸
      8 #define Width 20
      9 
     10 // 全局变量
     11 int ball_x, ball_y; // 小球的坐标
     12 int ball_vx, ball_vy; // 小球的速度
     13 int position_x, position_y; // 挡板中心坐标
     14 int ridus;  // 挡板半径大小
     15 int left, right; // 挡板左右位置
     16 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
     17 // 0为空格,1为小球O,2为挡板*,3为方块#
     18 
     19 void gotoxy(int x, int y)  //光标移动到(x,y)位置
     20 {
     21     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
     22     COORD pos;
     23     pos.X = x;
     24     pos.Y = y;
     25     SetConsoleCursorPosition(handle, pos);
     26 }
     27 
     28 void startup()  // 数据初始化
     29 {
     30     ridus = 5;
     31     position_x = High - 1;
     32     position_y = Width / 2;
     33     left = position_y - ridus;
     34     right = position_y + ridus;
     35 
     36     ball_x = position_x - 1;
     37     ball_y = position_y;
     38     ball_vx = -1;
     39     ball_vy = 1;
     40     canvas[ball_x][ball_y] = 1;
     41 
     42     int k, i;
     43     for (k = left;k <= right;k++)  // 挡板
     44         canvas[position_x][k] = 2;
     45 
     46     for (k = 0;k < Width;k++)  // 加几排砖块
     47         for (i = 0;i < High / 4;i++)
     48             canvas[i][k] = 3;
     49 }
     50 
     51 void show()  // 显示画面
     52 {
     53     gotoxy(0, 0);    // 光标移动到原点位置,以下重画清屏
     54     int i, j;
     55     for (i = 0;i < High;i++)
     56     {
     57         for (j = 0;j < Width;j++)
     58         {
     59             if (canvas[i][j] == 0)
     60                 printf(" ");   //   输出空格
     61             else if (canvas[i][j] == 1)
     62                 printf("0");   //   输出小球0
     63             else if (canvas[i][j] == 2)
     64                 printf("*");   //   输出挡板*
     65             else if (canvas[i][j] == 3)
     66                 printf("#");   //   输出砖块#
     67         }
     68         printf("|\n"); // 显示右边界
     69     }
     70     for (j = 0;j < Width;j++)
     71         printf("-"); // 显示下边界
     72     printf("\n");
     73 }
     74 
     75 void updateWithoutInput()  // 与用户输入无关的更新
     76 {
     77     if (ball_x == High - 2)
     78     {
     79         if ((ball_y >= left) && (ball_y <= right))   // 被挡板挡住
     80         {
     81         }
     82         else    // 没有被挡板挡住
     83         {
     84             printf("游戏失败\n");
     85             system("pause");
     86             exit(0);
     87         }
     88     }
     89 
     90     static int speed = 0;
     91     if (speed < 7)
     92         speed++;
     93     if (speed == 7)
     94     {
     95         speed = 0;
     96 
     97         canvas[ball_x][ball_y] = 0;
     98         // 更新小球坐标
     99         ball_x = ball_x + ball_vx;
    100         ball_y = ball_y + ball_vy;
    101         canvas[ball_x][ball_y] = 1;
    102 
    103         // 碰到边界后反弹        
    104         if ((ball_x == 0) || (ball_x == High - 2))
    105             ball_vx = -ball_vx;
    106         if ((ball_y == 0) || (ball_y == Width - 1))
    107             ball_vy = -ball_vy;
    108 
    109         // 碰到砖块后反弹
    110         if (canvas[ball_x - 1][ball_y] == 3)
    111         {
    112             ball_vx = -ball_vx;
    113             canvas[ball_x - 1][ball_y] = 0;
    114             printf("\a");
    115         }
    116     }
    117 }
    118 
    119 void updateWithInput()  // 与用户输入有关的更新
    120 {
    121     char input;
    122     if (kbhit())  // 判断是否有输入
    123     {
    124         input = getch();  // 根据用户的不同输入来移动,不必输入回车
    125         if (input == 'a' && left > 0)
    126         {
    127             canvas[position_x][right] = 0;
    128             position_y--;  // 位置左移
    129             left = position_y - ridus;
    130             right = position_y + ridus;
    131             canvas[position_x][left] = 2;
    132         }
    133         if (input == 'd' && right < Width - 1)
    134         {
    135             canvas[position_x][left] = 0;
    136             position_y++;  // 位置右移
    137             left = position_y - ridus;
    138             right = position_y + ridus;
    139             canvas[position_x][right] = 2;
    140         }
    141     }
    142 }
    143 
    144 int main()
    145 {
    146     startup();  // 数据初始化    
    147     while (1)  //  游戏循环执行
    148     {
    149         show();  // 显示画面
    150         updateWithoutInput();  // 与用户输入无关的更新
    151         updateWithInput();     // 与用户输入有关的更新
    152     }
    153     return 0;
    154 }
    3.2消砖块

        3.3空战游戏

      1 #pragma warning(disable:4996);
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <conio.h>
      5 #include <windows.h>
      6 
      7 #define High 15  // 游戏画面尺寸
      8 #define Width 25
      9 #define EnemyNum 5 // 敌机个数
     10 
     11 // 全局变量
     12 int position_x, position_y; // 飞机位置
     13 int enemy_x[EnemyNum], enemy_y[EnemyNum];  // 敌机位置
     14 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
     15                         // 0为空格,1为飞机*,2为子弹|,3为敌机@
     16 int score; // 得分
     17 int BulletWidth; // 子弹宽度
     18 int EnemyMoveSpeed; // 敌机移动速度
     19 
     20 void gotoxy(int x, int y)  //光标移动到(x,y)位置
     21 {
     22     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
     23     COORD pos;
     24     pos.X = x;
     25     pos.Y = y;
     26     SetConsoleCursorPosition(handle, pos);
     27 }
     28 
     29 void startup() // 数据初始化
     30 {
     31     position_x = High - 1;
     32     position_y = Width / 2;
     33     canvas[position_x][position_y] = 1;
     34     int k;
     35     for (k = 0;k < EnemyNum;k++)
     36     {
     37         enemy_x[k] = rand() % 2;
     38         enemy_y[k] = rand() % Width;
     39         canvas[enemy_x[k]][enemy_y[k]] = 3;
     40     }
     41     score = 0;
     42     BulletWidth = 0;
     43     EnemyMoveSpeed = 20;
     44 }
     45 
     46 void show()  // 显示画面
     47 {
     48     gotoxy(0, 0);  // 光标移动到原点位置,以下重画清屏
     49     int i, j;
     50     for (i = 0;i < High;i++)
     51     {
     52         for (j = 0;j < Width;j++)
     53         {
     54             if (canvas[i][j] == 0)
     55                 printf(" ");   //   输出空格
     56             else if (canvas[i][j] == 1)
     57                 printf("*");   //   输出飞机*
     58             else if (canvas[i][j] == 2)
     59                 printf("|");   //   输出子弹|
     60             else if (canvas[i][j] == 3)
     61                 printf("@");   //  输出飞机@
     62         }
     63         printf("\n");
     64     }
     65     printf("得分:%d\n", score);
     66     Sleep(20);
     67 }
     68 
     69 void updateWithoutInput()  // 与用户输入无关的更新
     70 {
     71     int i, j, k;
     72     for (i = 0;i < High;i++)
     73     {
     74         for (j = 0;j < Width;j++)
     75         {
     76             if (canvas[i][j] == 2)
     77             {
     78                 for (k = 0;k < EnemyNum;k++)
     79                 {
     80                     if ((i == enemy_x[k]) && (j == enemy_y[k]))  // 子弹击中敌机
     81                     {
     82                         score++;                // 分数加1
     83                         if (score % 5 == 0 && EnemyMoveSpeed > 3)   // 达到一定积分后,敌机变快
     84                             EnemyMoveSpeed--;
     85                         if (score % 5 == 0)   // 达到一定积分后,子弹变厉害
     86                             BulletWidth++;
     87                         canvas[enemy_x[k]][enemy_y[k]] = 0;
     88                         enemy_x[k] = rand() % 2;           // 产生新的飞机
     89                         enemy_y[k] = rand() % Width;
     90                         canvas[enemy_x[k]][enemy_y[k]] = 3;
     91                         canvas[i][j] = 0;      // 子弹消失
     92                     }
     93                 }
     94                 // 子弹向上移动
     95                 canvas[i][j] = 0;
     96                 if (i > 0)
     97                     canvas[i - 1][j] = 2;
     98             }
     99         }
    100     }
    101 
    102     static int speed = 0;
    103     if (speed < EnemyMoveSpeed)
    104         speed++;
    105 
    106     for (k = 0;k < EnemyNum;k++)
    107     {
    108         if ((position_x == enemy_x[k]) && (position_y == enemy_y[k]))  // 敌机撞到我机
    109         {
    110             printf("失败!\n");
    111             Sleep(3000);
    112             system("pause");
    113             exit(0);
    114         }
    115 
    116         if (enemy_x[k] > High)   // 敌机跑出显示屏幕
    117         {
    118             canvas[enemy_x[k]][enemy_y[k]] = 0;
    119             enemy_x[k] = rand() % 2;           // 产生新的飞机
    120             enemy_y[k] = rand() % Width;
    121             canvas[enemy_x[k]][enemy_y[k]] = 3;
    122             score--;  // 减分
    123         }
    124 
    125         if (speed == EnemyMoveSpeed)
    126         {
    127             // 敌机下落
    128             for (k = 0;k < EnemyNum;k++)
    129             {
    130                 canvas[enemy_x[k]][enemy_y[k]] = 0;
    131                 enemy_x[k]++;
    132                 speed = 0;
    133                 canvas[enemy_x[k]][enemy_y[k]] = 3;
    134             }
    135         }
    136     }
    137 }
    138 
    139 void updateWithInput()  // 与用户输入有关的更新
    140 {
    141     char input;
    142     if (kbhit())  // 判断是否有输入
    143     {
    144         input = getch();  // 根据用户的不同输入来移动,不必输入回车
    145         if (input == 'a' && position_y > 0)
    146         {
    147             canvas[position_x][position_y] = 0;
    148             position_y--;  // 位置左移
    149             canvas[position_x][position_y] = 1;
    150         }
    151         else if (input == 'd' && position_y < Width - 1)
    152         {
    153             canvas[position_x][position_y] = 0;
    154             position_y++;  // 位置右移
    155             canvas[position_x][position_y] = 1;
    156         }
    157         else if (input == 'w')
    158         {
    159             canvas[position_x][position_y] = 0;
    160             position_x--;  // 位置上移
    161             canvas[position_x][position_y] = 1;
    162         }
    163         else if (input == 's')
    164         {
    165             canvas[position_x][position_y] = 0;
    166             position_x++;  // 位置下移
    167             canvas[position_x][position_y] = 1;
    168         }
    169         else if (input == ' ')  // 发射子弹
    170         {
    171             int left = position_y - BulletWidth;
    172             int right = position_y + BulletWidth;
    173             if (left < 0)
    174                 left = 0;
    175             if (right > Width - 1)
    176                 right = Width - 1;
    177             int k;
    178             for (k = left;k <= right;k++) // 发射闪弹
    179                 canvas[position_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
    180         }
    181     }
    182 }
    183 
    184 int main()
    185 {
    186     startup();  // 数据初始化    
    187     while (1) //  游戏循环执行
    188     {
    189         show();  // 显示画面
    190         updateWithoutInput();  // 与用户输入无关的更新
    191         updateWithInput();  // 与用户输入有关的更新
    192     }
    193     return 0;
    194 }
    3.3空战游戏

        3.4贪吃蛇

      1 #pragma warning(disable:4996);
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <conio.h>
      5 #include <windows.h>
      6 
      7 #define High 20  // 游戏画面尺寸
      8 #define Width 30
      9 
     10 // 全局变量
     11 int moveDirection; // 小蛇移动位置,上下左右分别用1,2,3,4表示
     12 int food_x, food_y; // 食物的位置
     13 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
     14     // 0为空格0,-1为边框#,-2为食物F,1为蛇头@,大于1的正数为蛇身*
     15 
     16 void gotoxy(int x, int y)  //光标移动到(x,y)位置
     17 {
     18     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
     19     COORD pos;
     20     pos.X = x;
     21     pos.Y = y;
     22     SetConsoleCursorPosition(handle, pos);
     23 }
     24 
     25 // 移动小蛇
     26 // 第一步扫描数组canvas所有元素,找到正数元素都+1
     27 // 找到最大元素(即蛇尾巴),把其变为0
     28 // 找到=2的元素(即蛇头),再根据输出的上下左右方向,把对应的另一个像素值设为1(新蛇头)
     29 void moveSnakeByDirection()
     30 {
     31     int i, j;
     32     for (i = 1;i < High - 1;i++)
     33         for (j = 1;j < Width - 1;j++)
     34             if (canvas[i][j] > 0)
     35                 canvas[i][j]++;
     36 
     37     int oldTail_i, oldTail_j, oldHead_i, oldHead_j;
     38     int max = 0;
     39 
     40     for (i = 1;i < High - 1;i++)
     41         for (j = 1;j < Width - 1;j++)
     42             if (canvas[i][j] > 0)
     43             {
     44                 if (max < canvas[i][j])
     45                 {
     46                     max = canvas[i][j];
     47                     oldTail_i = i;
     48                     oldTail_j = j;
     49                 }
     50                 if (canvas[i][j] == 2)
     51                 {
     52                     oldHead_i = i;
     53                     oldHead_j = j;
     54                 }
     55             }
     56 
     57     int newHead_i, newHead_j;
     58 
     59     if (moveDirection == 1) // 向上移动
     60     {
     61         newHead_i = oldHead_i - 1;
     62         newHead_j = oldHead_j;
     63     }
     64     if (moveDirection == 2) // 向下移动
     65     {
     66         newHead_i = oldHead_i + 1;
     67         newHead_j = oldHead_j;
     68     }
     69     if (moveDirection == 3) // 向左移动
     70     {
     71         newHead_i = oldHead_i;
     72         newHead_j = oldHead_j - 1;
     73     }
     74     if (moveDirection == 4) // 向右移动
     75     {
     76         newHead_i = oldHead_i;
     77         newHead_j = oldHead_j + 1;
     78     }
     79 
     80     // 新蛇头如果吃到食物
     81     if (canvas[newHead_i][newHead_j] == -2)
     82     {
     83         canvas[food_x][food_y] = 0;
     84         // 产生一个新的食物
     85         food_x = rand() % (High - 5) + 2;
     86         food_y = rand() % (Width - 5) + 2;
     87         canvas[food_x][food_y] = -2;
     88 
     89         // 原来的旧蛇尾留着,长度自动+1
     90     }
     91     else // 否则,原来的旧蛇尾减掉,保持长度不变
     92         canvas[oldTail_i][oldTail_j] = 0;
     93 
     94     // 是否小蛇和自身撞,或者和边框撞,游戏失败
     95     if (canvas[newHead_i][newHead_j] > 0 || canvas[newHead_i][newHead_j] == -1)
     96     {
     97         printf("游戏失败!\n");
     98         Sleep(2000);
     99         system("pause");
    100         exit(0);
    101     }
    102     else
    103         canvas[newHead_i][newHead_j] = 1;
    104 }
    105 
    106 void startup() // 数据初始化
    107 {
    108     int i, j;
    109 
    110     // 初始化边框
    111     for (i = 0;i < High;i++)
    112     {
    113         canvas[i][0] = -1;
    114         canvas[i][Width - 1] = -1;
    115     }
    116     for (j = 0;j < Width;j++)
    117     {
    118         canvas[0][j] = -1;
    119         canvas[High - 1][j] = -1;
    120     }
    121 
    122     // 初始化蛇头位置
    123     canvas[High / 2][Width / 2] = 1;
    124     // 初始化蛇身,画布中元素值分别为2,3,4,5....
    125     for (i = 1;i <= 4;i++)
    126         canvas[High / 2][Width / 2 - i] = i + 1;
    127 
    128     // 初始小蛇向右移动
    129     moveDirection = 4;
    130 
    131     food_x = rand() % (High - 5) + 2;
    132     food_y = rand() % (Width - 5) + 2;
    133     canvas[food_x][food_y] = -2;
    134 }
    135 
    136 void show()  // 显示画面
    137 {
    138     gotoxy(0, 0);  // 光标移动到原点位置,以下重画清屏
    139     int i, j;
    140     for (i = 0;i < High;i++)
    141     {
    142         for (j = 0;j < Width;j++)
    143         {
    144             if (canvas[i][j] == 0)
    145                 printf(" ");   //   输出空格
    146             else if (canvas[i][j] == -1)
    147                 printf("#");   //   输出边框#
    148             else if (canvas[i][j] == 1)
    149                 printf("@");   //   输出蛇头@
    150             else if (canvas[i][j] > 1)
    151                 printf("*");   //   输出蛇身*
    152             else if (canvas[i][j] == -2)
    153                 printf("F");   //   输出食物F
    154         }
    155         printf("\n");
    156     }
    157     Sleep(100);
    158 }
    159 
    160 void updateWithoutInput()  // 与用户输入无关的更新
    161 {
    162     moveSnakeByDirection();
    163 }
    164 
    165 void updateWithInput()  // 与用户输入有关的更新
    166 {
    167     char input;
    168     if (kbhit())  // 判断是否有输入
    169     {
    170         input = getch();  // 根据用户的不同输入来移动,不必输入回车
    171         if (input == 'a')
    172         {
    173             moveDirection = 3;   // 位置左移
    174             moveSnakeByDirection();
    175         }
    176         else if (input == 'd')
    177         {
    178             moveDirection = 4;  // 位置右移
    179             moveSnakeByDirection();
    180         }
    181         else if (input == 'w')
    182         {
    183             moveDirection = 1;  // 位置上移
    184             moveSnakeByDirection();
    185         }
    186         else if (input == 's')
    187         {
    188             moveDirection = 2;   // 位置下移
    189             moveSnakeByDirection();
    190         }
    191     }
    192 }
    193 
    194 int main()
    195 {
    196     startup();  // 数据初始化    
    197     while (1) //  游戏循环执行
    198     {
    199         show();  // 显示画面
    200         updateWithoutInput();  // 与用户输入无关的更新
    201         updateWithInput();  // 与用户输入有关的更新
    202     }
    203     return 0;
    204 }
    贪吃蛇

      第四章 

        4.2多球反弹

      1 #pragma warning(disable:4996);
      2 
      3 #include <graphics.h>
      4 #include <conio.h>
      5 #include <math.h>
      6 #define High 480  // 游戏画面尺寸
      7 #define Width 640
      8 #define BallNum 15 // 小球个数
      9 
     10 int main()
     11 {
     12     float ball_x[BallNum], ball_y[BallNum]; // 小球的坐标
     13     float ball_vx[BallNum], ball_vy[BallNum]; // 小球的速度
     14     float radius;  // 小球的半径
     15     int i, j;
     16 
     17     radius = 20;
     18 
     19     for (i = 0;i < BallNum;i++) // 随机小球的位置与速度
     20     {
     21         ball_x[i] = rand() % int(Width - 4 * radius) + 2 * radius;
     22         ball_y[i] = rand() % int(High - 4 * radius) + 2 * radius;
     23         ball_vx[i] = (rand() % 2) * 2 - 1;
     24         ball_vy[i] = (rand() % 2) * 2 - 1;
     25     }
     26 
     27     initgraph(Width, High);
     28     BeginBatchDraw();
     29 
     30     while (1)
     31     {
     32         // 绘制黑线、黑色填充的圆
     33         setcolor(BLACK);
     34         setfillcolor(BLACK);
     35         for (i = 0;i < BallNum;i++)
     36             fillcircle(ball_x[i], ball_y[i], radius);
     37 
     38         // 更新小圆坐标
     39         for (i = 0;i < BallNum;i++)
     40         {
     41             ball_x[i] = ball_x[i] + ball_vx[i];
     42             ball_y[i] = ball_y[i] + ball_vy[i];
     43 
     44             // 把超出边界的小球拉回来
     45             if (ball_x[i] < radius)
     46                 ball_x[i] = radius;
     47             if (ball_y[i] < radius)
     48                 ball_y[i] = radius;
     49             if (ball_x[i] > Width - radius)
     50                 ball_x[i] = Width - radius;
     51             if (ball_y[i] > High - radius)
     52                 ball_y[i] = High - radius;
     53         }
     54 
     55         // 判断是否和墙壁碰撞
     56         for (i = 0;i < BallNum;i++)
     57         {
     58             if ((ball_x[i] <= radius) || (ball_x[i] >= Width - radius))
     59                 ball_vx[i] = -ball_vx[i];
     60             if ((ball_y[i] <= radius) || (ball_y[i] >= High - radius))
     61                 ball_vy[i] = -ball_vy[i];
     62         }
     63 
     64         float minDistances2[BallNum][2]; // 记录某个小球,距离它最近的小球的距离,这个小球的下标
     65         for (i = 0;i < BallNum;i++)
     66         {
     67             minDistances2[i][0] = 9999999;
     68             minDistances2[i][1] = -1;
     69         }
     70 
     71         // 求解所有小球两两之间的距离平方
     72         for (i = 0;i < BallNum;i++)
     73         {
     74             for (j = 0;j < BallNum;j++)
     75             {
     76                 if (i != j) // 自己和自己不需要比
     77                 {
     78                     float dist2;
     79                     dist2 = (ball_x[i] - ball_x[j]) * (ball_x[i] - ball_x[j])
     80                         + (ball_y[i] - ball_y[j]) * (ball_y[i] - ball_y[j]);
     81                     if (dist2 < minDistances2[i][0])
     82                     {
     83                         minDistances2[i][0] = dist2;
     84                         minDistances2[i][1] = j;
     85                     }
     86                 }
     87             }
     88         }
     89 
     90         // 判断球之间是否碰撞
     91         for (i = 0;i < BallNum;i++)
     92         {
     93             if (minDistances2[i][0] <= 4 * radius * radius) // 最小距离小于阈值,发生碰撞
     94             {
     95                 j = minDistances2[i][1];
     96                 // 交换速度                
     97                 int temp;
     98                 temp = ball_vx[i]; ball_vx[i] = ball_vx[j]; ball_vx[j] = temp;
     99                 temp = ball_vy[i]; ball_vy[i] = ball_vy[j]; ball_vy[j] = temp;
    100 
    101                 minDistances2[j][0] = 999999999; // 避免交换两次速度,又回去了
    102                 minDistances2[j][1] = -1;
    103             }
    104         }
    105 
    106         // 绘制黄线、绿色填充的圆
    107         setcolor(YELLOW);
    108         setfillcolor(GREEN);
    109         for (i = 0;i < BallNum;i++)
    110             fillcircle(ball_x[i], ball_y[i], radius);
    111 
    112         FlushBatchDraw();
    113 
    114         // 延时
    115         Sleep(3);
    116     }
    117     EndBatchDraw();
    118     closegraph();
    119     return 0;
    120 }
    4.2多球反弹

        4.3实时钟表

      1 #pragma warning(disable:4996);
      2 
      3 #include <graphics.h>
      4 #include <conio.h>
      5 #include <math.h>
      6 
      7 #define High 480  // 游戏画面尺寸
      8 #define Width 640
      9 #define    PI    3.14159
     10 
     11 int main()
     12 {
     13     initgraph(Width, High);        // 初始化 640 x 480 的绘图窗口    
     14     int center_x, center_y;      // 中心点的坐标,也是表的中心
     15     center_x = Width / 2;
     16     center_y = High / 2;
     17     int secondLength = Width / 5;           // 秒针的长度
     18     int minuteLength = Width / 6;           // 分针的长度
     19     int hourLength = Width / 7;             // 时针的长度
     20 
     21     int secondEnd_x, secondEnd_y;    // 秒针的终点
     22     int minuteEnd_x, minuteEnd_y;    // 分针的终点
     23     int hourEnd_x, hourEnd_y;    // 时针的终点
     24     float secondAngle;       // 秒钟对应的角度
     25     float minuteAngle;       // 分钟对应的角度
     26     float hourAngle;         // 时钟对应的角度
     27 
     28     SYSTEMTIME ti;                // 定义变量保存当前时间
     29 
     30     BeginBatchDraw();
     31     while (1)
     32     {
     33         // 绘制一个简单的表盘
     34         setlinestyle(PS_SOLID, 1);
     35         setcolor(WHITE);
     36         circle(center_x, center_y, Width / 4);
     37 
     38         // 画刻度
     39         int x, y, i;
     40         for (i = 0; i < 60; i++)
     41         {
     42             x = center_x + int(Width / 4.3 * sin(PI * 2 * i / 60));
     43             y = center_y + int(Width / 4.3 * cos(PI * 2 * i / 60));
     44 
     45             if (i % 15 == 0)
     46                 bar(x - 5, y - 5, x + 5, y + 5);
     47             else if (i % 5 == 0)
     48                 circle(x, y, 3);
     49             else
     50                 putpixel(x, y, WHITE);
     51         }
     52 
     53         outtextxy(center_x - 25, center_y + Width / 6, "我的时钟");
     54 
     55         GetLocalTime(&ti);        // 获取当前时间
     56         // 秒钟角度变化
     57         secondAngle = ti.wSecond * 2 * PI / 60;  // 一圈一共2*PI,一圈60秒,一秒钟秒钟走过的角度为2*PI/60
     58         // 分钟角度变化
     59         minuteAngle = ti.wMinute * 2 * PI / 60 + secondAngle / 60;  // 一圈一共2*PI,一圈60分,一分钟分钟走过的角度为2*PI/60
     60         // 时钟角度变化
     61         hourAngle = ti.wHour * 2 * PI / 12 + minuteAngle / 12;  // 一圈一共2*PI,一圈12小时,一小时时钟走过的角度为2*PI/12        
     62         // 由角度决定的秒针端点坐标
     63         secondEnd_x = center_x + secondLength * sin(secondAngle);
     64         secondEnd_y = center_y - secondLength * cos(secondAngle);
     65 
     66         // 由角度决定的分针端点坐标
     67         minuteEnd_x = center_x + minuteLength * sin(minuteAngle);
     68         minuteEnd_y = center_y - minuteLength * cos(minuteAngle);
     69 
     70         // 由角度决定的时针端点坐标
     71         hourEnd_x = center_x + hourLength * sin(hourAngle);
     72         hourEnd_y = center_y - hourLength * cos(hourAngle);
     73 
     74         setlinestyle(PS_SOLID, 2);
     75         setcolor(YELLOW);
     76         line(center_x, center_y, secondEnd_x, secondEnd_y); // 画秒针
     77 
     78         setlinestyle(PS_SOLID, 5);
     79         setcolor(BLUE);
     80         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 画分针
     81 
     82         setlinestyle(PS_SOLID, 10);
     83         setcolor(RED);
     84         line(center_x, center_y, hourEnd_x, hourEnd_y); // 画时针
     85 
     86         FlushBatchDraw();
     87         Sleep(10);
     88 
     89         setcolor(BLACK);
     90         setlinestyle(PS_SOLID, 2);
     91         line(center_x, center_y, secondEnd_x, secondEnd_y);  // 隐藏前一帧的秒针
     92         setlinestyle(PS_SOLID, 5);
     93         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 隐藏前一帧的分针
     94         setlinestyle(PS_SOLID, 10);
     95         line(center_x, center_y, hourEnd_x, hourEnd_y); // 隐藏前一帧的时针
     96     }
     97 
     98     EndBatchDraw();
     99     getch();                // 按任意键继续    
    100     closegraph();            // 关闭绘图窗口
    101     return 0;
    102 }
    4.3实时时钟

        4.4Easy实现消砖块

      1 #pragma warning(disable:4996);
      2 
      3 #include <conio.h>
      4 #include <graphics.h>
      5 
      6 #define High 480  // 游戏画面尺寸
      7 #define Width 640
      8 #define Brick_num 10 // 砖块个数
      9 
     10 // 全局变量
     11 int ball_x, ball_y; // 小球的坐标
     12 int ball_vx, ball_vy; // 小球的速度
     13 int radius;  // 小球的半径
     14 int bar_x, bar_y; // 挡板中心坐标
     15 int bar_high, bar_width;  // 挡板的高度和宽度
     16 int bar_left, bar_right, bar_top, bar_bottom; // 挡板的上下左右位置坐标
     17 
     18 int isBrickExisted[Brick_num]; // 每个砖块是否存在,1为存在,0为没有了
     19 int brick_high, brick_width; // 每个砖块的高度和宽度
     20 
     21 void startup()  // 数据初始化
     22 {
     23     ball_x = Width / 2;
     24     ball_y = High / 2;
     25     ball_vx = 1;
     26     ball_vy = 1;
     27     radius = 20;
     28 
     29     bar_high = High / 20;
     30     bar_width = Width / 2;
     31     bar_x = Width / 2;
     32     bar_y = High - bar_high / 2;
     33     bar_left = bar_x - bar_width / 2;
     34     bar_right = bar_x + bar_width / 2;
     35     bar_top = bar_y - bar_high / 2;
     36     bar_bottom = bar_y + bar_high / 2;
     37 
     38     brick_width = Width / Brick_num;
     39     brick_high = High / Brick_num;
     40 
     41     int i;
     42     for (i = 0;i < Brick_num;i++)
     43         isBrickExisted[i] = 1;
     44 
     45     initgraph(Width, High);
     46     BeginBatchDraw();
     47 }
     48 
     49 void clean()  // 消除画面
     50 {
     51     setcolor(BLACK);
     52     setfillcolor(BLACK);
     53     fillcircle(ball_x, ball_y, radius);     // 绘制黑线、黑色填充的圆
     54     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黑线、黑色填充的挡板
     55 
     56     int i, brick_left, brick_right, brick_top, brick_bottom;
     57     for (i = 0;i < Brick_num;i++)
     58     {
     59         brick_left = i * brick_width;
     60         brick_right = brick_left + brick_width;
     61         brick_top = 0;
     62         brick_bottom = brick_high;
     63         if (!isBrickExisted[i])     // 砖块没有了,绘制黑色
     64             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);
     65     }
     66 }
     67 
     68 void show()  // 显示画面
     69 {
     70     setcolor(YELLOW);
     71     setfillcolor(GREEN);
     72     fillcircle(ball_x, ball_y, radius);    // 绘制黄线、绿色填充的圆
     73     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黄线、绿色填充的挡板
     74 
     75     int i, brick_left, brick_right, brick_top, brick_bottom;
     76 
     77     for (i = 0;i < Brick_num;i++)
     78     {
     79         brick_left = i * brick_width;
     80         brick_right = brick_left + brick_width;
     81         brick_top = 0;
     82         brick_bottom = brick_high;
     83 
     84         if (isBrickExisted[i])     // 砖块存在,绘制砖块
     85         {
     86             setcolor(WHITE);
     87             setfillcolor(RED);
     88             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);    // 绘制砖块
     89         }
     90     }
     91 
     92     FlushBatchDraw();
     93     // 延时
     94     Sleep(3);
     95 }
     96 
     97 void updateWithoutInput()  // 与用户输入无关的更新
     98 {
     99     // 挡板和小圆碰撞,小圆反弹
    100     if (((ball_y + radius >= bar_top) && (ball_y + radius < bar_bottom - bar_high / 3))
    101         || ((ball_y - radius <= bar_bottom) && (ball_y - radius > bar_top - bar_high / 3)))
    102         if ((ball_x >= bar_left) && (ball_x <= bar_right))
    103             ball_vy = -ball_vy;
    104 
    105     // 更新小圆坐标
    106     ball_x = ball_x + ball_vx;
    107     ball_y = ball_y + ball_vy;
    108 
    109     // 小圆和边界碰撞
    110     if ((ball_x == radius) || (ball_x == Width - radius))
    111         ball_vx = -ball_vx;
    112     if ((ball_y == radius) || (ball_y == High - radius))
    113         ball_vy = -ball_vy;
    114 
    115     // 判断小圆是否和某个砖块碰撞
    116     int i, brick_left, brick_right, brick_bottom;
    117     for (i = 0;i < Brick_num;i++)
    118     {
    119         if (isBrickExisted[i])     // 砖块存在,才判断
    120         {
    121             brick_left = i * brick_width;
    122             brick_right = brick_left + brick_width;
    123             brick_bottom = brick_high;
    124             if ((ball_y == brick_bottom + radius) && (ball_x >= brick_left) && (ball_x <= brick_right))
    125             {
    126                 isBrickExisted[i] = 0;
    127                 ball_vy = -ball_vy;
    128             }
    129         }
    130     }
    131 }
    132 
    133 void updateWithInput()  // 与用户输入有关的更新
    134 {
    135     char input;
    136     if (kbhit())  // 判断是否有输入
    137     {
    138         input = getch();  // 根据用户的不同输入来移动,不必输入回车
    139         if (input == 'a' && bar_left > 0)
    140         {
    141             bar_x = bar_x - 15;  // 位置左移
    142             bar_left = bar_x - bar_width / 2;
    143             bar_right = bar_x + bar_width / 2;
    144         }
    145         if (input == 'd' && bar_right < Width)
    146         {
    147             bar_x = bar_x + 15;  // 位置右移
    148             bar_left = bar_x - bar_width / 2;
    149             bar_right = bar_x + bar_width / 2;
    150         }
    151         if (input == 'w' && bar_top > 0)
    152         {
    153             bar_y = bar_y - 15;  // 位置左移
    154             bar_top = bar_y - bar_high / 2;
    155             bar_bottom = bar_y + bar_high / 2;
    156         }
    157         if (input == 's' && bar_bottom < High)
    158         {
    159             bar_y = bar_y + 15;  // 位置右移
    160             bar_top = bar_y - bar_high / 2;
    161             bar_bottom = bar_y + bar_high / 2;
    162         }
    163     }
    164 }
    165 
    166 void gameover()
    167 {
    168     EndBatchDraw();
    169     closegraph();
    170 }
    171 
    172 int main()
    173 {
    174     startup();  // 数据初始化    
    175     while (1)  //  游戏循环执行
    176     {
    177         clean();  // 把之前绘制的内容取消
    178         updateWithoutInput();  // 与用户输入无关的更新
    179         updateWithInput();     // 与用户输入有关的更新
    180         show();  // 显示新画面
    181     }
    182     gameover();     // 游戏结束、后续处理
    183     return 0;
    184 }
    4.4反弹球消砖块

     

     4.5鼠标交互的反弹器

      1 #pragma warning(disable:4996);
      2 #include <conio.h>
      3 #include <graphics.h>
      4 
      5 #define High 480  // 游戏画面尺寸
      6 #define Width 640
      7 #define Brick_num 10 // 砖块个数
      8 
      9 // 全局变量
     10 int ball_x, ball_y; // 小球的坐标
     11 int ball_vx, ball_vy; // 小球的速度
     12 int radius;  // 小球的半径
     13 int bar_x, bar_y; // 挡板中心坐标
     14 int bar_high, bar_width;  // 挡板的高度和宽度
     15 int bar_left, bar_right, bar_top, bar_bottom; // 挡板的上下左右位置坐标
     16 
     17 int isBrickExisted[Brick_num]; // 每个砖块是否存在,1为存在,0为没有了
     18 int brick_high, brick_width; // 每个砖块的高度和宽度
     19 
     20 void startup()  // 数据初始化
     21 {
     22     ball_x = Width / 2;
     23     ball_y = High / 2;
     24     ball_vx = 1;
     25     ball_vy = 1;
     26     radius = 20;
     27 
     28     bar_high = High / 20;
     29     bar_width = Width / 2;
     30     bar_x = Width / 2;
     31     bar_y = High - bar_high / 2;
     32     bar_left = bar_x - bar_width / 2;
     33     bar_right = bar_x + bar_width / 2;
     34     bar_top = bar_y - bar_high / 2;
     35     bar_bottom = bar_y + bar_high / 2;
     36 
     37     brick_width = Width / Brick_num;
     38     brick_high = High / Brick_num;
     39 
     40     int i;
     41     for (i = 0;i < Brick_num;i++)
     42         isBrickExisted[i] = 1;
     43 
     44     initgraph(Width, High);
     45     BeginBatchDraw();
     46 }
     47 
     48 void clean()  // 消除画面
     49 {
     50     setcolor(BLACK);
     51     setfillcolor(BLACK);
     52     fillcircle(ball_x, ball_y, radius);     // 绘制黑线、黑色填充的圆
     53     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黑线、黑色填充的挡板
     54 
     55     int i, brick_left, brick_right, brick_top, brick_bottom;
     56     for (i = 0;i < Brick_num;i++)
     57     {
     58         brick_left = i * brick_width;
     59         brick_right = brick_left + brick_width;
     60         brick_top = 0;
     61         brick_bottom = brick_high;
     62         if (!isBrickExisted[i])     // 砖块没有了,绘制黑色
     63             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);
     64     }
     65 }
     66 
     67 void show()  // 显示画面
     68 {
     69     setcolor(YELLOW);
     70     setfillcolor(GREEN);
     71     fillcircle(ball_x, ball_y, radius);    // 绘制黄线、绿色填充的圆
     72     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黄线、绿色填充的挡板
     73 
     74     int i, brick_left, brick_right, brick_top, brick_bottom;
     75 
     76     for (i = 0;i < Brick_num;i++)
     77     {
     78         brick_left = i * brick_width;
     79         brick_right = brick_left + brick_width;
     80         brick_top = 0;
     81         brick_bottom = brick_high;
     82 
     83         if (isBrickExisted[i])     // 砖块存在,绘制砖块
     84         {
     85             setcolor(WHITE);
     86             setfillcolor(RED);
     87             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);    // 绘制砖块
     88         }
     89     }
     90 
     91     FlushBatchDraw();
     92     // 延时
     93     Sleep(3);
     94 }
     95 
     96 void updateWithoutInput()  // 与用户输入无关的更新
     97 {
     98     // 挡板和小圆碰撞,小圆反弹
     99     if (((ball_y + radius >= bar_top) && (ball_y + radius < bar_bottom - bar_high / 3))
    100         || ((ball_y - radius <= bar_bottom) && (ball_y - radius > bar_top - bar_high / 3)))
    101         if ((ball_x >= bar_left) && (ball_x <= bar_right))
    102             ball_vy = -ball_vy;
    103 
    104     // 更新小圆坐标
    105     ball_x = ball_x + ball_vx;
    106     ball_y = ball_y + ball_vy;
    107 
    108     // 小圆和边界碰撞
    109     if ((ball_x == radius) || (ball_x == Width - radius))
    110         ball_vx = -ball_vx;
    111     if ((ball_y == radius) || (ball_y == High - radius))
    112         ball_vy = -ball_vy;
    113 
    114     // 判断小圆是否和某个砖块碰撞
    115     int i, brick_left, brick_right, brick_bottom;
    116     for (i = 0;i < Brick_num;i++)
    117     {
    118         if (isBrickExisted[i])     // 砖块存在,才判断
    119         {
    120             brick_left = i * brick_width;
    121             brick_right = brick_left + brick_width;
    122             brick_bottom = brick_high;
    123             if ((ball_y == brick_bottom + radius) && (ball_x >= brick_left) && (ball_x <= brick_right))
    124             {
    125                 isBrickExisted[i] = 0;
    126                 ball_vy = -ball_vy;
    127             }
    128         }
    129     }
    130 }
    131 
    132 void updateWithInput()  // 与用户输入有关的更新
    133 {
    134     MOUSEMSG m;        // 定义鼠标消息
    135     if (MouseHit())  //这个函数用于检测当前是否有鼠标消息
    136     {
    137         m = GetMouseMsg();      // 获取一条鼠标消息
    138         if (m.uMsg == WM_MOUSEMOVE)
    139         {
    140             // 鼠标移动时,挡板的位置等于鼠标所在的位置
    141             bar_x = m.x;
    142             bar_y = m.y;
    143             bar_left = bar_x - bar_width / 2;
    144             bar_right = bar_x + bar_width / 2;
    145             bar_top = bar_y - bar_high / 2;
    146             bar_bottom = bar_y + bar_high / 2;
    147         }
    148         else if (m.uMsg == WM_LBUTTONDOWN)
    149         {
    150             // 按下鼠标左键,初始化小球的位置为挡板上面中心
    151             ball_x = bar_x;
    152             ball_y = bar_top - radius - 3;
    153         }
    154     }
    155 }
    156 
    157 void gameover()
    158 {
    159     EndBatchDraw();
    160     closegraph();
    161 }
    162 
    163 int main()
    164 {
    165     startup();  // 数据初始化    
    166     while (1)  //  游戏循环执行
    167     {
    168         clean();  // 把之前绘制的内容取消
    169         updateWithoutInput();  // 与用户输入无关的更新
    170         updateWithInput();     // 与用户输入有关的更新
    171         show();  // 显示新画面
    172     }
    173     gameover();     // 游戏结束、后续处理
    174     return 0;
    175 }
    鼠标交互的反弹器
  • 相关阅读:
    代码走读 airflow 2
    sql 查询相关
    控制你的鼠标和键盘
    TODO
    二进制流的操作收集
    daterangepicker-双日历
    datetimepicker使用
    ADO执行事务
    动态添加表sql
    执行带返回值的存储过程
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/15600334.html
Copyright © 2020-2023  润新知