Help debugging game

Started by
6 comments, last by Tset_Tsyung 11 years, 7 months ago
Hi all,

First of all this is my first post on this site - but not my first visit. I love this place!

Now I'm teaching myself how to program games. I taught myself C++ (dummies guides, online tutorials and the like) and have decided to start with my first game - a tetris clone.

Now I've gotten to a point where the blocks fall, detect collisions and lock into place (albeit in a not so pretty way) but after you drop a block on the central point, or you've played for a minute some really funky stuff hits the rendered fan.

Basically all of a sudden blocks appear at the top. Your piece can't move - but spasmodically rotates to new shapes. And the blocks at the bottom seem to morph as if they're trying out for a remake of "The Blob".

Could I post the code here and have someone help with the debugging?

Unfortunately because this is my first game I haven't used classes (totally my bad) so it may be a little harder to understand, but any help would be appreciated. I don't want to move onto any other projects until this one is nailed.

Thanks all,

Mike
Advertisement
I would suggest to learn how to use the debugger if you don't already know. You should be able to find your problem pretty quickly.
Definitely post your code here so we can take a look at it. I'll be happy to try and find a problem. Without that, it's really hard to help you.

If you're interested, I made my own C++ Tetris clone and posted it online with the source code. If you want to see how I've solved some of the problems you could take a look. It's hosted here https://sourceforge.net/projects/dujekcgames/files/
But, like yours. It was one of my first projects in C++, and as such it's very badly put together. Using header files wrong and with no classes :) so don't think thats the right way to do it. I could go back now and make it a million times better.

Out of interest, what are you using to render your game? I used SFML.
Yeah learn to use your tools, if you don't work in visual studios yet, I would suggest that you do it from now on. you can download the express edition for C++ here: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express

Also as DujekC suggested, post your code online. You could for example use sourceforge for this. There are enough ways to do just this, so you have no excuse to not do it. I and many others would love to help you. Letting other people review you code will increase your programming skills alot. People can say what things you shouldn't do and/or how you should do things better. So please share it and let us help you.

If you don't use classes yet, I would really do that. It's important that you learn how these work and how to use them. I learned C++ with this book. (I had 5th edition, but why buy old books when you can buy the 6th edition). There are also enough free books, articles and webpages available. A great start is maybe the "shiny new FAQ" by GameDev.

Looking forward to see your project!
Hi all,

Thanks for your postings.
@Falaenor - I'm pretty good at using the debugger and stepping through the code... but don't know how to check the contents of multi-dimensional arrays at any time. Think I'll impliment Text file error logging next time. That always worked in PERL for me smile.png

@Dujekc - Cool, will definitely look at your code... tomorrow, too tired now lol.

@GlenDC - Yup, way ahead of you on the visual studio express. Loving it but as I said in my reply to Falaenor having trouble find full contents of my multi-D array. I will look into using sourceforge as a means of hosting code but in the meantime I've just put the two files I've written as an attachement... Hope that's okay.

Thanks for all your help guys 'n' girls.

Mike

P.S. Pants - can't do .cpp or .h uploads so here's the contents of said files:

main.cpp:
//include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <time.h>
#include "shapes.h"
// define the screen resolution
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 800
#define STARTX 5
#define STARTY 20
// include the Direct3D Library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
// global declarations
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
LPDIRECT3DINDEXBUFFER9 i_buffer = NULL;
// function prototypes
void initD3D(HWND hWnd);
void render_frame(void);
void cleanD3D();
void init_graphics(void);
void init_light(void); // sets up the light and the material
void line_check();
bool move_check();

struct CUSTOMVERTEX {FLOAT X, Y, Z; D3DVECTOR NORMAL;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)
bool bDrop = false;
int nCompLines = 0;
int cDropSpeed = 1;
char cCurrentPiece = rand() % 7;
char cRotation = 0;
char board[10][20];
char checkboard[10][20];
char position[2] = {STARTX, STARTY};
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
srand(clock());
unsigned long timer1, timer2 = NULL;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL, "WindowClass", "Our Direct3D Program",
WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_MAXIMIZE);
// set up and initialize Direct3D
initD3D(hWnd);
// enter the main loop:
MSG msg;
timer1 = clock();
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
if(nCompLines >= 10)
{
nCompLines = 0;
cDropSpeed++;
}
/* MOVEMENT LOGIC
this controls the basic movements of the falling blocks and checks for basic collisions
*/
timer2 = clock();
// first check to see if user is dropping block at increased rate
if((bDrop == true) && ((timer2 - timer1) >= (CLOCKS_PER_SEC / 20)))
{
if(move_check())
position[1]--;
timer1 = clock();
// otherwise check for standard drop rate
}else if((timer2 - timer1) >= CLOCKS_PER_SEC / cDropSpeed)
{
if(move_check())
position[1]--;
timer1 = clock();
}
line_check();

//memcpy(checkboard,board, sizeof(board)); // copy the maing board to the checking board
render_frame();
}
// clean up DirectX and COM
cleanD3D();
return msg.wParam;
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_LEFT:
{
for(char cX = 0; cX < 4; cX++)
{
char x = position[0] + OurShapes[cCurrentPiece][cRotation][cX][0];
char y = position[1] + OurShapes[cCurrentPiece][cRotation][cX][1];
if(x == 0)
{
return 0;
} else if(board[x-1][y] == 1)
{
return 0;
}
}
position[0]--;
break;
}
case VK_RIGHT:
{
for(char cX = 0; cX < 4; cX++)
{
char x = position[0] + OurShapes[cCurrentPiece][cRotation][cX][0];
char y = position[1] + OurShapes[cCurrentPiece][cRotation][cX][1];
if(x == 9)
{
return 0;
} else if(board[x+1][y] == 1)
{
return 0;
}
}
position[0]++;
break;
}
case VK_UP:
{
if(cRotation == 3)
{
cRotation = 0;
} else
{
cRotation++;
}
break;
}
case VK_DOWN:
{
bDrop = true;
break;
}
} break;
case WM_KEYUP:
{
bDrop = false;
break;
}
default:
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// create a device class using this information and the info from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // call the function to initialize the cube
init_light(); // call the function to initialize the light and material
d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE); // turn on the 3D lighting
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); // ambient light
}
// this is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(50, 50, 255), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(50, 50, 255), 1.0f, 0);
d3ddev->BeginScene();
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// set the view transform
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (30.0f, 60.0f, -175.0f), // the camera position
&D3DXVECTOR3 (30.0f, 60.0f, 0.0f), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView);
// set the projection transform
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45),
(FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT,
1.0f, // the near view-plane
500.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);
// select the vertex and index buffers to use
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->SetIndices(i_buffer);
// start the world transform process
D3DXMATRIX matTranslate;
// render each square of the game board
for(char cBoardx = 0; cBoardx < 10; cBoardx++)
{
for(char cBoardy = 0; cBoardy < 20; cBoardy++)
{
if(board[cBoardx][cBoardy] == 1)
{
D3DXMatrixTranslation(&matTranslate, (float)cBoardx * 6.0f, (float)cBoardy * 6.0f,
1.0f);
d3ddev->SetTransform(D3DTS_WORLD, &matTranslate);
d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
}
}
}
// render each cube in the shape
for(char cX = 0; cX < 4; cX++)
{
D3DXMatrixTranslation(&matTranslate,
((float)(position[0] + OurShapes[cCurrentPiece][cRotation][cX][0])) * 6.0f,
((float)(position[1] + OurShapes[cCurrentPiece][cRotation][cX][1]))* 6.0f, 1.0f);
d3ddev->SetTransform(D3DTS_WORLD, &matTranslate);

// draw the cube
d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
}
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);

}

// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
v_buffer->Release();
i_buffer->Release();
d3ddev->Release();
d3d->Release();
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX vertices[] =
{
{ -3.0f, -3.0f, 3.0f, 0.0f, 0.0f, 1.0f, }, // side 1
{ 3.0f, -3.0f, 3.0f, 0.0f, 0.0f, 1.0f, },
{ -3.0f, 3.0f, 3.0f, 0.0f, 0.0f, 1.0f, },
{ 3.0f, 3.0f, 3.0f, 0.0f, 0.0f, 1.0f, },
{ -3.0f, -3.0f, -3.0f, 0.0f, 0.0f, -1.0f, }, // side 2
{ -3.0f, 3.0f, -3.0f, 0.0f, 0.0f, -1.0f, },
{ 3.0f, -3.0f, -3.0f, 0.0f, 0.0f, -1.0f, },
{ 3.0f, 3.0f, -3.0f, 0.0f, 0.0f, -1.0f, },
{ -3.0f, 3.0f, -3.0f, 0.0f, 1.0f, 0.0f, }, // side 3
{ -3.0f, 3.0f, 3.0f, 0.0f, 1.0f, 0.0f, },
{ 3.0f, 3.0f, -3.0f, 0.0f, 1.0f, 0.0f, },
{ 3.0f, 3.0f, 3.0f, 0.0f, 1.0f, 0.0f, },
{ -3.0f, -3.0f, -3.0f, 0.0f, -1.0f, 0.0f, }, // side 4
{ 3.0f, -3.0f, -3.0f, 0.0f, -1.0f, 0.0f, },
{ -3.0f, -3.0f, 3.0f, 0.0f, -1.0f, 0.0f, },
{ 3.0f, -3.0f, 3.0f, 0.0f, -1.0f, 0.0f, },
{ 3.0f, -3.0f, -3.0f, 1.0f, 0.0f, 0.0f, }, // side 5
{ 3.0f, 3.0f, -3.0f, 1.0f, 0.0f, 0.0f, },
{ 3.0f, -3.0f, 3.0f, 1.0f, 0.0f, 0.0f, },
{ 3.0f, 3.0f, 3.0f, 1.0f, 0.0f, 0.0f, },
{ -3.0f, -3.0f, -3.0f, -1.0f, 0.0f, 0.0f, }, // side 6
{ -3.0f, -3.0f, 3.0f, -1.0f, 0.0f, 0.0f, },
{ -3.0f, 3.0f, -3.0f, -1.0f, 0.0f, 0.0f, },
{ -3.0f, 3.0f, 3.0f, -1.0f, 0.0f, 0.0f, },
};
// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();
// create the indices using an int array
short indices[] =
{
0, 1, 2, // side 1
2, 1, 3,
4, 5, 6, // side 2
6, 5, 7,
8, 9, 10, // side 3
10, 9, 11,
12, 13, 14, // side 4
14, 13, 15,
16, 17, 18, // side 5
18, 17, 19,
20, 21, 22, // side 6
22, 21, 23,
};
// create an index buffer interface called i_buffer
d3ddev->CreateIndexBuffer(36*sizeof(short),
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&i_buffer,
NULL);
// lock i_buffer and load the indices into it
i_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, indices, sizeof(indices));
i_buffer->Unlock();
}
// this is the function that sets up the lights and materials
void init_light(void)
{
D3DLIGHT9 light; // create the light struct
D3DMATERIAL9 material; // create the material struct
ZeroMemory(&light, sizeof(light)); // clear out the light struct for use
light.Type = D3DLIGHT_DIRECTIONAL; // make the light type 'directional light'
light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); // set the light's color
light.Direction = D3DXVECTOR3(-1.0f, -0.3f, 1.0f);
d3ddev->SetLight(0, &light); // send the light struct properties to light #0
d3ddev->LightEnable(0, TRUE); // turn on light #0
ZeroMemory(&material, sizeof(D3DMATERIAL9)); // clear out the struct for use
material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set diffuse color to white
material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set ambient color to white
d3ddev->SetMaterial(&material); // set the globably-used material to &material
}
void line_check()
{
// run through each line...
for(char cY = 0; cY < 20; cY++)
{
char counter = 0;
// checking to see if any areas in the line are block free..
for(char cX = 0; cX < 10; cX++)
{
if(board[cX][cY] == 0)
{
// if so line is not complete so move onto next line...
break;
}
counter++;
}
// otherwise line obviously full
if(counter == 10)
{
// increment nCompLines as this is controls the speed
nCompLines++;
// so clear out all the blocks in the line...
for(char cClearX = 0; cClearX < 10; cClearX++)
{
board[cClearX][cY] = 0;
}

// and move all the blocks in the above rows down by one
for(char cMoveY = cY+1; cMoveY < 19; cMoveY++)
{
for(char cMoveX = 0; cMoveX < 10; cMoveX++)
{
board[cMoveX][cMoveY-1] = board[cMoveX][cMoveY];
}
}
// we need to check the same line again after it's all dropped so set it back one
cY--;
// top line has to be cleared manually
for(char cClearX = 0; cClearX < 10; cClearX++)
{
board[cClearX][19] = 0;
}
}
}
}
bool move_check()
{
for(char block = 0; block < 4; block++)
{
if((position[1] + OurShapes[cCurrentPiece][cRotation][block][1]) == 0)
{
for(char cBlock = 0; cBlock < 4; cBlock++)
{
int x = position[0] + OurShapes[cCurrentPiece][cRotation][cBlock][0];
int y = position[1] + OurShapes[cCurrentPiece][cRotation][cBlock][1];
board[x][y] = 1;
}
cCurrentPiece = rand() % 7;
position[0] = STARTX;
position[1] = STARTY;
return false;
}else
{

if(board[position[0] + OurShapes[cCurrentPiece][cRotation][block][0]]
[position[1] + OurShapes[cCurrentPiece][cRotation][block][1] -1] == 1)
{
for(char cBlock = 0; cBlock < 4; cBlock++)
{
int x = position[0] + OurShapes[cCurrentPiece][cRotation][cBlock][0];
int y = position[1] + OurShapes[cCurrentPiece][cRotation][cBlock][1];
board[x][y] = 1;
}
cCurrentPiece = rand() %7;
position[0] = STARTX;
position[1] = STARTY;
return false;
}
}
}
return true;
}




and shapes.h
#ifndef _SHAPES_
#define _SHAPES_
char OurShapes[7][4][4][2] =
{
//line
{
//rotation1
{
{0, 0},
{0, 1},
{0, 2},
{0, -1}
},
//rotation2
{
{0, 0},
{-1, 0},
{1, 0},
{2, 0}
},
//rotation3
{
{0, 0},
{0, 1},
{0, 2},
{0, -1}
},
// rotation4
{
{0, 0},
{-1, 0},
{1, 0},
{2, 0}
}
},
// square
{
//rotation1
{
{0, 0},
{1, 0},
{0, -1},
{-1, -1}
},
//rotation2
{
{0, 0},
{1, 0},
{0, -1},
{-1, -1}
},
//rotation3
{
{0, 0},
{1, 0},
{0, -1},
{-1, -1}
},
//rotation4
{
{0, 0},
{1, 0},
{0, -1},
{-1, -1}
}
},
// S
{
//rotation1
{
{0, 0},
{0, 1},
{1, 1},
{-1, 0},
},
//rotation2
{
{0, 0},
{-1, 0},
{-1, 1},
{0, -1}
},
//rotation3
{
{0, 0},
{0, 1},
{1, 1},
{-1, 0},
},
//rotation4
{
{0, 0},
{-1, 0},
{-1, 1},
{0, -1}
}
},
// S reversed
{
//rotation1
{
{0, 0},
{1, 0},
{0, 1},
{-1, 1}
},
//rotation2
{
{0, 0},
{0, -1},
{1, 0},
{1, 1}
},
//rotation3
{
{0, 0},
{1, 0},
{0, 1},
{-1, 1}
},
//rotation4
{
{0, 0},
{0, -1},
{1, 0},
{1, 1}
}
},
// L
{
//rotation1
{
{0, 0},
{0, 1},
{0, -1},
{1, -1}
},
//rotation2
{
{0, 0},
{1, 0},
{-1, 0},
{-1, -1}
},
//rotation3
{
{0, 0},
{0, -1},
{0, 1},
{-1, 1}
},
//rotation4
{
{0, 0},
{-1, 0},
{1, 0},
{1, 1}
}
},
// L reversed
{
//rotation1
{
{0, 0},
{0, 1},
{0, -1},
{-1, -1}
},
//rotation2
{
{0, 0},
{-1, 0},
{1, 0},
{-1, 1}
},
//rotation3
{
{0, 0},
{0, -1},
{0, 1},
{1, 1}
},
//rotation4
{
{0, 0},
{-1, 0},
{1, 0},
{1, -1}
}
},
// T
{
//rotation1
{
{0, 0},
{-1, 0},
{1, 0},
{0, 1}
},
//rotation2
{
{0, 0},
{0, 1},
{1, 0},
{0, -1}
},
//rotation3
{
{0, 0},
{-1, 0},
{1, 0},
{0, -1}
},
//rotation4
{
{0, 0},
{-1, 0},
{0, -1},
{0, 1}
}
}
};
#endif

Again,
thanks all
I reviewed your code in a fast way. Let me list some fast tips:

  • Don't use the old C preproccesor (#define) way to define constants. Rather use static const variables. These give you what you need without the evil macro's.
    For example: "static const int SCREEN_WIDTH = 1280;" instead of "#define SCREEN_WIDTH 1280"
  • Global declarations is something you should try to avoid. You have no classes so it's hard to have no global variables, but you really should move to classes. Maybe this can give you a start: http://www.cprogramming.com/tutorial/lesson12.html
  • You don't have to write void as a parameter if you want parameters in your function. For example: "void foo(void);" is the same as "void foo();"
  • Initiate all your variables for your structure variables. For example, on line 54-59 you init. your WNDCLASSEX variable, wc. Don't forget to init the icon members. If you want to use the default one you could just type: "//LoadIcon (nullptr, IDI_APPLICATION);"
  • Keep your code clean and readable. Maybe it is because you pasted it here in the forum, but if it isn't you should really use more new lines to group your code. Also try to keep a logical system in your tab system. And once you have a system for your tabs and other characters, like your function block stuff. Then try to keep with that system. ( Again, I don't know if this is also is on your computer, it's just how I see it on my computer )
  • Use more functions. A small example: On line 122 you check the WM_KEYDOWN windows message. Maybe you could then have a function that handles the keyboard input, this keeps your code organized and gives you more control. It also keeps your WndProc function readable.

Didn't debugged your code yet, if someone else doesn't do it, I'll do it later if I find some more spare time.
@GlenDC,

Yeah I see what you mean about the formatting - that must've been from when I copied the text from VS express to notepad, then to here.

I pretty much came to the same conclusion about the global variables just before I uploaded. I know I have read the same thing before but until I actually see the real-life advantage for myself I can't really learn to apply it - it's just the way my brains wired... with coding anyway lol.

Same thing with the functions, I had already come to a similar conclusion when trying to debug... but by that point wasn't up for overhauling the whole thing... maybe after I've got the damn thing running I will.

Many thanks for the tips - it's good to know that I'm STARTING (not there yet) to think along the right lines. And I appreciate your trying to debug it for me... I owe you one dude!
IT'S ALIVE! IT'S ALIIIIVVVEEE!

Well I say alive... it's not as dead at least.

I have found out what was causing the problem. There was a problem with the following line in the function move_check():
[source lang="cpp"] if(board[position[0] + OurShapes[cCurrentPiece][cRotation][block][0]]
[position[1] + OurShapes[cCurrentPiece][cRotation][block][1] -1] == 1)[/source]
Forgive my poor explanation skills but I'll do must to explain why this was causing a problem.

My 2-dimensional array for the board was 10*20, but with the above if statement I would sometimes be trying to read OUTSIDE of the array. The coloumns were numbered 0 - 19 (because the first address is 0). However with the shapes it would sometimes try to read from address 20 or above. I'm not sure but I believe this causes C++ to wrap around to the beginning of the array and start again, and therefore reading collisions with items at the bottom of the board DESPITE the piece being at the top. I have resoled this but adjusting it to read as follows:

[source lang="cpp"] int colx = position[0] + OurShapes[cCurrentPiece][cRotation][block][0];
int coly = position[1] + OurShapes[cCurrentPiece][cRotation][block][1] -1;

if(coly > 19)
{
continue;
}

if(board[colx][coly] == 1)[/source]

So now if the block is "outside the board" it won't bother checking for collisons and will simply move on to the next iteration of the loop.


However I now am working on a second problem and any help would again be greatly appreciated.

Sometimes the keyboard input isn't recognised. This means that the block won't sometimes move left, right, rotate or drop at the increased speed. Once you get the block to respond once it's fine until it stop... but I don't know why this is.

I'm using WindowProc for handling the keyboard input. I have read a LOT of conflicting ideas regarding the use of DirectInput over WindowProc, but since the actual DirectX documentation say use WindowProc (unless using controllers such as gamepads or joysticks).

So why is the input jamming up?

This topic is closed to new replies.

Advertisement