我正致力于创建一个基于文本的Windows游戏,我遇到了一个问题(我猜),在主要功能中,数组在类范围内的工作方式不同。据我所知,它是一个更大的数组类成员(或大量变量)和Windows创建DC或其他Windows API调用和/或变量之间的某种交互。
我想要做的是有一个名为Map的类,它包含一个二维Tiles数组。 Tile只是一个带有基本tile信息的简单结构。我想使数组256 x 256.就我所知,这不应该是一个问题。每个Tile应为32个字节。这个数组总共2 MB。
但是,当我在main函数中声明Map类的变量时,游戏崩溃,然后使用Windows DC执行操作。返回值似乎有所不同,在当前形式中,它通常返回255,但我也得到了#34;进程以状态-1073741571"终止。虽然128 x 128阵列在课堂上工作。如果我删除DisplayScreen中的数组或代码,它也可以正常工作。正如我暗示的那样,如果我只是将Tiles数组移动到主函数中,它也会起作用。
我真的很困惑。我不知道会有什么区别。没有什么超出范围。无论是公共会员还是私人会员都无关紧要。非动态类成员都应该在堆栈中声明,并且在类中它不应该以不同的方式工作,对吧?对不起?有关其他信息,我使用的是Code :: Blocks和Min GW编译器。一切都是最新的。我正在运行Windows 10.我的计算机规格也不是问题,但如果重要,我有16 GB内存和4Ghz Athlon FX 8核心处理器。
编辑:这是完整的代码,因此没有遗漏任何内容
Game.h:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
struct Tile
{
char chr[2];
int r[2], b[2], g[2];
bool solid;
bool translucent;
int opacity;
};
class Map
{
Tile tileMap[256][256];
public:
Map();
};
Map::Map()
{
int i, j;
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
main.cpp中:
#include <windows.h>
#include "Game.h"
#define FRAMERATE 60
//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);
//Make the class name into a global variable
char strClassName[ ] = "GameApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd; //This is the handle for our window
MSG messages; //Here messages to the application are saved
WNDCLASSEX wndClassEx; //Data structure for the windowclass
Map test;
DWORD sysTimer;
DWORD sysPrevTime = 0;
DWORD timerDelta = 1000 / FRAMERATE;
//Get a handle for the whole screen
HDC hDC = GetDC(NULL);
//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL; //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));
//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;
//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName, //Class name
"Game Test", //Title Text
WS_OVERLAPPEDWINDOW, //default window type
0, //X pos of window at top left
0, //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP, //Child-window to desktop
NULL, //No menu
hThisInstance, //Program Instance handler
NULL); //No Window Creation data
//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);
//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}
TranslateMessage(&messages);
DispatchMessage(&messages);
}
sysTimer = timeGetTime();
if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}
}
}
//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}
void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);
HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);
SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));
//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World @", 15);
//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);
//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);
DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}
即使是创建DC的某个实例,它也会崩溃。它工作正常,否则创建和销毁DC并反复显示位图,即使我离开它一小时。一旦我用它中的大数组创建了那个类,它就会死掉。
我实际上曾经将Display功能作为一个类功能,我把它移出去是因为我认为这是问题,但它不是。
有趣的是,如果我从“地图测试”中更改声明;&#39;到地图*测试=新地图;&#39;并适当地改变程序的其余部分,它的工作原理。老实说,这样做看起来有点愚蠢,而且我认为如果我没有充分的理由将所有东西放在堆上,这会减慢一切。另外,我不喜欢绷带。如果有问题,我宁愿修理它。
有什么想法吗?
答案 0 :(得分:0)
你有一个堆栈溢出(条件,而不是网站)。
答案 1 :(得分:0)
这个问题可以在这个程序中重现:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}
它失败,因为它达到了堆栈限制。
同样tileMap[i][j].chr[2]
不受限制。声明为char chr[2];
有效索引为0和1.它最多只能达到tileMap[i][j].chr[1]
同上b[]
,r[]
和g[]
更改Map
类,以便它在堆上分配内存并修复chr
:
class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};
Map::Map()
{
int i, j;
tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];
for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X'; //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}