Я пишу код для того, что должно быть тетрисовой игрой. Это на ранней стадии, и сейчас он отображает только одну часть (кусок, который будет «падать» в этот момент), и это все, что он должен делать. Стрелка вверх позволяет вам перемещаться вперед (в частности, только) через случайно сформированную последовательность фигур (используя метод «мешок»). И, используя левую и правую стрелки, вы можете вращать фигуры. В любом случае, он закодирован на платформе win32, и я обнаружил, что после определенного количества кадров (работает WM_PAINT) основной HDC становится нулевым, и все останавливается. Для достижения этого требуется примерно вдвое больше кадров для удержания клавиш со стрелками вправо или влево, чтобы удерживать клавишу со стрелкой вверх. Что-то странное в том, что после примерно 1000 кадров область консоли, которую я активно рисую (рамка размером 600x600 пикселей), станет черной (hdc еще не был аннулирован), и только когда стрелка вверх нажата, hdc аннулируется. Я подозреваю, что проблема заключается в том, что методы, вызываемые при нажатии клавиши со стрелкой вверх, передают hdc в качестве параметра методам внутри класса (скажите мне, является ли это плохой практикой или что-то я должен делать вместо этого). Я думаю, что hdc может быть развращающим или чем-то (честно говоря, я понятия не имею). Клавиши со стрелками влево и вправо не напрямую вызывают методы с использованием HDC в качестве параметра. Из-за ярлыков case и того, как разработан шаблон win32, я должен хранить HDC, область видимости которого выпадает из любого фреймворка, так что я могу получить доступ к ручке окна за пределами поля для рисования (я чувствую, что это плохая практика, но я хотел бы понять, почему, прежде чем я уйду с дороги, чтобы найти новый способ). Я отправлю код, сохраненный HDC называется mainHDC, и он определен непосредственно перед оператором основного случая. Чтобы узнать вас, я дам обзор структуры кода:C++ Win32: HDC и отладка
Главный .cpp-файл, содержащий основную программу win32, вызывает конструктор класса Tetris в WM_PAINT и сохраняет его повсеместно, как mainHDC, и, при подсказке «следующий» метод (который приносит следующий фрагмент), метод «turnPiece» (который вращает кусок по часовой стрелке или против часовой стрелки на основе параметра) и метод «краски», который обновляет экран, перекраивая текущий шт. В классе tetris (который находится в собственном заголовочном файле) существует подкласс «части», который содержит информацию о его объектах, которые определяются другим уровнем подклассов, названных одним символом, изображенным частицами форма. Форма, цвет и размер фигур хранятся в 2-х массивах указателей (с использованием COLORREF). «Pieces» содержит свой собственный метод DrawObject, который рисует объект, который его вызывает (который, как и все методы рисования/рисования, имеет HDC в качестве аргумента). Существует также метод, который вращает форму под названием «turnTet» (метод «turnPiece» передает вызов из основного .cpp-файла в «штуки»). Единственные другие применимые методы - это те, которые содержатся в классе «тетрис», которые являются «красками» и «следующей» (они в конечном итоге рисуют объект). Случаи 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. Помогите ... пожалуйста (и спасибо).
Слишком много несвязанного текста. Ваша проблема не связана с * Tetris *. Пожалуйста, сформулируйте свою проблему самым кратким способом. – IInspectable