#include #include #include #include "EasyXPng.h" // 用于显示带透明通道的png图片// 引用 Windows Multimedia API#pragma comment(lib,"Winmm.lib")#define WIDTH 560// 画面宽度#define HEIGHT 800// 画面高度#define MaxBulletNum 200// 最多子弹个数
void sleep(DWORD ms) // 精确延时函数{
static DWORD oldtime = GetTickCount();
while(GetTickCount() - oldtime < ms)
Sleep(1);
oldtime = GetTickCount();
}
void PlayMusicOnce(TCHAR fileName[80]) // 播放一次音乐函数{
TCHAR cmdString1[50];
_stprintf(cmdString1, _T("open %s alias tmpmusic"), fileName);// 生成命令字符串mciSendString(_T("close tmpmusic"), NULL, 0, NULL); // 先把前面一次的音乐关闭mciSendString(cmdString1, NULL, 0, NULL); // 打开音乐mciSendString(_T("play tmpmusic"), NULL, 0, NULL); // 仅播放一次}
class Rocket // 定义火箭类{
public:
IMAGE im_rocket; // 火箭图像IMAGE im_blowup; // 爆炸图像float x,y; // 火箭坐标float width,height; // 火箭图片的宽度、高度int liveSecond; // 火箭存活了多长时间int life; // 火箭有几条命
void draw() // 显示火箭相关信息{
// 窗口左上角显示life个火箭图片,表示火箭生命数for (int i=0;i
putimagePng(i*width*0.9,0,&im_rocket);
// 窗口正上方显示坚持了多少秒TCHAR s[20];
setbkmode(TRANSPARENT); // 文字字体透明_stprintf(s, _T("%d秒"), liveSecond);
settextcolor(WHITE); // 设定文字颜色settextstyle(40, 0, _T("黑体"));// 设定文字大小、样式outtextxy(WIDTH*0.85, 20, s); // 输出文字内容
if (life>0) // 根据有命没命,显示不同的图片putimagePng(x - width/2,y-height/2,&im_rocket); // 游戏中显示火箭图片else
putimagePng(x - width/2,y-height/2,&im_blowup); // 游戏中显示爆炸图片}
void update(float mx,float my) // 根据输入的坐标更新火箭的位置{
x = mx;
y = my;
}
void updateWhenLifeLost() // 当火箭减命时执行的操作{
PlayMusicOnce(_T("explode.mp3")); // 播放一次爆炸音效life --; // 生命减少}
};
class Bullet // 定义子弹类{
public:
IMAGE im_bullet; // 子弹图像float x,y; // 子弹坐标float vx,vy; // 子弹速度float radius; // 接近球体的子弹半径大小
void draw()// 显示子弹{
putimagePng(x - radius,y-radius,&im_bullet);
}
void update() // 更新子弹的位置、速度{
x += vx;
y += vy;
if (x<=0 || x>=WIDTH)
vx = -vx;
if (y<=0 || y>=HEIGHT)
vy = -vy;
}
int isCollideRocket(Rocket rocket) // 判断子弹是否和火箭碰撞{
float distance_x = abs(rocket.x - x);
float distance_y = abs(rocket.y - y);
if ( distance_x < rocket.width/2 && distance_y < rocket.height/2 )
return 1; // 发生碰撞返回1else
return 0; // 不碰撞返回0}
};
class SmartUFO: public Bullet // 智能飞碟类,由Bullet类派生出来{
public:
void updateVelforTarge(Rocket targetRocket) // 让飞碟的速度瞄向目标火箭{
float scalar = 1*rand()/double(RAND_MAX) + 1; // 速度大小有一定的随机性if (targetRocket.x>x) // 目标在飞碟左边,飞碟x方向速度向右vx = scalar;
else if (targetRocket.x
if (targetRocket.y>y) // 目标在飞碟下方,飞碟y方向速度向下vy = scalar;
else if (targetRocket.y
}
};
IMAGE im_bk,im_bullet,im_rocket,im_blowup,im_UFO; // 定义图像对象Bullet bullet[MaxBulletNum]; // 定义子弹对象数组Rocket rocket; // 定义火箭对象SmartUFO ufo; // 定义飞碟对象int bulletNum = 0; // 已有子弹的个数
void startup() // 初始化函数{
mciSendString(_T("open game_music.mp3 alias bkmusic"), NULL, 0, NULL);//打开背景音乐mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL); // 循环播放
srand(time(0)); // 初始化随机种子loadimage(&im_bk, _T("background.png")); // 导入背景图片loadimage(&im_bullet, _T("bullet.png")); // 导入子弹图片loadimage(&im_rocket, _T("rocket.png")); // 导入火箭图片loadimage(&im_blowup, _T("blowup.png")); // 导入爆炸图片loadimage(&im_UFO, _T("ufo.png")); // 导入飞碟图片
// 对飞碟的一些成员变量初始化ufo.x = WIDTH/2; // 设置飞碟位置ufo.y = 10;
ufo.im_bullet = im_UFO; // 设置飞碟图片ufo.radius = im_UFO.getwidth()/2; // 设置飞碟半径大小ufo.updateVelforTarge(rocket); // 更新飞碟的速度
// 对rocket一些成员变量初始化rocket.im_rocket = im_rocket; // 设置火箭图片rocket.im_blowup = im_blowup; // 设置火箭爆炸图片rocket.width = im_rocket.getwidth(); // 设置火箭宽度rocket.height = im_rocket.getheight(); // 设置火箭高度rocket.life = 5; // 火箭初始5条命
initgraph(WIDTH,HEIGHT); // 新开一个画面BeginBatchDraw(); // 开始批量绘制}
void show() // 绘制函数{
putimage(0, 0, &im_bk);// 显示背景ufo.draw(); // 显示飞碟for (int i=0;i
bullet[i].draw(); // 显示已有的子弹rocket.draw(); // 显示火箭及相关信息FlushBatchDraw(); // 批量绘制sleep(10); // 暂停}
void updateWithoutInput() // 和输入无关的更新{
if (rocket.life<=0) // 火箭没有命了,不处理return; // 直接返回
static int lastSecond = 0; // 记录前一次程序运行了多少秒static int nowSecond = 0; // 记录当前程序运行了多少秒static clock_t start = clock(); // 记录第一次运行时刻clock_t now = clock(); // 获得当前时刻// 计算程序目前一共运行了多少秒nowSecond =( int(now - start) / CLOCKS_PER_SEC);
rocket.liveSecond = nowSecond; // 火箭生成了多少秒赋值
if (nowSecond==lastSecond+1) // 时间过了1秒钟,更新下飞碟的速度ufo.updateVelforTarge(rocket); // ufo速度方向瞄准火箭
if (nowSecond==lastSecond+2) // 时间过了2秒钟,新增一颗子弹{
lastSecond = nowSecond; // 更新下lastSecond变量// 如果没有超出最大子弹数目的限制,增加一颗新的子弹if (bulletNum
{
bullet[bulletNum].x = WIDTH/2; // 子弹初始位置bullet[bulletNum].y = 10;
float angle = (rand()/double(RAND_MAX)-0.5)*0.9*PI;
float scalar = 2*rand()/double(RAND_MAX) + 2;
bullet[bulletNum].vx = scalar*sin(angle); // 子弹随机速度bullet[bulletNum].vy = scalar*cos(angle);
bullet[bulletNum].im_bullet = im_bullet; // 设置子弹图像bullet[bulletNum].radius = im_bullet.getwidth()/2; // 子弹半径为图片宽度一半}
bulletNum++; // 子弹数目加一}
for (int i=0;i
bullet[i].update(); // 更新子弹的位置、速度if (bullet[i].isCollideRocket(rocket)) // 判断子弹是否和火箭碰撞{
rocket.updateWhenLifeLost(); // 火箭减命相关操作bullet[i].x = 5; // 当前子弹移开,防止重复碰撞bullet[i].y = 5;
break; // 火箭已炸,不用再和其他子弹比较了}
}
ufo.update(); // 更新飞碟的位置、速度if (ufo.isCollideRocket(rocket)) // 判断飞碟是否和火箭碰撞{
rocket.updateWhenLifeLost(); // 当火箭减命时执行的操作ufo.x = 5; // 当前飞碟移开,防止重复碰撞ufo.y = 5;
}
}
void updateWithInput() // 和输入相关的更新{
if (rocket.life<=0) // 火箭没有命了,不处理return; // 直接返回
MOUSEMSG m;// 定义鼠标消息while (MouseHit()) // 检测当前是否有鼠标消息{
m = GetMouseMsg();
if(m.uMsg == WM_MOUSEMOVE) // 到鼠标移动时rocket.update(m.x,m.y); // 火箭的位置等于鼠标所在的位置}
}
int main() // 主函数{
startup(); // 初始化while (1) // 重复运行{
show(); // 绘制updateWithoutInput(); // 和输入无关的更新updateWithInput(); // 和输入相关的更新}
return 0;
}