Link to home
Start Free TrialLog in
Avatar of hauntedfury
hauntedfury

asked on

Problem with Loops!

I am developing a Tetris Game as my OOP Project using Win32 SDK .
The problem i am facing is that first of all the game just takes up all of the CPU and after 1-2 mins its just gets Stuck...........I have checked the loops but they cant be wrong as they seem to work fine for the first 3-5 iterations but then suddenly the game gets stuck

The code is as follows :



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CODE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include<iostream.h>
#include <windows.h>
#include "Resource.h"

HWND hwnd;
HDC dc,memDC;
HBITMAP MainBMP;
HINSTANCE hInst;
int MAX_X=23,MAX_Y=27;

CONST ID_TIMER=1;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

class Block
{
private:
      bool block[4][4];
      int x,y;
      int maxX;
public:
      Block();
      Block(int type);
      Block(int type,int xc,int yc);
      int getX();
      void setX(int xc);
      int getY();
      void setY(int yc);
      void setBlockType(int type);
      void Rotate();
      void Draw(int xc,int yc);
      void fillZeros();
      void Print();
      void moveLeft();
      void moveRight();
      void moveDown();
      void setIndex(int i,int j,bool k);
      bool getIndex(int i,int j);
      int getMaxX();
};

int Block::getMaxX()
{
return maxX;
}
void Block::setIndex(int i,int j,bool k)
{
      block[i][j]=k;
}
bool Block::getIndex(int i,int j)
{
      return block[i][j];
}

void Block::moveLeft()
{
      if(x>0)
      x--;
}
void Block::moveRight()
{
      if(x<(23-maxX))
      x++;
}
void Block::moveDown()
{
      if(y<23)
      y++;
}

void Block::Rotate()
{
      bool temp[4][4];
      
      for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
            {
                  temp[j][3-i]=block[i][j];
            }
            for(i=0;i<4;i++)
                  for(int j=0;j<4;j++)
                        block[i][j]=temp[i][j];
}

Block::Block(int type,int xc,int yc)
{
      x=xc;
      y=yc;
      fillZeros();
      setBlockType(type);
}

Block::Block(int type)
{
      x=0;y=0;
      fillZeros();
      setBlockType(type);
}

void Block::setBlockType(int type)
{
      fillZeros();
      switch(type)
      {
      case 1:
            block[2][0]=1;
            block[2][1]=1;
            block[3][0]=1;
            block[3][1]=1;
            maxX=2;
            break;
      case 2:
            block[3][0]=1;
            maxX=1;
            break;
      case 3:
            block[0][0]=1;
            block[0][1]=1;
            block[0][2]=1;
            block[1][1]=1;
            block[2][1]=1;
            block[3][1]=1;
            maxX=3;
            break;
      case 4:
            *(*(block+0)+0)=1;
            *(*(block+1)+0)=1;
            *(*(block+2)+0)=1;
            
            *(*(block+0)+1)=1;
            break;
      case 5:
            *(*(block+0)+2)=1;
            *(*(block+1)+2)=1;
            *(*(block+2)+2)=1;
            
            *(*(block+0)+1)=1;
            
            break;
      case 6:
            *(*(block+1)+1)=1;
            *(*(block+1)+2)=1;
            
            *(*(block+2)+2)=1;
            break;
      case 7:
            *(*(block+1)+0)=1;
            *(*(block+1)+1)=1;
            *(*(block+1)+2)=1;
            
            *(*(block+0)+1)=1;
            *(*(block+2)+1)=1;
            break;
      case 8:
            *(*(block+2)+0)=1;
            *(*(block+2)+1)=1;
            *(*(block+2)+2)=1;
            
            *(*(block+0)+1)=1;
            *(*(block+1)+1)=1;
            break;
      case 9:
            *(*(block+0)+0)=1;
            *(*(block+0)+1)=1;
            *(*(block+0)+2)=1;
            
            *(*(block+1)+1)=1;
            *(*(block+2)+1)=1;
            break;
      case 10:
            block[1][1]=1;
            block[1][2]=1;
            block[2][1]=1;
            block[2][2]=1;
            break;
      }
      
}

Block::Block()
{
      x=0;
      y=0;
      fillZeros();
      setBlockType(1);
      
}

void Block::fillZeros()
{
      for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
            {
                  block[i][j]=0;
            }
}

void Block::Print()
{
      cout<<"Position : ("<<x<<","<<y<<")"<<endl;;
      for(int i=0;i<4;i++)
      {
            for(int j=0;j<4;j++)
            {
                  cout<<*(*(block+i)+j)<<" ";
            }
            cout<<endl;
      }
}

int Block::getX()
{
      return x;
}

void Block::setX(int xc)
{
      x=xc;
}

int Block::getY()
{
      return y;
}

void Block::setY(int yc)
{
      y=yc;
}


class Maze
{
private:
      int **maze;
      int len,wid;
public:
      Maze();
      Maze(int length,int width);
      void fillZeros();
      void Print();
      void setIndex(int,int,int);
      int getIndex(int,int);
      void insertBlock(Block b);
      void deleteRow(int n);
};

void Maze::deleteRow(int n)
{
      for(int i=n;i>0;i--)
            for(int j=0;j<23;j++)
            {
            setIndex(j,i,getIndex(j,i-1));
            }

}

void Maze::insertBlock(Block block)
{
int x=block.getX();
int y=block.getY();

for(int i=0;i<4;i++)
      for(int j=0;j<4;j++)
      {
      setIndex(x+j,y+i,block.getIndex(i,j));
      }

}
Maze::Maze()
{
      len=25;
      wid=10;
      maze=new int*[len];
      for(int i=0;i<len;i++)
            *(maze+i)=new int[wid];
      fillZeros();
}


Maze::Maze(int length,int width)
{
      len=length;
      wid=width;
      maze=new int*[len];
      for(int i=0;i<len;i++)
            *(maze+i)=new int[wid];
      
      fillZeros();
}

void Maze::Print()
{
      for(int i=0;i<len;i++)
      {
            for(int j=0;j<wid;j++)
            {
                  cout<<*(*(maze+i)+j)<<" ";
            }
            cout<<endl;
      }
}
void Maze::fillZeros()
{
      for(int i=0;i<len;i++)
            for(int j=0;j<wid;j++)
            {
                  *(*(maze+i)+j)=0;
            }
}

void Maze::setIndex(int r,int c,int v)
{
      *(*(maze+r)+c)=v;
}
int Maze::getIndex(int r,int c)
{
      return *(*(maze+r)+c);
}


class Tetris
{
private:
      Maze tetrisMaze;
      Block currentBlock;
      Block nextBlock;
      int state;
public:
      Tetris();
      generateRandomBlock();
      void Main();
      void Game(int param);
      void Run(int state,int param);
      void sendMessage(int mess);
      void checkHit();
      void setState(int st);
      int getState();
      
      
};

void Tetris::setState(int st)
{
state=st;
}
int Tetris::getState()
{
return state;
}
      
void Tetris::checkHit()
{
int check=1;
for(int i=0;i<27;i++)
{
      for(int j=0;j<23;j++)
      {
      if(tetrisMaze.getIndex(j,i)==0)
            {
            check=0;
            break;
            }
            else
            {
            check=1;
            }
      }
      if(check==1)
            {
            tetrisMaze.deleteRow(i);            
            }
      
}

}
// Key=1 for Space (ASCII-32)
// Key=2 for Left (ASCII-37)
// Key=3 for Right (ASCII-39)
// Key=4 for Down (ASCII-40)
// Key=5 For ESC (ASCII-27)
void Tetris::sendMessage(int mess)
{
      switch(mess)
      {
      case 1:
            currentBlock.Rotate();
            break;
      case 2:
            currentBlock.moveLeft();
            break;
      case 3:
            currentBlock.moveRight();
            break;
      case 4:
            currentBlock.moveDown();
            break;
      case 5:
            break;
            
      }
}


Tetris::Tetris():tetrisMaze(23,27),currentBlock(1,0,0)
{
      
      //for(int i=0;i<23;i++)
      //      for(int j=22;j<27;j++)
      //            tetrisMaze.setIndex(i,j,1);
}
HDC          hdcMem;
HBITMAP      hbmMem;
HANDLE       hOld;

PAINTSTRUCT  ps;
HDC          hdc;

      int tx=0,ty=0;
void Tetris::Game(int param)
{
      MainBMP=LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP2));
      memDC=CreateCompatibleDC(dc);
      SelectObject(memDC, MainBMP);
      
      hdc=GetDC(hwnd);

      hdcMem = CreateCompatibleDC(hdc);
    hbmMem = CreateCompatibleBitmap(hdc,530, 620);
    hOld   = SelectObject(hdcMem, hbmMem);
      
      BitBlt(hdcMem,0,0,530,620,memDC,0,0,SRCCOPY);

      MainBMP=LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
      memDC=CreateCompatibleDC(dc);
      SelectObject(memDC, MainBMP);


      
      // Draw Moving Block
      for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
            {
                  if(currentBlock.getIndex(i,j)==1)
                  {
                        tx=j*20+30+(currentBlock.getX()*20);
                        ty=i*20+30+(currentBlock.getY()*20) ;
                        BitBlt(hdcMem,tx,ty,20,20,memDC,0,0,SRCCOPY);
                  }
            }
      // End drawring Moving Box
            
      // Draw Boxes overlay
            for(i=0;i<MAX_Y;i++)
                  for(int j=0;j<MAX_X;j++)
                  {
                        if(tetrisMaze.getIndex(j,i)==1)
                        {
                              tx=j*20+30;
                              ty=i*20+30;
                              BitBlt(hdcMem,tx,ty,20,20,memDC,0,0,SRCCOPY);
                        }
                  }
      // End Drawing Boxes Overlay
                  
      
      BitBlt(hdc, 0, 0,530,620, hdcMem, 0, 0, SRCCOPY);
      DeleteDC(memDC);
      DeleteDC(hdc);
      DeleteDC(hdcMem);
      ReleaseDC(hwnd,hdc);
      
      // Move Block
      if(param==1)
      {
            if(currentBlock.getY()<23)
                  currentBlock.setY(currentBlock.getY()+1);
             else
             {
                   tetrisMaze.insertBlock(currentBlock);
                   currentBlock.setX(0);
                   currentBlock.setY(0);
             }
      }
      // End Moving block
      checkHit();
                  
}

void Tetris::Main()
{
      
      dc=GetDC(hwnd);
      MainBMP=LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
      memDC=CreateCompatibleDC(dc);
      SelectObject(memDC, MainBMP);
      BitBlt(dc, 1, 1, 600, 600, memDC, 0, 0, SRCCOPY);
      DeleteDC(memDC);
      
}

void Tetris::Run(int state,int param)
{
      switch(state)
      {
      case 1:
            Main();
            break;
      case 2:
            Game(param);
            break;
      }
}

Tetris tetris;

LRESULT CALLBACK WndProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
{
      int virtual_code=0;
      int state=0;
      int xPos = LOWORD(lParam);  // horizontal position of cursor
      int yPos = HIWORD(lParam);  // vertical position of cursor
      switch(message){
            
      case WM_KEYUP:
      
            virtual_code = (int)wParam;
            // Key=1 for Space (ASCII-32)
            // Key=2 for Left (ASCII-37)
            // Key=3 for Right (ASCII-39)
            // Key=4 for Down (ASCII-40)
            // Key=5 For ESC (ASCII-27)

            switch(wParam)
            {
            case VK_SPACE:
                  tetris.sendMessage(1);
                  SendMessage(hwnd,WM_PAINT,0,0);
                  break;
            case VK_LEFT:
                  tetris.sendMessage(2);
                  SendMessage(hwnd,WM_PAINT,0,0);
                  break;
            case VK_RIGHT:
                  tetris.sendMessage(3);
                  SendMessage(hwnd,WM_PAINT,0,0);
                  break;
            case VK_DOWN:
                  tetris.sendMessage(4);
                  SendMessage(hwnd,WM_PAINT,0,0);
                  break;
            case VK_ESCAPE:
                  tetris.sendMessage(5);
                  break;
                  
            }
            return 0;
            break;
            case WM_ERASEBKGND:
                  return 1;
                  break;
            case WM_PAINT:
                  state=tetris.getState();
                  switch(state)
                  {
                  case 1:
                        tetris.Main();
                        break;
                  case 2:
                        tetris.Game(1);
                        break;
                  case 3:
                        MessageBox(hwnd,"Thank you for Playing!","TetriX",1);
                        exit(0);
                        break;      
                  }
                  break;
                  case WM_CLOSE:
                        PostQuitMessage(0);
                        return 0;
                        
                  case WM_LBUTTONUP:
                        
                        if((xPos>190&&xPos<325)&&(yPos>345&&yPos<380))
                        {
                              MessageBox(hwnd,"Start Game!","TetRiX",0);
                              tetris.setState(2);
                        }
                        if((xPos>190&&xPos<325)&&(yPos>396&&yPos<432))
                        {
                              MessageBox(hwnd,"TetriX!\nProject of OOP!","TetRiX",0);
                        }
                        if((xPos>212&&xPos<310)&&(yPos>450&&yPos<486))
                        {
                              MessageBox(hwnd,"Bubyez!","TetRiX",0);
                              exit(0);
                        }
                        
                        break;
                  
                  case WM_TIMER:
                  SendMessage(hwnd,WM_PAINT,1,1);      
                  break;
                  /*state=tetris.getState();
                        switch(state)
                        {
                        case 1:
                              tetris.Main();
                              break;
                        case 2:
                              tetris.Game(1);
                              //SendMessage(hwnd,WM_PAINT,1,1);
                              break;
                        case 3:
                              MessageBox(hwnd,"Thank you for Playing!","TetriX",1);
                              exit(0);
                              break;      
                        }
                        break;
                        */
                        
      }
    return DefWindowProc(hWnd,message,wParam,lParam);
}

///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////

INT WINAPI WinMain( HINSTANCE hinst, HINSTANCE hint, LPSTR lp, INT i)
{
      
      int ret=0;
      // Create A Window Class Structure
      WNDCLASSEX wc;
      wc.cbClsExtra = 0;
      wc.cbSize = sizeof(wc);
      wc.cbWndExtra = 0;
      wc.hbrBackground = NULL;
      wc.hCursor = NULL;
      wc.hIcon = NULL;
      wc.hIconSm = NULL;
      wc.hInstance = GetModuleHandle(NULL);
      wc.lpfnWndProc = WndProc;
      wc.lpszClassName = "VK3D";
      wc.lpszMenuName = NULL;
      wc.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC;
      hInst=hinst;
            tetris.setState(1);
              // Register Window Class
              RegisterClassEx(&wc);
              // Create Window
              HWND hWnd = CreateWindowEx(0,"VK3D","TetriX",WS_OVERLAPPEDWINDOW, 0,0,530,620,NULL,NULL,wc.hInstance,0);
              hwnd = hWnd;
              ShowWindow(hWnd,SW_SHOW);
              // Message Loop
              MSG msg;
              ret=SetTimer(hwnd,ID_TIMER, 100,NULL);
              while(true){
                    if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE)){
                          if(msg.message==WM_QUIT)break;
                          TranslateMessage(&msg);
                          DispatchMessage(&msg);
                         
                    }
              }
             
              return 0;
}

Hope u can help me.........
ASKER CERTIFIED SOLUTION
Avatar of furqanchandio
furqanchandio

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Can I suggest you break Game into two, one to redraw that is called on the WM_PAINT message and one to actually do the intelligence that is done on timer. I'd suspect that posting a WM_PAINT message on timer to achieve this will break just as you describe or at least get you into deep kaka later down the line. This method is clearly a hack that should be removed at the earliest opportunity.

I'd also suggest you post a link to this question in the Games arena.

Paul
Avatar of wayside
wayside

No comment has been added to this question in more than 21 days, so it is now classified as abandoned..
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: furqanchandio

Any objections should be posted here in the next 4 days. After that time, the question will be closed.

wayside
EE Cleanup Volunteer