如何解决我尝试使用ascii角色制作游戏,但闪烁过多
我做了一个游戏。它基本上是这样的。每半秒钟输入一次if条件,然后进行一切计算,然后将所有内容打印到控制台。这是我的游戏循环。
//game loop
while(!IsGameOver)
{
// Updates every half a second
if ((int)(elapsedtime / 500) > PrevIoUsRoundQSec)
{
PrevIoUsRoundQSec = (int)(elapsedtime / 500);
BulletCalculation(bullets);
RemoveBulletsOutsideOfTheBoard(bullets,BoardLength);
HealthCalculation(SpaceShips,bullets);
RemoveDead(SpaceShips,bullets);
DrawGame(BoardWidth,BoardLength,SpaceShips,bullets);
}
// Updates EverySecond
if ((int)(elapsedtime / 1000) > PrevIoUsRoundSec)
{
PrevIoUsRoundSec = (int)(elapsedtime / 1000);
PreDir = HordLogic(SpaceShips,bullets,BoardWidth,PreDir,PreNearBorder);
}
IsGameOver = GameOver(SpaceShips);
// To keep time
auto end = chrono::steady_clock::Now();
elapsedtime = chrono::duration_cast<chrono::milliseconds>(end - start).count();
}
起初,我尝试cout
计算完每个字符。但是它的打印效果很差,您可以看到单独打印每个字符。那确实很糟糕。在互联网上进行搜索后,我发现printf
func更快,但也没有真正帮助到我。我最后的灵魂是在字符串中添加evey字符并立即打印该字符串。这是最好的解决方案,但还不够,因为您可以看到游戏闪烁,这会使一切变得复杂。
这是我的绘图功能的最新版本。
void DrawGame(int BoardWidth,int BoardLength,vector<Entity*> &SpaceShips,vector<Bullet> &bullets)
{
system("cls");
string screen = "";
for (int x = 0; x < BoardWidth + 2; x++)
{
screen += (char)178;
}
screen += "\n";
for (int y = 1; y < BoardLength + 1; y++)
{
for (int x = 0; x < BoardWidth + 2; x++)
{
if (x == 0 || x == BoardWidth + 1)
{
screen += (char)178;
}
else
{
bool enteredIf = false;
for (int i = 0; i < SpaceShips.size(); i++)
{
// Tough Enemy drawing
if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 't')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 't')
{
screen += "#";
enteredIf = true;
}
//Idle Enemy drawing
if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'i')
{
screen += "U";
enteredIf = true;
}
//Shooting Enemy Drawing
if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
{
screen += "#";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 's')
{
screen += "/";
enteredIf = true;
}
else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 's')
{
screen += "\\";
enteredIf = true;
}
//Player Drawing
if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'p')
{
screen += "^";
enteredIf = true;
}
else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
{
screen += "<";
enteredIf = true;
}
else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
{
screen += "_";
enteredIf = true;
}
else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
{
screen += ">";
enteredIf = true;
}
}
if (!enteredIf)
{
screen += " ";
}
}
}
screen += "\n";
}
for (int x = 0; x < BoardWidth + 2; x++)
{
screen += (char)178;
}
// draw bullets
for (int i = 0; i < bullets.size(); i++)
{
if (bullets[i].GetDir() == 's')
{
screen.at(((bullets[i].y * (BoardWidth + 3)) - 1) + (bullets[i].x + 1)) = (char)203;
}
else if (bullets[i].GetDir() == 'w')
{
screen.at(((bullets[i].y* (BoardWidth + 3)) - 1) + (bullets[i].x + 1)) = (char)202;
}
}
screen += "\n Remaining lives: ";
screen += itoa(SpaceShips[0]->hp);
cout << screen;
}
这是游戏的外观(我没有看到任何禁止共享链接的规则。如果可以的话,欢迎提出警告):https://www.loom.com/share/1bcc97fa0cbe4ee3aec62e317b10fcd0
解决方法
您正在使用std::cout
可能是问题所在。标准输出流与终端交互的方式是连续的行序列,随着新行的添加,它们自然会向上滚动。您需要与终端进行较低级别的交互,从而可以更好地控制其行为。
一个这样的选项是在Unix系统上使用ncurses library(在Windows命令行上使用PDCurses)
这将允许您使用“固定”终端窗口,并在该固定窗口上设置字符的值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。