一、项目介绍这是一个弹幕射击类小游戏(究极简化版)。方向键控制移动,按住z键射击,按住shift可以缓速移动,击败敌人取得胜利。游戏C语言实现+easyX图形绘制,视觉交互效果好,趣味性强。 编译环境:visual c++ 6.0第三方库:Easyx2022 二、运行截图




三、源码解析我们先思考游戏的流程。在程序运行的开始,我们自然需要初始化。接着就是游戏的进行过程,当检测到胜负已分时,给出提示,结束游戏。 在游戏过程中,所有的操作都需要得到实时的反馈。只要你输入操作,游戏数据和画面就会即时做出反应。显然我们需要用循环的方式,不断地检测输入,处理游戏数据以及绘制图像。 循环的频率是根据游戏刷新频率确定的,每经过一小段时间,循环就会执行一次,检测玩家在这段时间按下了什么按键,然后判断这些按键引起了移动方向的改变,还是子弹的发射,将这些结果写入到游戏数据当中,最后再刷新画面,计算出下一帧界面应该是什么样子。 然后是程序中定义的函数,变量及其功能。void hp_bar();void show_player();void show_enemy();void move_enemy(); //绘制一系列图像void draw_background();int generate_line(); // 若返回 -1,表示生成线条失败int create_p_b(); // 创建自机的子弹int create_e_b(); // 创建敌机的子弹int destroy_p_b(int index);int destroy_e_b(int index); // 删除一个子弹define FIRERATE 350 // 射击间隔时间define BLEED_TIME 150 // 受伤闪烁时间define MAX_LINES 75 // 最多同屏背景线条数目define MAX_ENEMY_BULLETS 40 // 最多同屏敌机子弹数目 int player_pos[2] = { 30,30 }; // 自机位置xyint enemy_bullet[MAX_ENEMY_BULLETS][2]; // 敌人的子弹位置int player_bullet[MAX_PLAYER_BULLETS][2]; // 自机的子弹位置int enemy_pos[2] = { 580,240 }; // 敌机位置bool p_b_slots[MAX_PLAYER_BULLETS] = { false }; // 用于判断 player_bullet 的某个位置是否可用bool e_b_slots[MAX_ENEMY_BULLETS] = { false };int number_p_b = 0, number_e_b = 0; // 记录自机和敌机的子弹数,减少遍历压力int player_health = 100, enemy_health = 100;bool isBleeding_p = false, isBleeding_e = false; // 用于实现命中后的闪烁效果int background_line[MAX_LINES][3]; // 背景的线条,三个参数分别是 x、y、长度bool line_slots[MAX_LINES] = { false };int number_lines = 0; // 记录背景线条数目clock_t begin_time = 0; 下面是主函数的源码。由于相对来说较长,所以其中的一部分我会用文字来描述,具体的内容会放在完整源码当中int main(){ initgraph(640, 550, 4); srand((unsigned)time(NULL)); settextcolor(RGB(0, 254, 0)); settextstyle(30, 0, "微软雅黑"); outtextxy(50, 200, "方向键移动, Z 攻击, 左 Shift 切换低速模式"); bool win = false, dead = false; clock_t firerate = clock(); // 射击控制 clock_t e_firerate = clock(); // 控制敌机的射击 clock_t runtime = clock(); // 用于控制画面刷新频率 clock_t bleed_p = clock(), bleed_e = clock(); // 用于实现受伤闪烁 clock_t backgroundline_generate = clock(); // 用于生成背景线条 Sleep(3000); BeginBatchDraw(); bool leftshift = false; begin_time = clock(); return 0;}以上是初始化内容。Initgraph()用来初始化绘图区域,settextcolor用来改变字体颜色,outtextxy用于在指定位置输出文字。BeginBatchDraw这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出,这样可以防止画面不同步输出。这几个函数都来自easyx头文件。初始化中还用clock()函数进行计时。Clock()返回值为clock_t类型,获取进程使用的cpu时间单元总数。等到某个时间点再次调用该函数,就能得出从现在到那时,究竟过了多长时间。while (true) { if (clock() - runtime >= FRAMERATE)//只有当距离处理上一帧过去了一定时间,才会开始下一次处理。 { runtime = clock(); cleardevice();//使用当前背景色清空绘图设备。 draw_background();//在本文件中定义,绘制背景 hp_bar();// 画血条 show_player();;//在本文件中定义,绘制玩家 show_enemy();;//在本文件中定义,绘制敌人 int n_p_b = 1, n_e_b = 1; // 计数,遍历子弹,刷新位置 int p_b_toprocess = number_p_b, e_b_toprocess = number_e_b; // 需要处理的子弹数这里number_p_b和number_e_b分别是自机和敌机的子弹数目。为了保证游戏运行正常,可以给双方的同屏弹幕数各设定一个上限,如果当前的子弹超过了上限,则后续的子弹不生成。这一步的意思是让这两个变量继承上一帧的子弹数目。 for (int i = 0; i < MAX_PLAYER_BULLETS && (n_p_b = BLEED_TIME) // 受伤时间结束后关闭受伤闪烁效果 { isBleeding_p = false; } if (clock() - bleed_e >= BLEED_TIME) // 受伤时间结束后关闭受伤闪烁效果 { isBleeding_e = false; } if (clock() - backgroundline_generate >= BACKGROUND) { backgroundline_generate = clock(); generate_line();//间隔一段时间绘制背景线条 } } } if (win) { settextcolor(RGB(0, 254, 0)); settextstyle(35, 0, "void hp_bar();void show_player();void show_enemy();void move_enemy(); void draw_background();首先是五个绘制图像的函数。它们的逻辑结构都是线性的,只需要依次调用函数即可。用到的函数有:setlinecolor用于设置当前设备画线颜色。line用于画直线。setfillcolor用于设置当前设备填充颜色。rectangle用于画无填充的矩形。fillrectangle用于画有边框的填充矩形。以及之前提到的绘制文字的函数等。
请登录后发表评论
注册
停留在世界边缘,与之惜别