I've noticed more and more people asking questions about writing games, so I thought I'd post this. It was written some time ago, as an excuse to learn various parts of DirectX. This game will detect if you have a joystick, and use it. If the joystick has force-feedback, it is supported. It is not complete, it is playable, but the main splash screen opens an area that should have included various options such as key selection and was never written. The release version also sometimes crashes on exit and leaks memory during the shutdown of the sound engine ( i.e., for half a second ). It's not perfect, but I don't have time to fix it, and on the other hand, I don't see any reason to let it rot on my hard drive when it might be enough to help someone. I believe the core code to manage the window in MFC came from CP, the code to play MP3s certainly did, although I did not use it. This code compiled under DirectX version 8, which was a pleasant surprise, so it can be taken on by anyone who wants to experiment with it.
The Sound Engine
The sound engine was designed to simplify the process of using Direct Sound by allowing sounds to be added to a player and called from there. I wanted to also use MP3s, but the only code I could find was in C, so only one mp3 is supported. This is a shame, because the sounds and images are the bulk of the download. The player also reports memory leaks during shutdown. Anyone who wants to take this on and finish it is welcome.
One area that I was able to get to where I wanted it was game speed. The game draws at the fastest frame rate it can manage and keeps it's speed constant by checking on each draw if a certain amount of time has elapsed in order to call functions to move the ship and the asteroids. They are separate so that, as the game gets harder, the asteroids move faster but the ship does not.
if (timeGetTime() - m_LastTime > (unsigned int) (30-((m_iLevel>15) ?
30 : m_iLevel * 2)))
m_LastTime = timeGetTime();
if (timeGetTime() - m_ShipTimer > 30)
m_ShipTimer = timeGetTime();
The game defines two classes for data storage:
floatpoint is used to track the ship's acceleration and position, because I use trig to figure out an acceleration based on the angle I am pointing. The
gameitem class is used to track asteroids. Those who know me well will be amused to note that I used to use
CArray rather than vector, and that this game uses MFC.
There is a lot of other stuff going on in this game, but I don't remember most of it. If you find this article interesting but you don't understand how something works, just email me, and as I recollect details through emails I get, I will update the article. Initially my desire is simply that someone get use out of this, because I am not doing anything with it.
Pixel perfect collisions
Another area I did a lot of work was in making collisions pixel perfect. The methodology is the same as used in my C# game, Collision, I suggest you read that article for a thorough explanation. The code under C++/DirectX looks like this:
while (rcShip.top > 0 && rcAsteroid.top > 0)
while (rcShip.left > 0 && rcAsteroid.left > 0)
if (!rcTest.IntersectRect(rcShip, rcAsteroid))
TRACE ("Intersect failed\r\n");
rc.top = ((m_iShipSprite/10) * 32)+576;
rc.left = ((m_iShipSprite%10) * 32);
rc.right = rc.left + 32;
rc.bottom = rc.top + 32;
rc.bottom += 128;
rc.top += 128;
dbltfx.dwSize = sizeof(DDBLTFX);
dbltfx.dwFillColor = RGB(0,0,0);
rc.top = ((m_Items[i].iSprite/5) * 64);
rc.left = ((m_Items[i].iSprite%5) * 64);
rc.right = rc.left + 62;
rc.bottom = rc.top + 64;
rc.top = ((m_Items[i].iSprite/10) * 32) + 384;
rc.left = ((m_Items[i].iSprite%10) * 32);
rc.right = rc.left + 32;
rc.bottom = rc.top + 32;
rc.top = ((m_Items[i].iSprite/20) * 16) + 512;
rc.left = ((m_Items[i].iSprite%20) * 16);
rc.right = rc.left + 16;
rc.bottom = rc.top + 16;
for ( int x = rcTest.left; x<=rcTest.right; x++)
for ( int y = rcTest.top;y<=rcTest.bottom; y++)
if (dcShip.GetPixel(x,y) != RGB(0,0,0) &&
dcAsteroid.GetPixel(x,y) != RGB(0,0,0))
The main point of interest is the last nested loop, where we use
GetPixel to establish if any pixels in the intersected area indicate a collision. Nowadays I would not use
GetPixel, but for all that, it works surprisingly well. I would instead use a
DIBSection and access the bits directly.
Playing the game
Basically to play the game, just use the arrow keys, left and right to rotate, up to accelerate and down to use your limited ( but recharging ) shield. Space fires.
Programming computers ( self taught ) since about 1984 when I bought my first Apple ][. Was working on a GUI library to interface Win32 to Python, and writing graphics filters in my spare time, and then building n-tiered apps using asp, atl and asp.net in my job at Dytech. After 4 years there, I've started working from home, at first for Code Project and now for a vet telemedicine company. I owned part of a company that sells client education software in the vet market, but we sold that and I worked for the owners for five years before leaving to get away from the travel, and spend more time with my family. I now work for a company here in Hobart, doing all sorts of Microsoft based stuff in C++ and C#, with a lot of T-SQL in the mix.