- Code Complete is an amazing book.
- Shmup01's code is pretty terrible and much of it will need to be redesigned and rewritten.
- Like Accelerated C++, I'll probably end up reading some or all of Code Complete.
Saturday, July 24, 2010
I'm about halfway through Code Complete and have realized three things:
Posted by Vince at 12:08 PM
Realizing this is about a month overdue, I'm posting my thoughts on Accelerated C++ while I still remember what it was about.
This book is definitely NOT for beginners, and I wouldn't recommend it to anyone that is just learning how to program. However, if you know a little C++, this book is no bore. If I could summarize it in one sentence (and steal a line used regularly in Code Complete), I would say that Accelerated C++ does a good job of teaching you how to program in the language rather than into it. The focus is on teaching through examples so, instead of getting an overview of all data structures available in STL in one big chapter, individual data structures are introduced as needed by the examples. Manipulating the structures through iterators and built-in algorithms is treated the same way - they are presented as the sample problems in the book grow to require their functionality.
Generic programming, effective use of inheritance, and some specific concepts such as handle classes are all presented extremely well in this book. Some relatively basic concepts are explored in a greater level of detail than you might read in other "how to program" books (explicitly establishing an invariant in while loops comes to mind), but by no means is this book a comprehensive guide to programming or to the language, something the authors agree with in the introduction.
That being said, I feel like I might need to give this one another read down the road. Some of the concepts presented later in the book, such as providing conversion capabilities to your classes and, again, the handle class, were pretty new concepts to me and I'm not sure I could leverage this knowledge without giving it another read and setting up some sample programs to get the hang of it. At this point, I feel like I've been given handed a rocket launcher with no instructions. I could try to use it but the odds are that the results will be catastrophic.
Saturday, June 26, 2010
I'm taking a break from coding. The size of the project has reached a point where I'm now officially navigating unchartered territory. At this point, the design decisions that I'm making will affect future iterations of the project and I want to make sure I don't build an entire house before realizing I need to move a few walls around on the first floor. In coding terms, I'm trying to decide how enemy patterns, weapons, bullets, and bullet patterns should all interact. My usual approach would be to start very simple, such as enemies that spawn based on a fixed pattern, shoot a few straight-lined bullets, and then die when they get shot. But I need to make sure that building something this way is flexible enough that if I want to have enemies move in linear patterns, and then curved patterns, and then a sequence of linear and curved patterns (etc...), that I don't have to rewrite large blocks of code every time I improve functionality.
I have a few designs in mind, and I'm getting a lot done on paper. But before I actually put anything into place, I want to step back and do a little summer reading and see if I can't draw upon the wisdom of some experienced programmers before embarking on this journey.
Summer reading list:
I finished Accelerated C++ this week and just started reading Code Complete. The next few blog posts will probably be book reviews and design discussions instead of project status. Hopefully the time I invest now will yield faster, better programming down the line.
Monday, June 21, 2010
So I thought that changing my game coordinate system from 'int' to 'float' would wreak havok and... I was wrong. Changing everything took less than an hour, cleaning up some warnings took 15 minutes, and the game now plays 10 times better.
This story has 2 morals:
- Carefully crafting modular software on the front end will save you from huge headaches when you (inevitably) end up changing something fundamental later.
- For bullet hell shmups, floats >>>> ints.
Posted by Vince at 6:58 PM
Sunday, June 20, 2010
Saturday, June 19, 2010
Thanks to Darkness for shedding a little light on the memory leak courtesy of TTF_RenderText_Solid. Shmup02 specs are still in the works, but I might try to write up a game design doc based on the Shmup01 engine first. Of course, this would require a couple more modifications to the engine (such as storing level data).
In the meantime, one big dilemma I've been facing is whether I should be using float or int for all of my coordinates. More details can be found on my gamdev.net forum post. Ultimately, it sounds like float is the way to go, which means I'll need to do some serious reworking of the engine to eliminate all traces of int from the code. It's going to be a pain, but I think the long term benefits will be worth it.
In the meantime, stay tuned for updates on my Shmup01-based game!
Tuesday, June 15, 2010
I added game state and gave the player a few lives, so Shmup01 FINALLY plays like a real game! There's still a lot of work to do, but one lovely thing I noticed is that, after the game is over, the process begins consuming approximately 12MB/second... given that the ENTIRE debug folder (exe, media, third party dlls) is just over 9MB total.... I found that to be absolutely insane.
Turns out that the SDL_TTF function TTF_RenderText_Solid is the culprit. My game over state basically said "keep on drawing the game over screen." Unfortunately, this included lines like this:
tempText = TTF_RenderText_Solid( font, "Final Score: ", textColor );
apply_surface( 350, 570, tempText, screen );
Every single call to TTF_RenderText_Solid was creating a brand new surface and assigning it to tempText. My faulty assumption was that the rendered surface only existed in the scope of assignment to tempText and then disappeared. This does not seem to be the case and it resulted in a heinous memory leak. For me, the solution was simply to have it render the text once instead of 30 times per second, but I could still see issues with regularly needing to update text on the screen (such as with scores or lives). I suppose you could pre-load a set of text surfaces (such as the single digit characters 0-9, etc), but that doesn't seem good either. I'm not sure if I'm missing something here or if I'm just running into limitations of SDL.
The good news is that I've been formulating some of the requirements for what Shmup02 will look like. There are still a couple gameplay bugs that I need to work out, but soon enough Shmup02 will be underway.
Sunday, June 13, 2010
Still no video, although I should be very close. I spent a lot of time cleaning things up and paving the way for smoother coding down the road. I haven't used any sort of revision control in the past, so I spent a lot of time learning about how it works and finding a good service. I ended up hosting my code for free on Assembla and using TortoiseSVN on the front end. So far, I'm very pleased with both of these products, and using version control in general! I'm amazed that I made it this far without using it.
I also spent a lot of time restructuring my inheritance hierarchy. Somehow, this led to a really nasty bug that has been in my code for a while but only surfaced after restructuring. Sometimes the program would crash AFTER I closed it, but the behavior was intermittent. The good news is that I became very good friends with Visual Studio's debugger. I still need to figure out where it debugs "from", as I could only get my game media to load if I used absolute paths instead of relative paths. The culprit ended up being a line in certain classes destructors:
SDL_FreeSurface( image );
I have no idea what SDL is doing when it frees surfaces, but I don't think my intuition was right in this case. My guess is that sometimes the program would try to access invalid memory or something as all the destructors were called (i.e. if a GraphicalObject frees an image that an EnemyShip is using as well, when the EnemyShip's destructor is called, there will be nothing to free).
I think I'm close to implementing the next set of features. Although I haven't made a ton of progress on the game in the last week and a half, I would say it has been extremely productive nonetheless.
Wednesday, June 2, 2010
I'm very happy to announce that, on a very basic level, phases 1-5 of Shmup01 are complete. It's ugly as sin and the code is in desperate need of some cleanup, but it works. You can more around and fire bullets at enemies. The enemies don't move, but they can fire bullets at you. Other than some minor changes (graphics, adding a background, creating a notion of losing a life, and making the enemies aim at you instead of simply shooting down), Shmup01 is done. Once I implement a few more features and clean up the code, I'll begin speccing out Shmup02. I'm not sure what features it will include, but it will definitely include the notion of levels (which will basically be a series of enemy and bullet patterns) and the ability to use various weapons.
Hopefully I'll be able to post a video of Shmup01 shortly.
Friday, May 28, 2010
It looks like collision detection is working! I implemented the method mentioned in my last post (hint: ????? was a much more involved step than I thought it would be), and now when the playership fires bullets at the one enemyship on the screen, it registers as hits. Time for some extensive testing...
Also, time to do some SERIOUS code cleanup. I need to go back and finish phase 4 (give enemy ships the ability to fire), and then tie all 5 phases together into what would technically be a "working" prototype for the game. I'll also need to do some pretty basic things (set up boundary conditions for all of the game objects, figure out what the final function prototype is going to look like for the collision detection function, create a GameManager class and throw everything into it instead of in main(), etc). So, as simple as phase 4 will be, it probably wont be done for a little while.
RANDOM tip of the day: I noticed that when I moved my ship diagonally up-right, I could fire at the same time. However, when I moved diagonally in ANY other direction, I couldn't fire! The code that handles movement and firing is extremely simple, so I was pulling my hair out before I finally did a little googling and realized that.... certain keyboards have limitations to how many keys can be pressed at once in certain regions of the keyboard (not even kidding). Once I changed my "fire" button from Space to S, everything started working.
Sunday, May 23, 2010
I finally broke down and upgraded/rebuilt my desktop. The limitations of programming on a laptop started to become unbearable.
Current rig features:
- i7 930
- Asus P6T
- 6GB OCZ Gold DDR3 12800
- Corsair 750TX
- 2xSamsung S2333SW (23" displays, 1920x1080)
So... life is good! But it's time to get back to coding. I still haven't started the collision detection algorithm, but I've been reconsidering the method mentioned in my previous post. I might be better off doing something like this:
- Call the "relative velocity" vector AB
- Call the "stationary" point P
- Create a vector AP, that starts at one end of the relative velocity vector and ends at P
- Project AP onto AB (something like this: http://en.wikipedia.org/wiki/Vector_projection)
Tuesday, May 11, 2010
Phase 3 (adding enemy ships) took a little longer than planned.... mainly because I've been teaching myself object oriented design on the fly and had to rearrange my inheritance hierarchy a little bit to enable greater flexibility down the road.
Still, I can now throw enemies on the screen and the player can shoot at them. Granted, the bullets don't do anything, which brings me to my next point...
I'm skipping Phase 4 (enable the enemies to fire) and heading straight to Phase 5 (collision detection). The more I've been thinking about it, the more I realized how tough this could be. Short version of the story: If a bullet is travelling at 10 pixels per frame and the player's hitbox is 5 pixels, it is possible that bullet could jump right over the player in one frame! (I made a post about this on gamedev.net: http://www.gamedev.net/community/forums/topic.asp?topic_id=570333 )
In any case, between the suggestions made on gamedev.net and some collision detection articles I read, I've decided to go with something like this:
- Assume every collision object is circular. Not ideal, but will work for now.
- For each frame, calculate the relative velocity of two items (say, a ship and a bullet) by subtracting one motion vector from the other.
- Now, all I'll have to do is see if this "relative velocity" vector ever get's too close to the ship (or bullet, depending on how I subtract the vectors). This will be done by...
- Taking the inverse slope of the "relative velocity" vector
- Use this slope and the position of the ship to determine the equation of the line perpendicular to the vector that passes through the point.
- Find the intersection of this line with the relative velocity vector. This is the closest that the vector comes to the ship. Calculate this distance.
- If this distance is less than the radius of the ship and the bullet, there's a collision
Disclaimer: I may be horribly misrepresenting the notion of a vector when I refer to the "relative velocity" vector. But hopefully the idea is clear. The idea is that I'll run through these steps for each pair of objects that need a collision check. Eventually, I'll add some code to minimize the number of checks that need to be made (but I'll save that for another post).
Time to post these ideas to gamedev and make sure they make sense!
Friday, May 7, 2010
I'm pleased (and surprised) to announce that phase 2 is already complete. Now the ship moves around AND fires bullets.
I'm finding one major challenge with writing graphic-driven programs is that debugging isn't as simple as writing a bunch of text to the screen every step of the way. While I could still write log files if I wanted to, I'm going to use this as an opportunity to learn how to properly use a debugger. I'm using Microsoft Visual C++ 2008 Express, so there's already a solid debugger at my disposal. So far, it's already helped me work my way through a couple of potentially nasty bugs with relative ease, so I'm definitely feeling good about deciding to use it!
On another note, for some reason whenever I tried to use an STL iterator, I would get a bizarre Linker error:
"...error LNK2019: unresolved external symbol __imp___CrtDbgReportW referenced in..."
It took a little Google-ing for me to find that I needed to remove the _DEBUG; entry from my project properties:
Alt+F7 (Project Properties)->Configuration Properties->C/C++->Preprocessor->Preprocessor Definitions
After deleting _DEBUG; from this entry, the program compiled and linked without issues.
Phase 3, here I come...
Ever since I was a kid, I've always wanted to design and create games. This blog will track my first real attempt at something beyond tic-tac-toe or connect four. I've always been a big fan of bullet hell shoot-em ups (shmups), so this project will be a basic attempt to create a shmup engine written using C++ and SDL. My biggest hope for this blog is that it will reach a point where it can be used as a road-map for future shmup creators. If the project goes well, consider this blog to be a guide. If it doesn't, consider this to be a list of things to avoid. Another hope is that this keeps me on track and organized, so if anyone is reading this and doesn't see an update for a long time, please e-mail me (firstname.lastname@example.org) and kindly remind me to get my ass in gear.
Short Term Goals: The overarching goal of this project is to create a very basic shmup where you can shoot at some static enemies and they'll shoot back. I've created five benchmarks:
- Phase 1: Display the player's ship on the screen, move it around with arrow keys (complete)
- Phase 2: Enable to the player ship to fire bullets (complete)
- Phase 3: Create some static enemies (complete)
- Phase 4: Enable the enemies to shoot at you on regular intervals (complete)
- Phase 5: Implement basic collision detection (complete)
This is pretty much the most basic shmup I can imagine. I'd also like to adopt a version control system and some standard comment/documentation schemes. Provided I make it this far, I will attempt to extend this functionality with...
Long Term Goals (roughly ordered by level of ambition):
- Intelligent collision detection, which should go a long way to creating "bullet hell"
- Moving enemies
- Non-linear bullet paths
- Multiple player weapons
- Learn how to draw (or make friends with an artist, or hire an artist)
- Learn how to compose (or make friends with a musician, or hire a musician)
- Create an XML representation of levels
- Create a level editor
- Create an Android port of this engine
- Create an XNA port of this engine
Future posts will (hopefully) contain the following:
- Status updates
- Links to useful resources that I find
- Discussions of the various software engineering dilemmas I will encounter