2015-12-29 9 views
-1

Я пишу код для того, что должно быть тетрисовой игрой. Это на ранней стадии, и сейчас он отображает только одну часть (кусок, который будет «падать» в этот момент), и это все, что он должен делать. Стрелка вверх позволяет вам перемещаться вперед (в частности, только) через случайно сформированную последовательность фигур (используя метод «мешок»). И, используя левую и правую стрелки, вы можете вращать фигуры. В любом случае, он закодирован на платформе 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. Помогите ... пожалуйста (и спасибо).

+1

Слишком много несвязанного текста. Ваша проблема не связана с * Tetris *. Пожалуйста, сформулируйте свою проблему самым кратким способом. – IInspectable

ответ

0

Ooh, старые школьные окна программирования ...

Это не может быть полнота проблемы, но в вашей setColor функции вы создаете Pen с CreatePen но не называя DeleteObject на нем. Это приведет к утечке ресурса и, в конечном итоге, приведет к проблемам, когда в Windows заканчивается использование ресурсов для объектов.

Кроме того, Контекст устройства, возвращаемый BeginPaint, является (как правило) действительным только до вызова EndPaint (если вы не указали иначе в вызове CreateWindow, если я правильно помню). Это может стать еще одним источником утечки ручек.

На вкладке «Процесс» диспетчера задач вы можете добавить столбец «GDI objects», который будет увеличиваться по мере запуска вашей программы, если вы пропустите ручки. Я видел это однажды с чем-то, что я написал назад, когда.

+1

Столбец в диспетчере задач называется * GDI-объектами *. Столбец * Ручки * относится к объектам ядра, а не к объектам GDI. – IInspectable

+0

Спасибо, кажется (пока), чтобы работать, и это не так. Это не похоже на фортран. Tsk Tsk, заносчивые программисты. Что предложит могущественный 1201ProgramAlarm? –

+0

@Inpectable Fixed; Я уходил (все больше и больше недостоверной) памяти. – 1201ProgramAlarm