引言
弹球游戏是一种经典的休闲游戏,它的玩法是控制一个挡板来反弹一个小球,使其打破所有的砖块,同时避免小球掉落。
知识回顾:
C语言图形编辑第一步:画一个圆 C语言图形编辑第二步:画线、画点、画长方形! 做一个简单的C语言绘制弹球游戏:第一步,让小球运动起来! C语言知识分享:使用easy X编写一个小球弹跳的动画,简单又易懂! |
经过前面的基础知识努力,本节课就来实现一个弹球的游戏创建
分析它的主要功能和实现方法,以及遇到的一些问题和解决方案。easy X 软件是一个针对 Visual C 的免费绘图库,它支持 VC6.0 ~ VC2022,简单易用,学习成本极低,应用领域广泛。它提供了一些简单的函数集合,可以方便地绘制各种图形和文字,以及处理键盘和鼠标的输入。它还支持静态编译,不依赖任何 dll,可以轻松地发布程序。
程序设计
程序结构
主要结构如下:
1、定义了一些常量和变量,用于表示窗口的大小、小球的半径、挡板的位置和大小、小球的速度和位置、分数等。
2、定义了一个 pause 函数,用于暂停游戏,当用户按下 C 键时继续。
3、定义了一个 main 函数,用于初始化图形窗口,绘制右侧的墙和提示信息,以及实现游戏的主循环。
4、在游戏的主循环中,根据小球的速度和位置更新小球的位置,绘制小球和挡板,显示分数,检测小球和挡板、墙壁、砖块的碰撞,处理用户的按键输入,判断游戏的结束条件,以及重置游戏的状态。
程序流程图
本程序的主要流程如下图所示:
程序实现
初始化图形窗口
使用了initgraph 函数来创建一个 640x480 像素的图形窗口:
initgraph(WIDTH, HIGH);
其中,WIDTH 和 HIGH 是两个常量,分别表示窗口的宽度和高度,它们的值分别为 640 和 480。
绘制右侧的墙和提示信息
使用了 fillrectangle 函数来绘制一个右侧的墙:
fillrectangle(WIDTH-200,0,WIDTH-195,HIGH);
其中,WIDTH 和 HIGH 是两个常量,分别表示窗口的宽度和高度,它们的值分别为 640 和 480。这样,我们就在窗口的右侧画了一个 5 像素宽的矩形,作为右墙。
使用了 outtextxy 函数来绘制一些提示信息:
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
outtextxy(WIDTH-160, HIGH-250, ("按P暂停 按C继续"));
outtextxy(WIDTH-160, HIGH-270, ("按A向左 按D向右"));
其中,WIDTH 和 HIGH 是两个常量,分别表示窗口的宽度和高度,它们的值分别为 640 和 480。ScoreBuffer 是一个字符数组,用于存储当前的分数,它的初始值为 “当前分数: 0”。这样,我们就在窗口的右下角输出了一些提示信息,告诉用户如何操作游戏。
更新小球的位置
使用了两个变量 x 和 y 来表示小球的圆心坐标,它们的初始值分别为 (WIDTH-200)-200 和 HIGH/2,即窗口的中间偏左的位置。还使用了两个变量 Vx 和 Vy 来表示小球的水平和垂直方向的速度,它们的初始值分别为 3 和 3,即向右下方运动。
本程序使用了如下的公式来更新小球的位置,即:
x = x Vx;
y = y Vy;
这样,每次循环,小球的位置就会根据速度改变一定的距离。
绘制小球和挡板
使用了 fillcircle 函数来绘制一个小球:
fillcircle(x, y, R);
其中,x, y 是两个变量,表示小球的圆心坐标,R 是一个常量,表示小球的半径,它的值为 10。这样,我们就在窗口中画了一个半径为 10 的小球。
使用了四个变量 Board_x1, Board_y1, Board_x2, Board_y2 来表示挡板的位置和大小,它们的初始值分别为 150, HIGH-5, 250, HIGH。
使用了 fillrectangle 函数来绘制一个挡板:
fillrectangle(Board_x1,Board_y1,Board_x2,Board_y2);
其中,Board_x1, Board_y1, Board_x2, Board_y2 是四个变量,表示挡板的位置和大小,它们的初始值分别为 150, HIGH-5, 250, HIGH,即窗口的底部中间位置,挡板的宽度为 100,高度为 5。这样,我们就在窗口的底部画了一个挡板,用于反弹小球。
显示分数
使用了一个变量 score 来表示当前的分数,它的初始值为 0,每次小球和挡板碰撞时,分数加 10。sprintf 函数来将分数转换为字符串,存储在 ScoreBuffer 字符数组中:
sprintf(ScoreBuffer,"%s%d","当前分数: ",score);
这样,我们就将分数和前缀 "当前分数: " 拼接成一个字符串,存储在 ScoreBuffer 中。
outtextxy 函数来显示分数:
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
其中,WIDTH 和 HIGH 是两个常量,分别表示窗口的宽度和高度,它们的值分别为 640 和 480。ScoreBuffer 是一个字符数组,用于存储当前的分数,它的初始值为 “当前分数: 0”。这样,我们就在窗口的右下角显示了当前的分数。
检测小球和挡板、墙壁、砖块的碰撞
使用了一些 if 语句来检测小球和挡板、墙壁、砖块的碰撞,如果发生碰撞,就改变小球的速度方向,实现反弹的效果。具体的判断条件如下:
如果小球的 x 坐标小于等于半径 R 或者大于等于右墙的 x 坐标减去半径 R,说明小球碰到了左墙或者右墙,此时,水平速度 Vx 取反,即:
if(x<=R || x>=WIDTH-203-R)
{
Vx=-Vx;
}
如果小球的 y 坐标小于等于半径 R,说明小球碰到了上边的墙,此时,垂直速度 Vy 取反,即:
if(y<=R)
{
Vy=-Vy;
}
如果小球的 y 坐标大于等于底墙的 y 坐标减去半径 R,说明小球碰到了底墙,此时,需要判断小球的 x 坐标是否在挡板的范围内,如果是,说明小球碰到了挡板,此时,垂直速度 Vy 取反,同时,分数加 10,即:
if(y>=HIGH-R-5)
{
if(x>=Board_x1-R && x<=Board_x2 R) //是否在板子上
{
Vy=-Vy;
//重新计算并显示分数
//clearrectangle(WIDTH-150, HIGH-350,WIDTH-50,HIGH-400);
settextcolor(BLACK);
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
score=score 10;
sprintf(ScoreBuffer,"%s%d","当前分数: ",score);
settextcolor(WHITE);
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
}
}
如果小球的 y 坐标小于等于砖块的 y 坐标加上半径 R,说明小球碰到了砖块,此时,需要判断小球的 x 坐标是否在砖块的范围内,如果是,说明小球碰到了砖块,此时,垂直速度 Vy 取反,同时,砖块消失,分数加 10,即:
if(y<=Brick_y R)
{
if(x>=Brick_x-R && x<=Brick_x Brick_w R) //是否在砖块上
{
Vy=-Vy;
//擦除砖块
setfillcolor(BLACK);
fillrectangle(Brick_x,Brick_y,Brick_x Brick_w,Brick_y Brick_h);
//重新计算并显示分数
//clearrectangle(WIDTH-150, HIGH-350,WIDTH-50,HIGH-400);
settextcolor(BLACK);
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
score=score 10;
sprintf(ScoreBuffer,"%s%d","当前分数: ",score);
settextcolor(WHITE);
outtextxy(WIDTH-150, HIGH-350, ScoreBuffer);
}
}
其中,Brick_x, Brick_y, Brick_w, Brick_h 是四个常量,表示砖块的位置和大小,它们的值分别为 100, 100, 50, 20,即窗口的左上角有一个 50x20 的矩形作为砖块。
处理用户的按键输入
使用了 GetAsyncKeyState 函数来检测用户的按键输入:
if(GetAsyncKeyState(65) & 0x8000) //向左
{
//省略代码
}
if(GetAsyncKeyState(68) & 0x8000) //向右
{
//省略代码
}
if(GetAsyncKeyState(80) & 0x8000)//暂停
{
pause();
}
其中,65, 68, 80 分别表示 A, D, P 键的虚拟键码,我们用它们来控制挡板的左右移动和游戏的暂停。如果用户按下 A 键,挡板向左移动一定的距离,如果用户按下 D 键,挡板向右移动一定的距离,如果用户按下 P 键,游戏暂停,调用 pause 函数,等待用户按下 C 键继续。
判断游戏是否结束
使用了一个 if 语句来判断游戏是否结束,如果小球的 y 坐标大于等于底墙的 y 坐标减去半径 R,且小球的 x 坐标不在挡板的范围内,说明小球掉落,游戏结束,此时,显示游戏结束
显示游戏结束信息
使用了 outtextxy 函数来显示游戏结束信息:
outtextxy(WIDTH-500, HIGH-350, ("游戏结束!Game Over!"));
outtextxy(WIDTH-500, HIGH-330, ("按C继续,按Q退出"));
这样,我们就在窗口的中间显示了游戏结束的信息,告诉用户如何选择继续或退出。
重置游戏的状态
使用了一个 while 循环来等待用户按下 C 或 Q 键,如果用户按下 C 键,就重新开始游戏,如果用户按下 Q 键,就退出程序,该循环的代码如下:
while(1)
{
Sleep(50);
if(GetAsyncKeyState(67) & 0x8000 ) //C
{
//清空提示信息,重新开始
setcolor(BLACK);
outtextxy(WIDTH-500, HIGH-350, ("游戏结束!Game Over!"));
outtextxy(WIDTH-500, HIGH-330, ("按C继续,按Q退出"));
goto Start;
}
if(GetAsyncKeyState(81) & 0x8000 ) //Q
{
break;
}
}
其中,67, 81 分别表示 C, Q 键的虚拟键码,我们用它们来控制游戏的继续或退出。如果用户按下 C 键,我们用 setcolor 和 outtextxy 函数来用黑色覆盖原来的提示信息,然后用 goto 语句跳转到 Start 标签处,重新开始游戏。如果用户按下 Q 键,我们就跳出循环,结束程序。
程序测试
运行结果
本程序运行后,会出现一个 640x480 像素的图形窗口,原文链接里看:
窗口的右侧有一个 5 像素宽的右墙,窗口的底部有一个 100 像素宽的挡板,窗口的左上角有一个 50x20 像素的砖块,窗口的中间偏左有一个半径为 10 像素的小球。窗口的右下角有一些提示信息,显示当前的分数,以及如何操作游戏。
用户可以使用 A 和 D 键来控制挡板的左右移动,使用 P 键来暂停游戏,使用 C 键来继续游戏。小球会根据速度和位置自动运动,如果碰到挡板、墙壁或砖块,就会反弹,如果碰到挡板或砖块,还会增加分数。如果小球掉落,游戏结束,窗口的中间会显示游戏结束的信息,用户可以选择按 C 键继续,或者按 Q 键退出。
觉得有用的话,动动你们的小手,点个赞和转发在看,非常感谢!!!
点赞加关注,学习不迷路
微信公众号|工控小新
EPLAN电气绘图、TIA 、CAD、C语言教学、单片机基础、三菱PLC ... 每日持续更新中
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved