STARSHIPS WERE MEANT TO FLY
Starship is an Asteroids-like game where players fight through waves of obstacles and enemies - either solo or with a friend.


class Game { public: Game(); ~Game(); void InitStars(); void SetSounds(); void SpawnShips(); void SpawnNewAsteroid(); void SpawnNewBeetle(); void SpawnNewWasp(); void SpawnNewBullet( Vec2 pos, Vec2 velocity, float angle ); void SpawnNewDebris( Vec2 startPos, Vec2 entityVelocity, Rgba8 color ); void Update( float deltaSeconds ); void Render() const;
// check collision of asteroid with sword if( asteroid && !asteroid->IsInvulnerable() ) { if( DoDiscsOverlap2D( asteroid->GetPosition(), ASTEROID_PHYSICS_RADIUS, player->GetPosition(), player->GetSwordLength() ) ) { Vec2 playerToAsteroid = asteroid->GetPosition() - player->GetPosition(); float dot = DotProduct2D( playerToAsteroid, player->GetSwordVector() ); if( dot > PLAYER_SWORD_DOT_THRESHOLD ) { asteroid->TakeDamage( 1 ); g_theAudio->StartSound( m_swordFXID, false, SWORD_VOLUME ); } } }
Post-Mortem
While working on Starship, I maintained task lists and task breakdowns to create a to-do list during work sessions. With this list, I could order and rearrange the tasks to work on, further flesh out features as I approached them, and update the itinerary with bugs and design issues that popped up. I also realized that as I got further into the project, I was able to plan and execute tasks faster, due to my increase in familiarity with the code base and understanding of how different problems related to each other. This plan-and-execute loop allowed me to be more efficient than just trying to plan everything out in detail or jumping head-first into code.
However, this work style was largely a bottom-up approach to programming, and for the sake of perceived efficiency I tended to leave refactoring and reorganization for later. There were many cases where the methods I wrote worked with little to no issues, but because I was so focused on getting the task done that I would end up ready to build and test, only to realize that I didn't even call the new methods in the game loop. Adopting a top-down approach - or at least keeping in mind the top levels of implementation when planning features - would eliminate this problem and the wasted time caused by it. My aversion to cleaning up and refactoring my code made some files unwieldy and made adjusting existing code for reuse more troublesome. Incorporating some level of cleanup in the plan-and-execute loop would lessen the burden of refactoring everything at the end of the project and make reusing constructs for future problems easier.