【发布时间】:2015-12-29 02:41:00
【问题描述】:
我正在为俄罗斯方块游戏编写代码。这是早期的,现在它只显示一个单件(此时将“下降”的件),这就是它应该做的。向上箭头允许您通过随机生成的片段序列(使用“袋子”方法)向前循环(特别是)。并且,使用左右箭头,您可以旋转碎片。无论如何,它是在 win32 平台上编码的,我发现在一定数量的帧(运行 WM_PAINT)之后,主 HDC 变为空,一切都停止了。按住向右或向左箭头键所需的帧数大约是按住向上箭头键所需帧数的两倍。奇怪的是,在大约 1000 帧之后,我正在积极绘制的控制台区域(一个 600x600 像素的帧)将变黑(hdc 还没有被取消),只有当按下向上箭头时hdc 无效。我怀疑的问题是按下向上箭头键时调用的方法将 hdc 作为参数传递给类内方法(告诉我这是不是不好的做法,或者我应该做些什么)。我认为 hdc 可能正在损坏或其他东西(老实说我不知道)。左右方向键不直接调用以 HDC 为参数的方法。由于案例标签和win32模板的设计方式,我必须存储一个范围不属于任何案例标签的HDC,这样我就可以在油漆箱之外访问窗口的句柄(我觉得这是不好的做法,但我想在我竭尽全力寻找新方法之前了解原因)。我将发布代码,存储的 HDC 称为 mainHDC,它是在 main case 语句之前定义的。为了提示您,我将概述代码结构:
包含基本 win32 程序的主 .cpp 文件调用 WM_PAINT 中的俄罗斯方块类构造函数,并像 mainHDC 一样普遍存储它,当提示时,“next”方法(带来下一个片段), “turnPiece”方法(根据参数顺时针或逆时针旋转棋子)和“paint”方法更新屏幕,重新绘制当前棋子。在俄罗斯方块类(在它自己的头文件中)中,有一个名为“pieces”的子类,其中包含有关其对象的信息,这些信息由另一个级别的子类定义,这些子类以碎片所描绘的单个字符命名形状。碎片的形状、颜色和大小存储在一个二维指针数组中(使用 COLORREF)。 “Pieces”包含自己的“DrawObject”方法,该方法绘制调用它的对象(与所有绘图/绘画方法一样,都有一个 HDC 作为参数)。还有一种旋转形状的方法称为“turnTet”(“turnPiece”方法将调用从主 .cpp 文件中继到“pieces”)。其他唯一适用的方法是在“俄罗斯方块”类中找到的方法,它们是“绘制”和“下一步”(它们最终绘制对象)。 WM_KEY 情况,不包括 VK_UP 情况,不使用保存的 hdc,而是使用 InvalidateRect()。
这是 .cpp 文件的适用部分
int tempt = 2;
int tempvar = 0;
tetris *mainOBJ;
HDC mainHDC;
HDC testHDC;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN:
switch (wParam) {
case VK_LEFT:
mainOBJ->turnPiece(false);
InvalidateRect(hWnd, 0, FALSE);
break;
case VK_RIGHT:
mainOBJ->turnPiece(true);
InvalidateRect(hWnd, 0, FALSE);
break;
case VK_UP:
mainOBJ->next(mainHDC);
InvalidateRect(hWnd, 0, FALSE);
break;
}
break;
case WM_COMMAND:
//Non-applicable & has not been changed
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
mainHDC = hdc;
HPEN oldP;
HPEN newP;
COLORREF qLC;
qLC = RGB(0, 0, 0);
newP = CreatePen(PS_SOLID, 1, qLC);
oldP = (HPEN) SelectObject(hdc, newP);
tempt++;
//USED FOR COUNTING FRAMES WITH DEBUGGER
if (tempt % 1 == 0) {
if (tempvar == 0) {
//CONSTRUCTOR CALL
mainOBJ = new tetris(hdc);
tempvar++;
}
//PAINT METHOD CALL
mainOBJ->paint(hdc);
}
if (hdc == NULL) {
int x = 3;
int y = x + 3; //SET DEBUG_BREAK POINT HERE
}
testHDC = hdc;
SelectObject(hdc, oldP);
DeleteObject(newP);
EndPaint(hWnd, &ps);
}
break;
}
}
头文件,包含俄罗斯方块和片断类
class tetris {
public:
class pieces {
private:
COLORREF **test;
int size;
public:
//Abbreviated for space
class O {};
class I {};
class S {};
class Z {};
class T {};
class L {};
class J {};
void setSize(int a) {
//Initializing the piece-array
test = new COLORREF*[a];
size = a;
int i = 0;
while (i < a) {
test[i] = new COLORREF[a];
i++;
}
}
void setShape(COLORREF **shape) {
test = shape;
}
void setColor(HDC hdc, COLORREF rgb) {
HPEN Penn = CreatePen(PS_SOLID, 1, rgb);
HPEN Peno = (HPEN)SelectObject(hdc, Penn);
}
static pieces getObject(char type) {
pieces Gen;
switch (type) {
case 'O':
{
//Identical (almost) to the other cases
O pcs = O();
Gen = *pcs.getObject();
return Gen;
}
break;
case 'I':
case 'S':
case 'Z':
case 'T':
case 'L':
case 'J':
return pieces();
}
void turnTet(bool clockwise) {
int i = 0;
int s;
COLORREF **shape;
int ter = size - 1;
shape = new COLORREF*[2];
while (i < size) {
shape[i] = new COLORREF[2];
s = 0;
while (s < size) {
shape[i][s] = def;
s++;
}
i++;
}
i = 0;
while (i < size) {
s = 0;
while (s < size) {
if (clockwise) {
shape[s][ter - i] = test[i][s];
}
else {
shape[ter - s][i] = test[i][s];
}
s++;
}
i++;
}
test = shape;
}
void drawObject(HDC hWnd) {
int i = 0;
int s;
while (i < size) {
s = 0;
while (s < size) {
setColor(hWnd, test[i][s]);
int scaleOfBox = 90;
DrawBox((s + 1) * scaleOfBox, (i + 1) * scaleOfBox, scaleOfBox - 1, scaleOfBox - 1, hWnd);
s++;
}
i++;
}
}
void DrawBox(int x, int y, int w, int h, HDC hdc) {
if (h < 0) {
h *= -1;
}
if (w < 0) {
w *= -1;
}
int i = 0;
while (i < h) {
MoveToEx(hdc, x, y + i, NULL);
LineTo(hdc, x + w, y + i);
i++;
}
}
};
tetris(HDC hdc) {
refresh();
bagp[cur].drawObject(hdc);
}
void next(HDC hdc) {
bagp[cur].DrawBox(0, 0, 600, 600, hdc);
bagp[cur].drawObject(hdc);
cur++;
if (cur > 6) {
refresh();
}
}
void turnPiece(bool clockwise) {
bagp[cur].turnTet(clockwise);
}
void refresh() {
srand(time(NULL));
bag[0] = rand() % 7;
int i = 1;
while (i < 7) {
bool open = false;
cur = i;
while (!open) {
bag[i] = rand() % 7;
int s = 1;
open = true;
while (s <= i) {
if (bag[i] == bag[i - s]) {
open = false;
}
s++;
}
}
i++;
}
cur = 0;
while (cur < 7) {
switch (bag[cur]) {
case 0:
bagp[cur] = pieces::getObject('O');
break;
case 2:
bagp[cur] = pieces::getObject('T');
break;
case 1:
bagp[cur] = pieces::getObject('I');
break;
case 3:
bagp[cur] = pieces::getObject('S');
break;
case 4:
bagp[cur] = pieces::getObject('Z');
break;
case 5:
bagp[cur] = pieces::getObject('L');
break;
case 6:
bagp[cur] = pieces::getObject('J');
break;
}
cur++;
}
cur = 0;
}
void paint(HDC hdc) {
COLORREF temp = def;
bagp[cur].setColor(hdc, temp);
bagp[cur].DrawBox(0, 0, 600, 600, hdc);
bagp[cur].drawObject(hdc);
}
private:
int bag[7];
int cur;
pieces bagp[7];
};
我不明白为什么 HDC 会像现在这样无效。我再次怀疑它与 hdc 如何作为参数传递或我如何保存 hdc 有关。帮助...请(谢谢)。
【问题讨论】:
-
不相关的文字过多。您的问题与 俄罗斯方块 无关。请以最简洁的方式陈述您的问题。
标签: c++ winapi parameters null gdi