#define _CRT_SECURE_NO_WARNINGS
#define EnemySpeed 1
#include<easyx.h>
#include<graphics.h>
#include<conio.h>
#include<vector>
#include<iostream>
#include<ctime>
#include<string>
using namespace std;
const int screenwidth = 600;
const int screenheight = 1200;
int num = 0;
IMAGE EnemyBoom[4];
IMAGE PlayerBoom[4];
IMAGE StrongEnemyBoom[4];
IMAGE heroimg, enemyimg, bkimg, bulletimg;
IMAGE StrongEnemyimg;
// 核心图像渲染函数
void MyPutImageAlphaInternal(int x, int y, IMAGE* img, int alpha) {
DWORD* dst = GetImageBuffer();
DWORD* draw = GetImageBuffer();
DWORD* src = GetImageBuffer(img);
int pictureWidth = img->getwidth();
int pictureHeight = img->getheight();
int graphWidth = getwidth();
int graphHeight = getheight();
int dstX = 0;
for (int iy = 0; iy < pictureHeight; iy++) {
for (int ix = 0; ix < pictureWidth; ix++) {
int srcX = ix + iy * pictureWidth;
int sa = ((src[srcX] & 0xff000000) >> 24);
sa = sa * ((float)alpha / 255);
int sr = ((src[srcX] & 0xff0000) >> 16);
int sg = ((src[srcX] & 0xff00) >> 8);
int sb = src[srcX] & 0xff;
if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight) {
dstX = (ix + x) + (iy + y) * graphWidth;
int dr = ((dst[dstX] & 0xff0000) >> 16);
int dg = ((dst[dstX] & 0xff00) >> 8);
int db = dst[dstX] & 0xff;
draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)
| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)
| (sb * sa / 255 + db * (255 - sa) / 255);
}
}
}
}
void MyPutImageAlpha(int x, int y, IMAGE* img, int alpha) {
DWORD* dst = GetImageBuffer();
DWORD* draw = GetImageBuffer();
DWORD* src = GetImageBuffer(img);
int graphWidth = getwidth();
int graphHeight = getheight();
int dstX = 0;
if ((x + img->getwidth() <= 0 || y + img->getheight() <= 0)) {
return;
}
else if (y >= graphHeight || x >= graphWidth) {
return;
}
else {
IMAGE imgTmp, imgTmp2, imgTmp3;
if (y < 0) {
SetWorkingImage(img);
getimage(&imgTmp, 0, -y, img->getwidth(), img->getheight() + y);
SetWorkingImage();
y = 0;
img = &imgTmp;
}
else if (y + img->getwidth() > graphHeight) {
SetWorkingImage(img);
getimage(&imgTmp, 0, 0, img->getwidth(), graphHeight - y);
SetWorkingImage();
}
if (x < 0) {
SetWorkingImage(img);
getimage(&imgTmp2, -x, 0, img->getwidth() + x, img->getheight());
SetWorkingImage();
x = 0;
img = &imgTmp2;
}
else if (x + img->getwidth() > graphWidth) {
SetWorkingImage(img);
getimage(&imgTmp3, 0, 0, graphWidth - x, img->getheight());
SetWorkingImage();
img = &imgTmp3;
}
}
MyPutImageAlphaInternal(x, y, img, alpha);
}
void MyPutImageAlpha(int x, int y, IMAGE* img) {
MyPutImageAlpha(x, y, img, 255);
}
// 资源加载函数
void LoadImg() {
loadimage(&StrongEnemyimg, "./images/enemy3_hit.png");
loadimage(&heroimg, "./images/me1.png", 51, 63);
loadimage(&enemyimg, "./images/enemy1.png");
loadimage(&bkimg, "./images/bk2.png", 600, 2400);
loadimage(&bulletimg, "./images/bullet1.png");
loadimage(&EnemyBoom[0], "./images/enemy1_down1.png");
loadimage(&EnemyBoom[1], "./images/enemy1_down2.png");
loadimage(&EnemyBoom[2], "./images/enemy1_down3.png");
loadimage(&EnemyBoom[3], "./images/enemy1_down4.png");
loadimage(&PlayerBoom[0], "./images/me_destroy_1.png", 51, 63);
loadimage(&PlayerBoom[1], "./images/me_destroy_2.png", 51, 63);
loadimage(&PlayerBoom[2], "./images/me_destroy_3.png", 51, 63);
loadimage(&PlayerBoom[3], "./images/me_destroy_4.png", 51, 63);
loadimage(&StrongEnemyBoom[0], "./images/enemy3_down1.png");
loadimage(&StrongEnemyBoom[1], "./images/enemy3_down2.png");
loadimage(&StrongEnemyBoom[2], "./images/enemy3_down3.png");
loadimage(&StrongEnemyBoom[3], "./images/enemy3_down4.png");
}
// 点与矩形区域判断函数
bool is_Area(int x, int y, RECT& r) {
return (r.left <= x && r.right >= x && r.top <= y && y <= r.bottom);
}
// 碰撞检测函数
bool Crash(const RECT& r1, const RECT& r2) {
return (r1.left < r2.right && r1.right > r2.left &&
r1.bottom > r2.top && r1.top < r2.bottom);
}
// 敌机击杀计数显示
void EnemyKillShow(int EnemyKillCount) {
setbkmode(TRANSPARENT);
string s = to_string(EnemyKillCount);
string str = "击杀数: " + s;
settextcolor(BLACK);
settextstyle(20, 0, "黑体");
outtextxy(10, 10, str.c_str());
}
class aircraft {
public:
aircraft(IMAGE& i) : img(i) {}
aircraft(IMAGE& i, int hp) : img(i), HP(hp) {
rect = { 0 };
}
virtual ~aircraft() {}
int GetHP() { return HP; }
void SetHP(int x) { HP = x; }
bool is_die() { return HP <= 0; }
void Attacked(int Damege) { HP -= Damege; }
RECT& GetRect() { return rect; }
protected:
int HP = 0;
IMAGE& img;
RECT rect;
};
class Bullet {
public:
Bullet(IMAGE& img, RECT pr, int d) : img(img), Damege(d) {
rect.left = pr.left + (pr.right - pr.left) / 2 - img.getwidth() / 2;
rect.right = rect.left + img.getwidth();
rect.top = pr.top - img.getheight();
rect.bottom = rect.top + img.getheight();
}
virtual bool Show() {
if (rect.bottom <= 0) return false;
rect.top -= 50;
rect.bottom -= 50;
MyPutImageAlpha(rect.left, rect.top, &img);
return true;
}
RECT& GetRect() { return rect; }
int GetDamege() { return Damege; }
protected:
RECT rect;
IMAGE& img;
int Damege;
};
class EnemyBullet : public Bullet {
public:
EnemyBullet(IMAGE& img, RECT pr) : Bullet(img, pr, 25) {}
virtual bool Show() {
if (rect.top >= screenheight) return false;
rect.top += 4;
rect.bottom += 4;
MyPutImageAlpha(rect.left, rect.top, &img);
return true;
}
};
class StrongEnemyBullet : public Bullet {
public:
StrongEnemyBullet(IMAGE& img, RECT pr, int of) : Bullet(img, pr, 100), offset(of) {}
virtual bool Show() {
if (rect.top >= screenheight) return false;
rect.top += 4;
rect.bottom += 4;
rect.left += offset;
rect.right += offset;
MyPutImageAlpha(rect.left, rect.top, &img);
return true;
}
protected:
int offset;
};
class BK {
public:
BK(IMAGE& i) : img(i), h(-screenheight) {}
void show() {
if (h >= 0) h = -screenheight;
h += 1;
MyPutImageAlpha(0, h, &img);
}
private:
IMAGE& img;
double h;
};
class Hero : public aircraft {
public:
Hero(IMAGE& i) : aircraft(i, 10000) {
SetRect();
}
virtual void SetRect() {
rect.left = screenwidth / 2 - img.getwidth() / 2;
rect.top = screenheight - img.getheight();
rect.right = rect.left + img.getwidth();
rect.bottom = screenheight;
}
virtual void show() {
string s = to_string(HP);
string str = "HP: " + s;
settextcolor(BLACK);
settextstyle(15, 0, "黑体");
outtextxy(rect.left - (rect.right - rect.left) / 2 + textwidth(str.c_str()) / 2,
rect.top - textheight(str.c_str()), str.c_str());
MyPutImageAlpha(rect.left, rect.top, &img);
}
void control() {
ExMessage mess;
if (peekmessage(&mess, EM_MOUSE)) {
rect.left = mess.x - img.getwidth() / 2;
rect.top = mess.y - img.getheight() / 2;
rect.right = rect.left + img.getwidth();
rect.bottom = rect.top + img.getheight();
}
}
void Shoot(vector<Bullet>& bullets, IMAGE& bulletimg) {
RECT heroRect = GetRect();
int bulletOffsetX[] = { -img.getwidth() / 4, 0, img.getwidth() / 4 };
for (int i = 0; i < sizeof(bulletOffsetX) / sizeof(int); ++i) {
RECT bulletRect;
bulletRect.left = heroRect.left + (heroRect.right - heroRect.left) / 2 - bulletimg.getwidth() / 2 + bulletOffsetX[i];
bulletRect.top = heroRect.top - bulletimg.getheight();
bulletRect.right = bulletRect.left + bulletimg.getwidth();
bulletRect.bottom = bulletRect.top + bulletimg.getheight();
bullets.push_back(Bullet(bulletimg, bulletRect, Damege));
}
}
void HeroDead() {
MyPutImageAlpha(rect.left, rect.top, &PlayerBoom[0]);
Sleep(100);
MyPutImageAlpha(rect.left, rect.top, &PlayerBoom[1]);
Sleep(100);
MyPutImageAlpha(rect.left, rect.top, &PlayerBoom[2]);
Sleep(100);
MyPutImageAlpha(rect.left, rect.top, &PlayerBoom[3]);
Sleep(100);
}
void SetDamege(int D) { Damege = D; }
int GetDamege() { return Damege; }
private:
int Damege = 25;
};
class Enemy : public aircraft {
public:
Enemy(IMAGE& i, int X) : aircraft(i, 500) {
rect.left = X;
rect.top = -img.getheight();
rect.right = rect.left + img.getwidth();
rect.bottom = rect.top + img.getheight();
}
virtual bool Show() {
if (is_die()) {
boomsum = (int)timer;
if (boomsum >= 4) {
boomsum = 0;
timer = 0;
return false;
}
MyPutImageAlpha(rect.left, rect.top, &EnemyBoom[boomsum]);
timer += 0.1;
return true;
}
else {
if (rect.top >= screenheight) return false;
rect.top += EnemySpeed;
rect.bottom += EnemySpeed;
MyPutImageAlpha(rect.left, rect.top, &img);
return true;
}
}
virtual void SetRect(int X, int Y) {
rect.left = X;
rect.top = Y;
rect.right = rect.left + img.getwidth();
rect.bottom = rect.top + img.getheight();
}
protected:
int boomsum = 0;
double timer = 0;
};
class StrongEnemy : public aircraft {
public:
StrongEnemy(IMAGE& i, int x) : aircraft(i, 10000) {
rect.left = x;
rect.top = -img.getheight();
rect.right = rect.left + img.getwidth();
rect.bottom = rect.top + img.getheight();
offset = 3;
}
virtual bool Show() {
if (aircraft::is_die()) {
boomsum = (int)timer;
if (boomsum >= 4) {
boomsum = 0;
timer = 0;
HP = 10000;
return false;
}
MyPutImageAlpha(rect.left, rect.top, &StrongEnemyBoom[boomsum]);
timer += 0.1;
return true;
}
else {
if (rect.top >= screenheight) return false;
MyPutImageAlpha(rect.left, rect.top, &img);
return true;
}
}
void Shoot(vector<StrongEnemyBullet>& bullets, IMAGE& bulletimg) {
RECT heroRect = GetRect();
int bulletOffsetX[] = { -img.getwidth() / 4, 0, img.getwidth() / 4 };
int j = -offset;
for (int i = 0; i < sizeof(bulletOffsetX) / sizeof(int); ++i) {
RECT bulletRect;
bulletRect.left = heroRect.left + (heroRect.right - heroRect.left) / 2 - bulletimg.getwidth() / 2 + bulletOffsetX[i];
bulletRect.top = heroRect.top - bulletimg.getheight();
bulletRect.right = bulletRect.left + bulletimg.getwidth();
bulletRect.bottom = bulletRect.top + bulletimg.getheight();
bullets.push_back(StrongEnemyBullet(bulletimg, bulletRect, j));
j += offset;
}
offset = rand() % 4;
}
protected:
int boomsum = 0;
int offset;
double timer = 0;
};
// 主菜单界面
void welcome() {
LPCTSTR Title = "飞机大战";
LPCTSTR textPlay = "开始游戏";
LPCTSTR textExit = "退出游戏";
while (1) {
BeginBatchDraw();
setbkcolor(WHITE);
cleardevice();
settextstyle(60, 0, "黑体");
settextcolor(BLACK);
outtextxy(screenwidth / 2 - textwidth(Title) / 2, screenheight / 6, Title);
settextstyle(40, 0, "楷体");
RECT Rplay, Rexit;
Rplay.left = (screenwidth / 2 - textwidth(textPlay) / 2);
Rplay.right = Rplay.left + textwidth(textPlay);
Rplay.top = screenheight / 4;
Rplay.bottom = Rplay.top + textheight(textPlay);
Rexit.left = (screenwidth / 2 - textwidth(textExit) / 2);
Rexit.right = Rplay.left + textwidth(textExit);
Rexit.top = screenheight / 3;
Rexit.bottom = Rexit.top + textheight(textExit);
outtextxy(Rplay.left, Rplay.top, textPlay);
outtextxy(Rexit.left, Rexit.top, textExit);
EndBatchDraw();
ExMessage me;
getmessage(&me, EM_MOUSE);
if (me.lbutton) {
if (is_Area(me.x, me.y, Rplay)) {
return;
}
else if (is_Area(me.x, me.y, Rexit)) {
exit(0);
}
}
}
}
// 游戏主循环
bool play() {
int EnemyKillCount = 0;
int StrongCount = 0;
setbkcolor(WHITE);
cleardevice();
bool is_play = true;
LoadImg();
BK backgrand(bkimg);
Hero H(heroimg);
clock_t lastEnemyTime = clock();
clock_t BulletLastEnemyTime = clock();
clock_t EnemyBulletLastEnemyTime = clock();
clock_t StrongBulletEnemyLastTime = clock();
vector<Enemy> es;
vector<StrongEnemy> SE;
vector<Bullet> HeroBullet;
vector<EnemyBullet> EBullet;
vector<StrongEnemyBullet> SBullet;
while (is_play) {
Sleep(3);
BeginBatchDraw();
backgrand.show();
H.control();
H.show();
clock_t currentTime = clock();
double elapsedTime = static_cast<double>(currentTime - lastEnemyTime) / CLOCKS_PER_SEC;
if (elapsedTime >= 1 && es.size() < 6) {
es.push_back(Enemy(enemyimg, abs(rand() % (screenwidth - enemyimg.getheight()))));
num++;
lastEnemyTime = currentTime;
}
clock_t BulletCurrentTime = clock();
double BulletElapsedTime = static_cast<double>(BulletCurrentTime - BulletLastEnemyTime) / CLOCKS_PER_SEC;
if (BulletElapsedTime >= 0.05) {
if (EnemyKillCount >= 15) {
H.Shoot(HeroBullet, bulletimg);
H.SetDamege(25 + EnemyKillCount % 3);
BulletLastEnemyTime = BulletCurrentTime;
}
else {
HeroBullet.push_back(Bullet(bulletimg, H.GetRect(), H.GetDamege()));
BulletLastEnemyTime = BulletCurrentTime;
}
}
auto it = es.begin();
while (it != es.end()) {
if (Crash(it->GetRect(), H.GetRect())) {
is_play = false;
EndBatchDraw();
H.HeroDead();
break;
}
auto bit = HeroBullet.begin();
while (bit != HeroBullet.end() && it != es.end()) {
if (Crash(bit->GetRect(), it->GetRect()) && !it->is_die()) {
it->Attacked(bit->GetDamege());
bit = HeroBullet.erase(bit);
if (it->is_die()) {
EnemyKillCount++;
StrongCount++;
break;
}
}
else { bit++; }
}
if (it != es.end() && !(*it).Show()) {
it = es.erase(it);
}
if (it != es.end()) {
it++;
}
}
if (!is_play) break;
auto EBit = EBullet.begin();
while (EBit != EBullet.end()) {
if (Crash(EBit->GetRect(), H.GetRect())) {
H.Attacked(EBit->GetDamege());
if (H.is_die()) {
is_play = false;
EndBatchDraw();
H.HeroDead();
break;
}
EBit = EBullet.erase(EBit);
}
if (EBit != EBullet.end()) EBit++;
}
if (!is_play) break;
H.control();
H.show();
auto buit = HeroBullet.begin();
while (buit != HeroBullet.end()) {
if (!(*buit).Show()) buit = HeroBullet.erase(buit);
else buit++;
}
EnemyKillShow(EnemyKillCount);
EndBatchDraw();
}
LPCTSTR over = "GAME OVER!";
setbkcolor(WHITE);
cleardevice();
settextstyle(60, 0, "黑体");
settextcolor(BLACK);
outtextxy(screenwidth / 2 - textwidth(over) / 2, 300, over);
Sleep(2000);
return true;
}
// 程序入口
int main() {
initgraph(screenwidth, screenheight, EW_NOMINIMIZE | SHOWCONSOLE);
bool is_run = true;
while (is_run) {
welcome();
is_play = play();
}
return 0;
}
他为什么说没定义标识符“is_play”