Adapt > Engage > Dominate

Archive for February, 2009

Switch statements and multiple deletions

Errors such as:

Unhandled exception at 0x0098c580 in MenschÄrgereDichNicht.exe: 0xC0000005: Access violation reading location 0xfeeefef6.

or

_vfptr 0xfeeefeee

CXX0030: Error: expression cannot be evaluated

might signal a problem similar to one I encountered.  By studying the memory addresses and looking at the call stack, I (correctly, as it turned out) assumed that I was deleting memory used by DirectInput twice.  But the thing is, I only had one Release in the entire program for that pointer.  It turned out that the problem lay in my switch statement which went through the game states.  I thought that calling PostMessage(hwnd, WM_DESTROY, 0, 0); would exit the function and not come back.  However, as it turns out, it does come back and I foolishly thought I could leave out the break statements.  Inserting those for each of the cases did the trick because the program was no longer able to cascade down the cases and end up posting the WM_DESTROY message multiple times (since it was used for multiple cases), thus deleting the DInput pointer multiple times.  Generally, I always put in breaks for clarity and correctness and having now had to track down this annoying error will ensure that I will do so a lot more in the future.

Another associated bug occurred because I didn’t check for the null condition on a pointer to the keyboard device and because of the way my code is structured, ending the program released the keyboard and then zoomed through the Poll_Keyboard function once more.  This, of course, was impossible since it had already been released.  A simple null check did the trick (although in the future it will probably be better to rewrite the code to avoid that problem altogether).

DirectX Release Order

Be sure to release DX objects in the correct order–ones created first should be released last.  Found this by releasing a font object after releasing the d3d and d3ddev objects and getting an access violation in [2] of the __vfptr part of the font object.

Simple Non-DirectInput Mouse Input

Instead of goofing around with DirectInput and mickeys, use Windows messaging instead.  This is especially useful in GUIs and hover events, should they be necessary for your game.

case WM_MOUSEMOVE:
{
mPos.setAbsX(GET_X_LPARAM(lParam));
mPos.setAbsY(GET_Y_LPARAM(lParam));
break;
}

case WM_LBUTTONUP:
{
mPos.setClick(true);
break;
}

in WndProc does the trick.  Additional messages such as double clicks, right clicks, and so on can be caught and used, depending on the program requirements.  Initialization with GetCursorPos and ScreenToClient sets up the correct beginning mouse position values.

Lost Input Devices

HRESULT hr;
hr=dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);
if(hr==DIERR_INPUTLOST || hr==DIERR_NOTACQUIRED)
{
dikeyboard->Acquire();
dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);

}

Above code can be used as an example to reaquire the keyboard/mouse if necessary after Alt+Tab or any other action which might cause the loss of the device.  The main idea is to store the result of GetDeviceState and then check for the error codes indicating failure.

D3DXVECTOR3 z value

If everything else appears normal when attempting to draw simple sprites on the screen and vectors are being used, ensure that the z value is initialized to 0.  Otherwise, the sprites/textures may not appear, even if everything else is correct.

Cat Attack

Occasionally our cat walks toward my mom casually and then suddenly leaps toward her leg with fangs and claws extended.  You really have to be careful of those walk-by bitings!