Original Post
I was programming the skeleton of a Direct Draw game. I decided to use a queue DS instead of acting on them immediately. However, I think I must have screwed up on one of the pointers because now I get error on calling one of the methods I will post the entirety of the code here, but the real problem occurs only when you press down a key. Main.cpp CKeyQueue.h CKeyQueue.cpp CKeyQueueItem.h CKeyQueueItem.cpp CKeyStroke.h CKeyStroke.cpp Here is the run-time error message: Unhandled exception at 0x00412406 in TileGame.exe: 0xC0000005: Access violation reading location 0x00000000. The current line of code is: CKeyQueueItem* getPrevItem() { return prevItem;}; This leads me to suspect a pointer error somewhere. I've tried to look for it, but to no avail. Thanks in advance.
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "windowsx.h"
#include "stdio.h"
#include "conio.h"
#include "CKeyQueue.h"
#include "CKeyQueueItem.h"
#include "CKeyStroke.h"
HWND hWnd; //handle to our window
HINSTANCE hInst; //handle to application instance
bool gameActive; //is the game active
CKeyQueue *keyQueue; //our keys are held in a queue.
//CKeyStroke* k = NULL;
LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
BOOL Initialise_Game();
void Game_Loop();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
Game_Loop();
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX sampleClass;
sampleClass.cbSize = sizeof(WNDCLASSEX);
sampleClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
sampleClass.lpfnWndProc = MsgHandler;
sampleClass.cbClsExtra = 0;
sampleClass.cbWndExtra = 0;
sampleClass.hInstance = hInstance;
sampleClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
sampleClass.hCursor = LoadCursor(NULL, IDC_ARROW);
sampleClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
sampleClass.lpszMenuName = NULL;
sampleClass.lpszClassName = "Sample Class";
sampleClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
return RegisterClassEx(&sampleClass);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow("Sample Class", "Sample Window", WS_POPUP | WS_VISIBLE,
(1152-640)/2, (864-480)/2, 640, 480, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
//ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_CREATE)
{
if(!Initialise_Game())
MessageBox(hWnd,"Error","Error",0);
return(0);
}
if (msg == WM_KEYDOWN)
{
keyQueue->add(new CKeyStroke((unsigned int) wparam));
}
return(DefWindowProc(hwnd, msg, wparam, lparam));
}
BOOL Initialise_Game()
{
gameActive = true;
keyQueue = new CKeyQueue();
if(!keyQueue)
return FALSE;
return TRUE;
}
void Game_Loop()
{
MSG msg;
while (gameActive)
{
//Process Messages
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//Update Screen
//Perform Game Logic
if(keyQueue->keysWaiting())
{
keyQueue->pop();
}
}
}
#pragma once
#include "CKeyQueueItem.h"
#include "CKeyStroke.h"
class CKeyQueue
{
private:
CKeyQueueItem *firstItem;
CKeyQueueItem *lastItem;
public:
CKeyQueue();
~CKeyQueue();
void add(CKeyStroke *item);
CKeyStroke pop();
CKeyQueueItem* getFirstItem() { return firstItem; };
void setFirstItem(CKeyQueueItem* newFirstItem) { firstItem = newFirstItem; };
CKeyQueueItem* getLastItem() { return lastItem; };
void setLastItem(CKeyQueueItem* newLastItem) { lastItem = newLastItem; };
bool keysWaiting();
};
#include "CKeyQueue.h"
#include "CKeyQueueItem.h"
#include "CKeyStroke.h"
CKeyQueue::CKeyQueue()
{
firstItem = 0;
lastItem = 0;
}
CKeyQueue::~CKeyQueue()
{
CKeyQueueItem* currentItem = lastItem;
while(!currentItem->getIsFirst())
{
if(currentItem->getNextItem())
delete currentItem->getNextItem();
currentItem = currentItem->getPrevItem();
}
}
void CKeyQueue::add(CKeyStroke *item)
{
if(!item)
return;
if(!firstItem)
{
firstItem = new CKeyQueueItem(item);
lastItem = firstItem;
}
else
{
lastItem->setNextItem(new CKeyQueueItem(item));
lastItem->getNextItem()->setPrevItem(lastItem);
lastItem->setIsLast(false);
lastItem = lastItem->getNextItem();
lastItem->setIsFirst(false);
}
}
CKeyStroke CKeyQueue::pop()
{
if(!firstItem)
return 0;
while(!firstItem->getCurrent()->isValid())
{
firstItem = firstItem->getNextItem();
delete firstItem->getPrevItem();
}
CKeyStroke temp = *(firstItem->getCurrent());
delete firstItem;
return temp;
}
bool CKeyQueue::keysWaiting()
{
return !(firstItem == 0); //0 = NULL
}
#pragma once
#include "CKeyStroke.h"
class CKeyQueueItem
{
private:
CKeyQueueItem *prevItem;
CKeyQueueItem *nextItem;
CKeyStroke *current;
bool isFirst;
bool isLast;
public:
CKeyQueueItem(CKeyStroke* item);
~CKeyQueueItem();
CKeyQueueItem* getPrevItem() { return prevItem;};
void setPrevItem(CKeyQueueItem* newPrevItem) { prevItem = newPrevItem; };
CKeyQueueItem* getNextItem() { return nextItem;};
void setNextItem(CKeyQueueItem* newNextItem) { nextItem = newNextItem; };
bool getIsFirst() { return isFirst; };
void setIsFirst(bool newIsFirst) { isFirst = newIsFirst; };
bool getIsLast() { return isLast; };
void setIsLast(bool newIsLast) { isLast = newIsLast; };
CKeyStroke* getCurrent() { return current; };
void setCurrent(CKeyStroke* newCurrent) {current = newCurrent;};
};
#include "CKeyQueueItem.h"
#include "CKeyStroke.h"
CKeyQueueItem::CKeyQueueItem(CKeyStroke *item)
{
prevItem = 0;
nextItem = 0;
current = item;
isFirst = true;
isLast = true;
}
CKeyQueueItem::~CKeyQueueItem()
{
delete current;
}
#pragma once
class CKeyStroke
{
private:
unsigned int keyPress;
__int64 secondsTime;
unsigned int millisTime;
public:
const static unsigned int TIMEOUT = 60000;
CKeyStroke(unsigned int key);
~CKeyStroke();
unsigned __int64 getKeyPress(){return keyPress;};
bool isValid();
};
#include "CKeyStroke.h"
#include <sys/timeb.h>
#include <time.h>
CKeyStroke::CKeyStroke(unsigned int key)
{
keyPress = key;
struct __timeb64 timebuffer;
_ftime64( &timebuffer );
secondsTime = timebuffer.time;
millisTime = timebuffer.millitm;
}
CKeyStroke::~CKeyStroke()
{
}
bool CKeyStroke::isValid()
{
struct __timeb64 timebuffer;
_ftime64( &timebuffer );
return ((timebuffer.time - secondsTime) * 1000 + (millisTime - timebuffer.millitm)) > TIMEOUT;
}