EasyX中画飞机用fillpolygon手绘三角形+矩形机翼,敌机用不同颜色fillcircle,子弹用fillrectangle;运动需双缓冲+GetTickCount64固定帧率+浮点坐标;碰撞在逻辑更新后立即检测;音效预加载WAV并用SND_MEMORY播放。

EasyX 中怎么画飞机和子弹的图形
EasyX 没有内置精灵系统,所有图形得靠 fillcircle、line、fillpolygon 或贴图(loadimage)实现。用矢量绘制适合调试,但性能差;用 PNG 贴图更真实,但要注意透明通道支持——必须用 loadimage(NULL, L"plane.png", 0, 0, true) 的 true 参数启用 alpha 通道,否则背景是黑块。
常见错误:直接用 loadimage 加载无透明信息的 JPG,结果飞机拖着一块白底飞;或者忘了调用 setorigin 对齐旋转中心,导致 rotateimage 时图像乱飘。
- 玩家飞机建议用
fillpolygon手绘(3个点构成三角形+1个小矩形当机翼),方便后续做碰撞检测 - 敌机可用不同颜色的圆圈区分类型:
setcolor(RED)+fillcircle(x, y, 8) - 子弹统一用小矩形:
fillrectangle(x-2, y-6, x+2, y),避免line在高速移动时“断线”
怎么让飞机和子弹动起来且不卡顿
核心是双缓冲 + 固定帧率循环。EasyX 默认开启双缓冲(initgraph 后自动生效),但很多人漏掉 BeginBatchDraw() / EndBatchDraw(),导致每帧重绘全部对象时 CPU 突增,尤其敌机一多就掉帧。
不要用 delay(16) 控制帧率——Windows 下精度差,且会阻塞输入。正确做法是用 GetTickCount64() 计算间隔:
立即学习“C++免费学习笔记(深入)”;
auto last_tick = GetTickCount64();
while (running) {
auto now = GetTickCount64();
if (now - last_tick < 16) { Sleep(1); continue; }
last_tick = now;
// 更新逻辑 + 绘图
}- 所有运动对象(飞机、子弹、爆炸效果)必须用浮点坐标(
double x, y)存储,避免整数截断导致“抖动” - 键盘响应别放主循环里轮询
GetAsyncKeyState,容易漏键;改用GetKeyState或配合消息钩子 - 子弹速度别硬写
y -= 5,统一用y -= speed * dt,为后期加慢动作/加速留接口
怎么检测子弹打中敌机
EasyX 没有内置碰撞函数,得自己算。矩形包围盒(AABB)最快,适合子弹打飞机这种简单场景;圆形检测(距离平方 (dx*dx + dy*dy) )更准但稍慢。
关键陷阱:检测时机不对。不能等子弹画出来再检测,必须在逻辑更新阶段(即修改坐标后、绘图前)立刻判断——否则会出现“子弹穿模”:明明看到打中了,但坐标还没更新到命中位置,检测失败。
- 玩家子弹数组用
vector<bullet></bullet>,敌机用vector<enemy></enemy>,遍历嵌套检测时记得从后往前删元素(避免迭代器失效) - 删除逻辑别写成
erase(it++),推荐it = bullets.erase(it) - 爆炸效果用状态机:
enum class BoomState { IDLE, PLAYING, DONE },每帧推进帧序号,播完自动标记删除
怎么加载音效和避免崩溃
EasyX 的 PlaySound 是 Windows API 封装,只支持 WAV,且默认异步播放。常见崩溃原因:WAV 文件路径含中文、文件被其他程序占用、或反复快速调用 PlaySound(L"shot.wav", NULL, SND_ASYNC | SND_FILENAME) 导致资源冲突。
稳妥做法是预加载到内存再播:
HGLOBAL hWave = LoadResource(GetModuleHandle(NULL), FindResource(NULL, L"SHOT_WAV", RT_RCDATA)); // ……(略去波形数据提取) PlaySound((LPCSTR)LockResource(hWave), NULL, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
- 绝对不要在
WM_PAINT或绘图函数里调用PlaySound,可能触发重入 - 音效文件务必用 16bit/44.1kHz 单声道 WAV,否则部分机器静音
- 背景音乐用
SND_LOOP | SND_ASYNC,但退出前必须显式调用PlaySound(NULL, NULL, 0)停止,否则进程残留音频句柄
真正麻烦的不是画图或移动,而是对象生命周期管理——子弹生成、飞行、碰撞、销毁,每个环节漏掉一个 erase 或少判一次边界,游戏跑十分钟就内存暴涨或闪退。贴图、声音、碰撞三者任意一个没处理好透明/格式/时机,画面或音效就会“断层”,而这种问题往往只在特定机器复现。



















