c++ - 运行程序后 Windows 控制台帧率下降
问题描述
正如标题所示,我在 C++ 中的 Windows 控制台应用程序存在问题。到目前为止,我已经创建了一个类,Console,来表示我重复用于构建 Windows 控制台的所有函数。我实现了一个画线算法,当用洋红色字符填充屏幕并用白色画一条线时,速度高达 500 fps。但是,接下来我实现了一个三角形绘制算法(仅连续调用三个线条绘制),并惊讶地发现帧速率下降到 20 左右。我再次删除了这段代码,但糟糕的帧速率仍然存在。我真的不知道为什么会发生这种情况,因为我基本上没有改变任何东西。
作为参考,这里是控制台代码(没有标题):
Console::Console(int width, int height):
m_handle(GetStdHandle(STD_OUTPUT_HANDLE)),
m_width(width),
m_height(height),
m_screen({ 0, 0, 1, 1 }),
m_title(L"Demo"),
m_buffer(new CHAR_INFO[(size_t)m_width * (size_t)m_height])
{
memset(m_buffer, 0, sizeof(CHAR_INFO) * m_width * m_height);
}
Console::~Console()
{
if (m_buffer)
delete[] m_buffer;
}
int Console::Construct(int char_w, int char_h)
{
if (m_handle == INVALID_HANDLE_VALUE)
return BAD_HANDLE;
if (!SetConsoleWindowInfo(m_handle, true, &m_screen))
return WINDOW_INFO_ERROR;
COORD screen_coord = { (short)m_width, (short)m_height };
if (!SetConsoleScreenBufferSize(m_handle, screen_coord))
return SCREEN_BUFFER_SIZE_ERROR;
CONSOLE_FONT_INFOEX cinfo;
cinfo.cbSize = sizeof(cinfo);
cinfo.dwFontSize.X = (short)char_w;
cinfo.dwFontSize.Y = (short)char_h;
cinfo.FontFamily = FF_DONTCARE;
cinfo.FontWeight = FW_NORMAL;
cinfo.nFont = 0;
wcscpy_s(cinfo.FaceName, L"Consolas");
if (!SetCurrentConsoleFontEx(m_handle, false, &cinfo))
return CONSOLE_FONT_ERROR;
CONSOLE_SCREEN_BUFFER_INFO cbuffinfo;
if (!GetConsoleScreenBufferInfo(m_handle, &cbuffinfo))
return GET_BUFFER_INFO_ERROR;
if (cbuffinfo.dwMaximumWindowSize.X < m_width)
return HORIZONTAL_SIZE_TOO_LARGE_ERROR;
if (cbuffinfo.dwMaximumWindowSize.Y < m_height)
return VERTICAL_SIZE_TOO_LARGE_ERROR;
m_screen = { 0, 0, (short)m_width - 1, (short)m_height - 1 };
if (!SetConsoleWindowInfo(m_handle, true, &m_screen))
return WINDOW_INFO_ERROR;
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandleClose, true))
return CLOSE_HANDLER_ERROR;
return OK;
}
void Console::Start()
{
active = true;
std::thread t(&Console::DoLoop, this);
t.join();
}
void Console::DoLoop()
{
if (!OnCreate())
active = false;
std::chrono::high_resolution_clock::time_point t1, t2;
t1 = std::chrono::high_resolution_clock::now();
t2 = t1;
while (active)
{
t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> diff = t2 - t1;
t1 = t2;
float dt = diff.count();
if (!OnUpdate(dt))
active = false;
wchar_t title_buff[256];
swprintf_s(title_buff, L"Console Application - %s - FPS: %3.2f", m_title.c_str(), 1.0f / dt);
SetConsoleTitle(title_buff);
WriteConsoleOutput(m_handle, m_buffer, { (short)m_width, (short)m_height }, { 0, 0 }, &m_screen);
}
finished.notify_one();
}
void Console::Fill(int x, int y, short glyph, short color)
{
if (x < 0 || y < 0 || x >= m_width || y >= m_height) return;
CHAR_INFO& ci = m_buffer[y * m_width + x];
ci.Char.UnicodeChar = glyph;
ci.Attributes = color;
}
void Console::Fill(int x1, int y1, int x2, int y2, short glyph, short color)
{
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x1 >= m_width) return;
if (y1 >= m_height) return;
if (x2 >= m_width) x2 = m_width - 1;
if (y2 >= m_height) y2 = m_height - 1;
if (x2 < 0) return;
if (y2 < 0) return;
for (int x = x1; x <= x2; x++)
{
for (int y = y1; y <= y2; y++)
{
CHAR_INFO& ci = m_buffer[y * m_width + x];
ci.Char.UnicodeChar = glyph;
ci.Attributes = color;
}
}
}
void Console::Clear(short glyph, short color)
{
for (int x = 0; x < m_width; x++)
{
for (int y = 0; y < m_height; y++)
{
CHAR_INFO& ci = m_buffer[y * m_width + x];
ci.Char.UnicodeChar = glyph;
ci.Attributes = color;
}
}
}
void Console::Line(int x1, int y1, int x2, int y2, short glyph, short color)
{
int dx = x2 - x1;
int dy = y2 - y1;
int adx = dx > 0 ? dx : -dx;
int ady = dy > 0 ? dy : -dy;
int dy2 = dy + dy;
int dx2 = dx + dx;
int adx2 = dx2 > 0 ? dx2 : -dx2;
int ady2 = dy2 > 0 ? dy2 : -dy2;
if (adx > ady)
{
if (x1 > x2)
{
int x = x1;
x1 = x2;
x2 = x;
dx = -dx;
dx2 = -dx2;
int y = y1;
y1 = y2;
y2 = y;
dy = -dy;
dy2 = -dy2;
}
int sy = dy > 0 ? 1 : dy < 0 ? -1 : 0;
int err = ady;
for (int x = x1, y = y1; x <= x2; x++)
{
Fill(x, y, glyph, color);
err += ady2;
if (err > adx2)
{
err -= adx2;
y += sy;
}
}
}
else
{
if (y1 > y2)
{
int x = x1;
x1 = x2;
x2 = x;
dx = -dx;
dx2 = -dx2;
int y = y1;
y1 = y2;
y2 = y;
dy = -dy;
dy2 = -dy2;
}
int sx = dx > 0 ? 1 : dx < 0 ? -1 : 0;
int err = adx;
for (int x = x1, y = y1; y <= y2; y++)
{
Fill(x, y, glyph, color);
err += adx2;
if (err > ady2)
{
err -= ady2;
x += sx;
}
}
}
}
void Console::Triangle(int x1, int y1, int x2, int y2, int x3, int y3, short glyph, short color)
{
Line(x1, y1, x2, y2, glyph, color);
Line(x2, y2, x3, y3, glyph, color);
Line(x3, y3, x1, y1, glyph, color);
}
BOOL Console::HandleClose(DWORD evt)
{
if (evt == CTRL_CLOSE_EVENT)
{
active = false;
std::unique_lock<std::mutex> ul(lock);
finished.wait(ul);
}
return true;
}
这是非常短的主要代码:
class Game : public Console
{
public:
Game(int width, int height):
Console(width, height)
{
}
bool OnCreate() override
{
return true;
}
bool OnUpdate(float dt) override
{
Clear(GLYPH_SOLID, FG_BLACK);
//Triangle(20, 20, 300, 40, 150, 200);
return true;
}
};
int main()
{
Game game(400, 300);
int err = game.Construct(2, 2);
if (err == Console::OK)
game.Start();
}
错误常量只是在头文件中定义的整数代码。如果需要任何其他代码,请告诉我。提前致谢!
编辑:
解决方案
推荐阅读
- node.js - TypeError:过去必须是字符串或缓冲区
- azure-sql-database - 如果 Azure SQL 的故障转移组已经具有高可用性,那么它的用途是什么?
- python - 使用保存的 Word2Vec 模型时发出警告
- cocoa - 在 Mojave 上禁用 NSScrollView 内部的活力?
- apache-spark - 从文本中近乎实时地提取表情符号
- python - 使用正则表达式从字符串中提取多个单词
- java - 如何通过 Selenium 认证进行测试?
- tpm - SGX 能否证明两个飞地位于不同的计算机上?
- c# - C# 从二叉搜索树创建 TreeView
- django - 如何使用 python manage.py runserver 命令在本地系统中以 https 方式运行 Django 服务器