easyx图形库在不定时会使窗口黑掉

-2

我用的是windows11操作系统Visual Studio 2019编译环境。

请看代码。

代码可能比较长,这是我编写的一款小游戏。我想说明的问题是在后面游戏结束时,不退出主程序但再调出图形窗口会使窗口黑屏。

#include <graphics.h>
#include <conio.h>
#include <time.h>
#include "EasyXPng.h"
#include <vector>
#include<iostream>
#include<windows.h>
#include <stdlib.h>
#include <string>
#include<setjmp.h>

#pragma comment(lib,"Winmm.lib")
#pragma warning(disable : 4996)
#define WIDTH 800 // 画面宽度
#define HEIGHT 600 // 画面高度
#define MaxBulletNum 35 // 最多子弹个数

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个火箭图片,表示火箭生命数
setfillcolor(RED);
fillrectangle(40, 10, life * 60, 20);

// 窗口正上方显示坚持了多少秒
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() // 当火箭减命时执行的操作
{

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; // 发生碰撞返回1
else
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 < x) // 目标在飞碟右边,飞碟x方向速度向左
vx = -scalar;
if (targetRocket.y > y) // 目标在飞碟下方,飞碟y方向速度向下
vy = scalar;
else if (targetRocket.y < y) // 目标在飞碟上方,飞碟y方向速度向上
vy = -scalar;
}
};

IMAGE im_bk, im_bullet, im_rocket, im_blowup, im_UFO, a; // 定义图像对象
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 < bulletNum; i++)
bullet[i].draw(); // 显示已有的子弹
rocket.draw(); // 显示火箭及相关信息
FlushBatchDraw(); // 批量绘制
sleep(10); // 暂停

}
static int lastSecond = 0; // 记录前一次程序运行了多少秒
static int nowSecond = 0; // 记录当前程序运行了多少秒
void updateWithoutInput() // 和输入无关的更新
{

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 + 4) // 时间过了4秒钟,新增一颗子弹
{
lastSecond = nowSecond; // 更新下lastSecond变量
// 如果没有超出最大子弹数目的限制,增加一颗新的子弹
if (bulletNum < MaxBulletNum)
{
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 < bulletNum; i++) // 对所有已有的子弹
{
bullet[i].update(); // 更新子弹的位置、速度
if (bullet[i].isCollideRocket(rocket)) // 判断子弹是否和火箭碰撞
{
rocket.updateWhenLifeLost(); // 火箭减命相关操作
bullet[i].x = 10; // 当前子弹移开,防止重复碰撞
bullet[i].y = 10;
break; // 火箭已炸,不用再和其他子弹比较了
}
}
ufo.update(); // 更新飞碟的位置、速度
if (ufo.isCollideRocket(rocket)) // 判断飞碟是否和火箭碰撞
{
rocket.updateWhenLifeLost(); // 当火箭减命时执行的操作
ufo.x = 10; // 当前飞碟移开,防止重复碰撞
ufo.y = 10;
}
}

void updateWithInput() // 和输入相关的更新
{

MOUSEMSG m; // 定义鼠标消息
while (MouseHit()) // 检测当前是否有鼠标消息
{
m = GetMouseMsg();
if (m.uMsg == WM_MOUSEMOVE) // 到鼠标移动时
rocket.update(m.x, m.y); // 火箭的位置等于鼠标所在的位置
}
}

int main() // 主函数
{
char xk[100000];
FILE* xxk = fopen("许可证.xk", "r");
while (!feof(xxk))
{
fgets(xk, 100000, xxk);

}
long long a = atoi(xk);
if (a == 362845)
{
a:
IMAGE im_b;
initgraph(800, 600);
loadimage(&im_b, _T("landscape7.png"));
putimage(0, 0, &im_b);
setbkmode(TRANSPARENT);
settextcolor(YELLOW);
settextstyle(25, 0, _T("黑体"));
outtextxy(350, 550, _T("Dev 3.0"));
settextstyle(35, 0, _T("黑体"));
Sleep(700);
outtextxy(50, 50, _T("坚持一百秒"));
Sleep(700);
rectangle(330, 200, 480, 250);
settextstyle(25, 0, _T("黑体"));
outtextxy(380, 215, _T("开始"));
Sleep(700);

while (1)
{
if (MouseHit())
{
MOUSEMSG a;
a = GetMouseMsg();
if (a.uMsg == WM_LBUTTONDOWN && a.x < 480 && a.x>330 && a.y > 200 && a.y < 250)
{
startup(); // 初始化
while (rocket.liveSecond<100&&rocket.life>0) // 重复运行
{
show(); // 绘制
updateWithoutInput();
updateWithInput();

}
if (rocket.liveSecond >= 100)
{
mciSendString(L"close bkmusic", NULL, 0, NULL);
goto a;
cleardevice();
initgraph(800, 600);
setbkmode(TRANSPARENT); // 文字字体透明
settextcolor(BLUE); // 设定文字颜色
IMAGE aaaaa;
loadimage(&aaaaa, _T("landscape7.png"));
putimage(0, 0,&aaaaa);
settextstyle(40, 0, _T("黑体"));
outtextxy(WIDTH * 0.5, 300, _T("你赢了!"));
Sleep(1000);
outtextxy(WIDTH * 0.5, 320, _T("再玩一次吗?"));
outtextxy(WIDTH*0.45, 342, _T("是"));
rectangle(WIDTH * 0.4, 340, WIDTH * 0.6, 360);
outtextxy(WIDTH * 0.7, 342, _T("否"));
rectangle(WIDTH * 0.65, 340, WIDTH * 0.75, 360);
}
else
{
mciSendString(L"close bkmusic", NULL, 0, NULL);
cleardevice();
goto a;

setbkmode(TRANSPARENT); // 文字字体透明
settextcolor(BLUE); // 设定文字颜色
IMAGE aaaaa;
loadimage(&aaaaa, _T("landscape7.png"));
putimage(0, 0, &aaaaa);
settextstyle(40, 0, _T("黑体"));
TCHAR s[20];
_stprintf(s, _T("你死了,并存活了%d秒"),rocket.liveSecond);
outtextxy(WIDTH * 0.5, 300, s);
Sleep(1000);
outtextxy(WIDTH * 0.5, 320, _T("再玩一次吗?"));
outtextxy(WIDTH * 0.45, 342, _T("是"));
rectangle(WIDTH * 0.4, 340, WIDTH * 0.6, 360);
outtextxy(WIDTH * 0.7, 342, _T("否"));
rectangle(WIDTH * 0.65, 340, WIDTH * 0.75, 360);
Sleep(10);
}

}

}
}

}
else
{
initgraph(800, 600);
IMAGE e;
loadimage(&e, _T("landscape4.png"));
putimage(0, 0, &e);
setbkmode(TRANSPARENT);
settextcolor(YELLOW);
settextstyle(30, 0, _T("黑体"));
outtextxy(200, 100, _T("您没有激活许可证,无法启动游戏。"));
Sleep(700);

exit(0);

}
return 0;
}

ava
Windows11

2021-12-27

0

只需要一个 initgraph 就可以了,多次执行不知有什么问题。

代码头文件 EasyXPng.h 没有

ava
xiongfj ◑◑

2021-12-27

技术讨论社区