基于Easy X图形库的C语言飞机大战 | 路远第一个C语言项目

前言

在B站跟着顽石老师学习了Easy X图形编程及飞机大战游戏,老师讲课非常有趣,十分推荐,唯一缺憾的就是飞机大战的视频是好几年前的并且感觉没有更新完,好多功能没有实现,不过也有好有坏,倒逼着我去自己思考动手实现后面的一些功能,飞机大战视频p8游戏的优化和BUG处理最后将近10分钟老师调试代码处理BUG对于我这个初学者有很大的帮助。由于时间紧张原因并没有完成飞机大战所有功能,剩下的一些细节功能后续有时间会继续改进。
【C/C++/EasyX】学编程,做游戏,小白快速入门图形编程,零基础入门到精通,学习就是这么快乐_哔哩哔哩_bilibili
C语言项目:飞机大战【最全教程】超详细教程带你从 0 开始做出飞机游戏!_哔哩哔哩_bilibili

代码文件和图片音乐资源在我的Gitee的C/C++项目仓库里。
03_02_飞机大战 · 路远Oo/C-C++项目 - 码云 - 开源中国 (gitee.com)

一、前置知识准备

1.Easy X图形库

针对C++的图形库,基于Windows图形编程,将Windows下的复杂程序过程进行封装,将Windows下的编程过程隐藏,给用户提供一个简单熟悉的接口。用户对于图形库中函数的调用,最终都会由Windows的底层API实现。可以用于编写小游戏、图形学、图像学、分形学、粒子系统、物理模拟等各种场景。
通过Easy X提供的函数,可以实现游戏窗口的绘制,并在窗口内进行图形和文字绘制及图像处理,可以通过鼠标消息函数和键盘消息函数对窗口内部的物体进行控制。
EasyX基础入门——这一篇就够啦-CSDN博客

2.图片

2.1图片存储
图片在计算机中由一个个像素点组成,以二进制的方式存储。
在RGB格式中,每个像素点用一个int整型类型表示,共4个字节32位比特位。第一个字节不存储数据用作占位符,剩下的三个字节各对应一个原色(红绿蓝),每一个原色取值范围为0~255。红色RGB(255,0,0),绿色RGB(0,255,0),蓝色RGB(0,0,255);白色RGB(255,255,255),黑色RGB(0,0,0)。
2.2掩码图
掩码是一串二进制代码对目标字段进行位与运算,屏蔽当前的输入位。将源码与掩码经过按位运算或逻辑运算得出新的操作数。
图像的掩码操作是指通过掩码核算子重新计算图像中各个像素的值,掩码核算子刻画邻域像素点对新像素值的影响程度,同时根据掩码算子中权重因子对原像素点进行加权平均。
2.3透明贴图技术
用掩码图和原图做一个颜色的二进制操作。
Easy X使用三元光栅操作实现透明贴图,将源图像与目标图像的像素进行位的逻辑运算(与或非)。
详解透明贴图和三元光栅操作 - CodeBus

二、飞机大战游戏思路

1.窗口制作

根据背景图尺寸利用窗口函数initgraph()绘制默认窗口;设置IMAGE对象,通过loadimage()函数把图片加载进程序,putimage()函数把图片放入指定位置(用来放置背景图片以及游戏所需的飞机子弹等素材的图片)。

initgraph(WIDTH, HEIGHT, SHOWCONSOLE);
//例如
IMAGE bk;//背景图片
loadimage(&bk, "./images/background.jpg");
putimage(0, 0, &bk);

2.数据及参数

创建结构体存储玩家飞机、子弹、敌机的各种属性:坐标点、长度、宽度、是否存活、数量、血量等信息。

struct plane//玩家飞机
{
	int x;
	int y;
	bool live;//是否存活
	int width;
	int height;
	int hp;//血量
	int type;//敌机类型 big small
}player,enemy[ENEMY_NUM];

3.素材载入

用一个2个空间数组定义飞机的图片,(其他素材同理)分别加载飞机的掩码图和原图,就可以在窗口输出无背景的素材图片。

//例如
IMAGE img_role[2];//玩家图片
//加载玩家图片
loadimage(&img_role[0], "./images/planeNormal_1.jpg");//掩码图
loadimage(&img_role[1], "./images/planeNormal_2.jpg");//原图
//绘制玩家飞机 
//透明贴图技术:用掩码图和原图做一个颜色的二进制操作
putimage(player.x, player.y, &img_role[0], NOTSRCERASE);
putimage(player.x, player.y, &img_role[1], SRCINVERT);

4.初始化

根据不同角色设置不同的参数。

//例如
//玩家初始化
player.x = WIDTH / 2;
player.y = HEIGHT - 120;
player.live = true;

5.素材移动

通过键盘操作可以控制玩家飞机移动,子弹自动向上移动和敌机自动向下移动。
第一种方式:_getch()函数
需要头文件conio.h。_getch()是阻塞函数,和scanf一样,没有输入就会卡住主程序等待输入,不是C语言的标准函数。
配合_kbhit()检测是否有键盘按下,加上switch语句添加操控的具体的按键。
第二种方式:GetAsyncKeyState()函数
需要头文件windows.h,但是由于EasyX包含了windows头文件,所以无须自己包含。非阻塞函数,非常流畅。
如果要检测字母按键,必须用大写,这样大小写都可以检测到,小写一个都检测不到;或者使用定义好的宏VK_UP、VK_DOWN、VK_LEFT、VK_RIGHT等。

//例如
//通过获取上键或W键使玩家向上移动
if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))//VK_UP系统定义的宏
{
	if (player.y > 0)//边界处理
	{
		player.y -= speed;
	}
}

6.双缓冲绘图

基于C语言的游戏开发的动态画面往往是不断的刷新显示区来实现的,即不断地输入和清空。画面较大的情况下会有闪屏或不流畅。
Easy X提供BeginBatchDraw函数,这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。以实现批绘图功能,可以消除闪烁。

BeginBatchDraw();
while (1)
{
	//绘制游戏图像的函数
	FlushBatchDraw();
	//游戏实现的代码
}
EndBatchDraw();

7.创造子弹和敌机

使子弹和敌机能够出现在屏幕上,并且不断更新(屏幕里子弹能同时存在的数目为初始化子弹数组中设置的值,敌机同理)。通过循环不断创建。

//例如
//创建子弹
for (int i = 0; i < BULLET_NUM; i++)
{
	if (!bull[i].live)
	{
		bull[i].x = player.x + (PLAN_WIDTH / 2) - (BULLET_WIDTH / 2);
		bull[i].y = player.y;
		bull[i].live = true;
		break;//创建一个跳出
	}
}

8.子弹打飞机

子弹的图片范围触及到敌机的图片范围,敌机HP-1。击落敌机后创造敌机时需要重置HP。玩家击落敌机,根据敌机HP获得分数。

void shootPlane()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			continue;
		}
		for (int j = 0; j < BULLET_NUM; j++)
		{
			if (!bull[j].live)
			{
				continue;
			}
			if (bull[j].x > enemy[i].x && bull[j].x<enemy[i].x + enemy[i].width
				&& bull[j].y>enemy[i].y && bull[j].y < enemy[i].y + enemy[i].height)
			{
				bull[j].live = false;
				enemy[i].hp--;
			}
		}
		if (enemy[i].hp <= 0)
		{
			
			if (enemy[i].type == BIG)
			{
				player.score += BIG_PH;
			}
			else
			{
				player.score +=SMALL_PH;
			}
			enemy[i].live = false;
			
			//printf("%d", player.score);//测试函数
		}
	}
}

9.定时器

封装一个定时器用来控制子弹的射击速度以及敌机的下降速度。

bool Timer(int ms, int id)
{
	static DWORD t[10];
	if (clock() - t[id] > ms)
	{
		t[id] = clock();
		return true;
	}
	return false;
}

10. 玩家被攻击

玩家撞到敌机,玩家HP-1,敌机HP-1。玩家撞毁敌机同样增加分数。代码原理同子弹打飞机相似。玩家血量小于10则游戏结束。

11. 游戏文字信息

在屏幕左上角显示玩家姓名、玩家血量、玩家得分,并实时更新血量值和得分值。

//例如
settextstyle(20, 10, "黑体");//设置字体
settextcolor(BLACK);//设置颜色
setbkmode(NULL);//清空文字背景
outtextxy(0, 0, "玩家姓名:路远");

12. 播放背景音乐

//打开音乐,播放音乐  alias取别名 repeat重复播放
mciSendString(_T("open ./images/game_music.mp3 alias BGM"), NULL, 0, NULL);//播放音乐
mciSendString(_T("play BGM repeat"), NULL, 0, NULL);//循环播放

13. 未实现的功能

没有实现子弹射击、击中敌机、与敌机碰撞等声音,有待完善。

三、飞机大战具体代码

1.game.h

#pragma once
#include <stdio.h>
#include <graphics.h> //图形库,帮助新手快速入门图形编程 easyx
#include <mmsystem.h>//包含多媒体设备接口头文件,一定放在graphics.h下面
#pragma comment(lib,"Winmm.lib")//加载静态库
#include <conio.h>//_getch()的头文件,不是C语言的标准函数
#include <time.h>


enum Size//窗口的高度和宽
{
	//窗口尺寸
	WIDTH = 591,
	HEIGHT = 864,

	//玩家飞机尺寸
	PLAN_WIDTH = 117,
	PLAN_HEIGHT = 120,

	//子弹尺寸
	BULLET_WIDTH = 19,
	BULLET_HEIGHT = 24,
	
	//子弹数目
	BULLET_NUM = 15,

	//敌机数目
	ENEMY_NUM = 10,
	//敌机尺寸
	BIG,
	SMALL,
	BIG_WIDTH = 104,
	BIG_HEIGHT = 148,
	SMALL_WIDTH = 52,
	SMALL_HEIGHT = 39,
	//敌机血量
	BIG_PH = 3,
	SMALL_PH = 1
};

#define PLAYER_SPEED 1 //玩家移动速度
#define ENEMY_SPEED 1//敌机移动速度
#define BULLET_SPEED 2//子弹移动速度



//加载图片函数
void loadImg();

//游戏图片的绘制函数
void gameDraw();

//玩家飞机初始化  子弹初始化
void gameInit();

//角色移动,获取键盘消息  子弹移动
void playerMove(int speed);

//创建子弹
void creatBullet();

//子弹移动
void bulletMove(int speed);

//设置敌机
void enemyHp(int i);

//创造敌机
void creatEnemy();

//敌机移动
void enemyMove(int speed);

//封装定时器
bool Timer(int ms, int id);

//打飞机
void shootPlane();

//玩家被攻击
void Attacked();

//游戏文字信息
void textDraw();

//播放背景音乐
void BGM();

2.game.cpp

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"


//把图片加载进程序
IMAGE bk;//背景图片
IMAGE img_role[2];//玩家图片
IMAGE img_bullet[2];//子弹图片
IMAGE img_enemy[2][2];//敌机图片
IMAGE img_dieplane[2];//玩家飞机死亡图片



void loadImg()
{
	//加载背景图片 591 * 864
	loadimage(&bk, "./images/background.jpg");

	//加载玩家图片
	loadimage(&img_role[0], "./images/planeNormal_1.jpg");//掩码图
	loadimage(&img_role[1], "./images/planeNormal_2.jpg");//原图

	//加载子弹图片
	loadimage(&img_bullet[0], "./images/bullet1.jpg");//掩码图
	loadimage(&img_bullet[1], "./images/bullet2.jpg");//原图

	//加载敌机的图片
	loadimage(&img_enemy[0][0], "./images/enemy_1.jpg");//掩码图
	loadimage(&img_enemy[0][1], "./images/enemy_2.jpg");//原图
	loadimage(&img_enemy[1][0], "./images/enemyPlane1.jpg");//掩码图
	loadimage(&img_enemy[1][1], "./images/enemyPlane2.jpg");//原图

	//加载玩家飞机死亡图片
	loadimage(&img_dieplane[0], "./images/planeExplode_1.jpg");//掩码图
	loadimage(&img_dieplane[1], "./images/planeExplode_2.jpg");//原图
}

struct plane//玩家飞机
{
	int x;
	int y;
	bool live;//是否存活
	int width;
	int height;
	int hp;//血量
	int type;//敌机类型 big small
	int score;//得分
}player,enemy[ENEMY_NUM];

struct bullet//子弹
{
	int x;
	int y;
	bool live;//是否存活
}bull[BULLET_NUM];

bool isExpolde = false; // 飞机是否爆炸

void gameDraw()
{
	//把背景图沾到窗口上
	putimage(0, 0, &bk);

	//绘制玩家飞机 
	//透明贴图技术:用掩码图和原图做一个颜色的二进制操作
	if (!isExpolde)
	{
		putimage(player.x, player.y, &img_role[0], NOTSRCERASE);
		putimage(player.x, player.y, &img_role[1], SRCINVERT);
	}
	else
	{
		putimage(player.x, player.y, &img_dieplane[0], NOTSRCERASE);
		putimage(player.x, player.y, &img_dieplane[1], SRCINVERT);
		Sleep(10000);//游戏结束
	}

	//绘制子弹
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)
		{
			putimage(bull[i].x, bull[i].y, &img_bullet[0], NOTSRCERASE);
			putimage(bull[i].x, bull[i].y, &img_bullet[1], SRCINVERT);
		}
	}

	//绘制敌机
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			if (enemy[i].type == BIG)
			{
				putimage(enemy[i].x, enemy[i].y, &img_enemy[1][0], NOTSRCERASE);
				putimage(enemy[i].x, enemy[i].y, &img_enemy[1][1], SRCINVERT);
			}
			else
			{
				putimage(enemy[i].x, enemy[i].y, &img_enemy[0][0], NOTSRCERASE);
				putimage(enemy[i].x, enemy[i].y, &img_enemy[0][1], SRCINVERT);
			}
		}
	}
}

void gameInit()
{
	loadImg();

	//玩家初始化
	player.x = WIDTH / 2;
	player.y = HEIGHT - 120;
	player.live = true;
	player.hp = 10;
	player.score = 0;
	printf("%d", player.hp);

	//子弹初始化
	for (int i = 0; i < BULLET_NUM; i++)
	{
		bull[i].x = 0;
		bull[i].y = 0;
		bull[i].live = false;

	}

	//敌机初始化
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		enemy[i].live = false;
		enemyHp(i);
	}
}

void playerMove(int speed)
{
	//玩家移动
#if 0
	//检测是否有键盘按下,有则返回值,否则返回假
	if (_kbhit())//<conio.h>里的
	{
		//第一种方式
	//_getch()  阻塞函数,和scanf一样,没有输入就会卡住主程序等待输入,不是C语言的标准函数
		char key = _getch();
		switch (key)
		{
		case 'w':
		case 'W':
			player.y -= speed;
			break;
		case 's':
		case 'S':
			player.y += speed;
			break;
		case 'a':
		case 'A':
			player.x -= speed;
			break;
		case 'd':
		case 'D':
			player.x += speed;
			break;
		}
	}
#elif 1
	//第二种方式
	//使用windows函数获取键盘输入  GetAsyncKeyState  非阻塞函数,非常流畅
	//小键盘的上下左右 如果要检测字母按键,必须用大写,这样大小写都可以检测到,小写一个都检测不到
	if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))//VK_UP系统定义的宏
	{
		if (player.y > 0)//边界处理
		{
			player.y -= speed;
		}
	}
	if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S'))
	{
		if (player.y < HEIGHT - PLAN_HEIGHT)
		{
			player.y += speed;
		}
	}
	if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
	{
		if (player.x + (PLAN_WIDTH / 2) > 0)
		{
			player.x -= speed;
		}
	}
	if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
	{
		if (player.x < WIDTH - (PLAN_WIDTH / 2))
		{
			player.x += speed;
		}
	}
	//printf("(%d,%d)", player.x, player.y);//测试函数
#endif//0
}

void creatBullet()
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (!bull[i].live)
		{
			bull[i].x = player.x + (PLAN_WIDTH / 2) - (BULLET_WIDTH / 2);
			bull[i].y = player.y;
			bull[i].live = true;
			break;//创建一个跳出
		}
	}
}

void bulletMove(int speed)
{
	//子弹射击频率
	if (GetAsyncKeyState(VK_SPACE) && Timer(300, 1))//300毫秒
	{
		creatBullet();
		
	}
	
	for (int i = 0; i < BULLET_NUM; i++)
	{
		
		if (bull[i].live)
		{
			
			bull[i].y -= speed;
			if (bull[i].y < 0)
			{
				bull[i].live = false;
			}
		}
	}
}

void enemyHp(int i)
{
	int flag = rand() % 10;
	if (flag >= 0 && flag <= 3)//产生大飞机
	{
		enemy[i].type = BIG;
		enemy[i].hp = BIG_PH;
		enemy[i].width = 104;
		enemy[i].height = 149;
	}
	else//小飞机
	{
		enemy[i].type = SMALL;
		enemy[i].hp = SMALL_PH;
		enemy[i].width = 52;
		enemy[i].height = 39;
	}
}

void creatEnemy()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			enemy[i].live = true;
			enemy[i].x = rand() % (WIDTH - (BIG_WIDTH + SMALL_WIDTH) / 2);
			enemy[i].y = 0;
			enemyHp(i);//重置敌机HP
			break;
		}
	}
}

void enemyMove(int speed)
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			enemy[i].y += speed;
			if (enemy[i].y > HEIGHT)
			{
				enemy[i].live = false;
			}
		}
	}
}

bool Timer(int ms, int id)
{
	static DWORD t[10];
	if (clock() - t[id] > ms)
	{
		t[id] = clock();
		return true;
	}
	return false;
}

void shootPlane()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			continue;
		}
		for (int j = 0; j < BULLET_NUM; j++)
		{
			if (!bull[j].live)
			{
				continue;
			}
			if (bull[j].x > enemy[i].x && bull[j].x<enemy[i].x + enemy[i].width
				&& bull[j].y>enemy[i].y && bull[j].y < enemy[i].y + enemy[i].height)
			{
				bull[j].live = false;
				enemy[i].hp--;
			}
		}
		if (enemy[i].hp <= 0)
		{
			
			if (enemy[i].type == BIG)
			{
				player.score += BIG_PH;
			}
			else
			{
				player.score +=SMALL_PH;
			}
			enemy[i].live = false;
			
			//printf("%d", player.score);//测试函数
		}
	}
}

void Attacked()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			continue;
		}
		if (player.x > enemy[i].x && player.x<enemy[i].x + enemy[i].width
			&& player.y>enemy[i].y && player.y < enemy[i].y + enemy[i].height)
		{

			enemy[i].hp--;
			player.hp--;
			//printf("%d", player.hp);//测试函数
			if (enemy[i].hp <= 0)
			{
				if (enemy[i].type == BIG)
				{
					player.score += BIG_PH;
				}
				else
				{
					player.score += SMALL_PH;
				}
				enemy[i].live = false;
				//printf("%d", player.score);//测试函数
			}
			if (player.hp <= 0)
			{
				isExpolde = true;
			}

		}
	}
}



void textDraw()
{
	char hp[10];
	char sco[10];
	sprintf(hp, "%d", player.hp);
	sprintf(sco, "%d", player.score);


	settextstyle(20, 10, "黑体");//设置字体
	settextcolor(BLACK);//设置颜色
	setbkmode(NULL);//清空文字背景
	outtextxy(0, 0, "玩家姓名:路远");
	
	outtextxy(0, 25, "玩家血量:");
	outtextxy(100, 25, hp);

	outtextxy(0, 50, "玩家得分:");
	outtextxy(100, 50, sco);
}

void BGM()
{
	//打开音乐,播放音乐  alias取别名 repeat重复播放
	mciSendString(_T("open ./images/game_music.mp3 alias BGM"), NULL, 0, NULL);//播放音乐
	mciSendString(_T("play BGM repeat"), NULL, 0, NULL);//循环播放

	//错误代码无法播放声音
	//mciSendString("open ./images/game_music.mp3 BGM", NULL, 0, NULL);//向多媒体设备接口(mci)发送(send)一个字符串(string)
	//mciSendString("play BGM repeat", NULL, 0, NULL);

}

3.test.cpp

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"



int main()
{
	//创建一个图形窗口
	initgraph(WIDTH, HEIGHT, SHOWCONSOLE);//SHOWCONSOLE  在输出图形函数的同时,把printf函数窗口也显示出来,方便对比界面看数据
	gameInit();

	BGM();

	//双缓冲绘图
	BeginBatchDraw();
	while (1)
	{
		gameDraw();
		textDraw();
		FlushBatchDraw();
		playerMove(PLAYER_SPEED);
		bulletMove(BULLET_SPEED);

		if (Timer(500, 0))
		{
			creatEnemy();
		}

		if (Timer(50, 2))
		{
			enemyMove(ENEMY_SPEED);
		}
		
		shootPlane();
		Attacked();
		//printf("路远来了\n");
	}
	EndBatchDraw();

	return 0;
}
  • 31
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在 easyx 飞机大战中,发射激光的实现需要以下几个步骤: 1. 定义激光的结构体,包括激光的坐标、速度、颜色、是否有效等属性。 2. 玩家飞机发射激光的实现,可以在玩家按下特定按键时,在玩家飞机的位置创建一个激光,并将其加入到激光数组中。 3. 激光的移动实现,每帧更新激光的坐标位置,将超出窗口范围或者已经击中敌机的激光标记为无效。 4. 检测激光是否与敌机相撞,如果相撞,则将激光标记为无效,并将敌机的生命值减少。 下面是一个简单的示例代码,展示了如何实现激光的发射和移动: ```cpp struct Laser { int x, y; // 激光的坐标 int speed; // 激光的速度 COLORREF color; // 激光的颜色 bool valid; // 激光是否有效 }; const int MAX_LASER_NUM = 20; Laser lasers[MAX_LASER_NUM]; // 激光数组 void shootLaser() { for (int i = 0; i < MAX_LASER_NUM; i++) { if (!lasers[i].valid) { lasers[i].x = player.x; lasers[i].y = player.y - 20; // 发射位置在飞机上方 lasers[i].speed = 10; lasers[i].color = RED; lasers[i].valid = true; break; } } } void updateLasers() { for (int i = 0; i < MAX_LASER_NUM; i++) { if (lasers[i].valid) { lasers[i].y -= lasers[i].speed; if (lasers[i].y < 0) { lasers[i].valid = false; } else { for (int j = 0; j < MAX_ENEMY_NUM; j++) { if (enemies[j].valid && IsCollided(enemies[j], lasers[i])) { enemies[j].valid = false; lasers[i].valid = false; break; } } } } } } ``` 注意,这只是一个简单的示例代码,实际实现中还需要考虑更多细节,如激光与敌机的碰撞检测、激光的发射速度、激光的数量限制等等。 ### 回答2: 在EasyX飞机大战游戏中,发射激光可以通过简单的编程实现。具体操作如下: 1. 在游戏中选择一个飞机作为主角飞机,在主循环中捕获键盘事件。 2. 使用GetAsyncKeyState函数来检测玩家是否按下了空格键,如果按下,则表示发射激光。 3. 在按下空格键后,创建一个激光对象,具体可以使用一个自定义的结构体来表示激光,该结构体包括激光的坐标、速度和绘制标志等属性。 4. 将新创建的激光对象添加到一个激光对象数组中,用来保存当前所有的激光对象。 5. 在主循环中更新激光对象数组中的所有激光对象,根据激光的速度更新激光的坐标位置。 6. 在主循环中绘制激光对象数组中的所有激光对象,根据激光的坐标位置在游戏窗口中绘制激光。 7. 在绘制激光时,可以使用EasyX提供的绘图函数实现,比如使用Line函数绘制一条直线来表示激光。 通过以上步骤,就可以在EasyX飞机大战游戏中实现激光的发射效果。玩家按下空格键后,会在飞机前方出现一个激光,随着时间的推移,激光会向前移动并逐渐消失。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值