Putting some pieces together

Well, it’s been a long while since I’ve posted. I went to GDC in San Francisco and had a blast! It was great to meet up with old friends, meet some new friends and learn a lot. I didn’t get the chance to go to that many talks – but when I did I enjoyed noticing how much more I understood than last year. Progress!

Anyway, immediately after GDC I came down with the flu and productivity of any kind at all was out of the question. But now, finally, I’m feeling more like myself again and I can get back to learning (and working).

Before going to GDC I thought I’d try to start putting things together to make sure they worked (though I’ve had no time to write about my changes until now). So I started working the PlayerObject and BulletObject into my GameScreen and removing my old implementations. Amazingly, I didn’t actually have to change very much in my code at all.

The biggest hurdle was spending way too long wondering why I couldn’t see the player drawn to screen. After an hour or so I worked out that the problem was all the way back up in main.cpp. My draw code is now being run from the Update functions of the GameObjects, and these are being called from the Update function in main. In main I was calling glClear, then the (soon to be deleted) draw function, and then calling glSwapBuffers before calling the Update function. Basically that meant I was drawing to the screen, then clearing the screen before posting the screen to the front buffer. Oops.

The only other issue was that my guess for the initial force used to shoot the bullets was way too low. After upping that to 30000 I decided that this was a “magic” number and this should really be passed in as a variable so I can have bullets of different speeds if I want.

As always, you can find my code on github – and the component code is still in a separate branch from master.

On an unrelated note, I’ve been reading a book called “Write Great Code” by Randall Hyde. So far I’ve learned a bit more about how integers and fixed-point variables are stored and manipulated – and how the C/C++ compiler might translate some of my code into assembly. I’m getting better at being able to understand assembly snippets – or at least to use them to better comprehend what is going on behind some higher level code and how that affects memory management and CPU usage.

Bullet refactor

In my last post I created a PhysicsComponent while in the process of refactoring my messy Player class. Today I decided to have a look at the rest of the Player class and see what else I could clean up.

The next biggest mess was how I was handling shooting and bullets. Basically each Player and Enemy had their own vectors of Bullets and handled them separately. The Bullet class seemed like a really good candidate for another GameObject – so the first step was to create a BulletObject. Bullets need to be drawn to the screen and also move around – so I’ve added both the SpriteComponent and PhysicsComponent to my BulletObject (as I did with the Player).

Looking at the existing code for moving the Bullet it quickly became clear that my static const friction value was going to have to become a regular member variable. My bullets don’t have constant acceleration, so really I’m just applying a force when they are shot and then never degrading their velocity. So I set the “friction” in my bullets to 1. I’ve not been able to test all this yet, so I’m going to be amazed if it all works first go.

As I predicted in my last post – I had to repeat the code where the physics and sprite components have to work together before the sprite can draw. So it definitely needs to change – I’m just not sure how (yet). Might sit on that one for a while.

Once the bullet object was out of the way I decided to make a BulletManager that would be responsible for storing all the bullets. This way the player and each of the enemies can just have references to the BulletManager. The BulletManager currently has a vector of pointers to Bullet objects – each time I call the Shoot function I create a new Bullet and add it to the vector. Not particularly cache-friendly but I will fix that when I get around to adding functionality for object pooling.

Once that was done I moved the Player’s shoot code into it’s own function and everything was looking a lot cleaner. Here’s how it looks:

void PlayerObject::shoot()
{
 if (m_fFireCoolDown <= 0) {
     m_fFireCoolDown = 0.3f;
     PhysicsComponent* physicsComponent = 
     dynamic_cast<PhysicsComponent*>(GameObject::GetComponent(PHYSICS));
     float rotationAngle = physicsComponent->GetRotation();
     glm::vec3 shootPos = physicsComponent->GetPosition();

     //calculate offset from player position in world space
     glm::vec4 offset = glm::rotate(glm::mat4(1), rotationAngle, 
     glm::vec3(0, 0, 1)) * glm::vec4(10, 0, 0, 1);

     m_pBulletManager->Shoot(rotationAngle, 
     shootPos - glm::vec3(offset.x, offset.y, offset.z));
     m_pBulletManager->Shoot(rotationAngle, 
     shootPos + glm::vec3(2*offset.x, 2*offset.y, 2*offset.z));
 }
}

I still think I’m going to store a reference to each component in each GameObject. Calling GetComponent each time I need to use it is a bit silly (and adds overhead).

The only other change I made was to add an “active” boolean to GameObject. I imagine this will be useful for all sorts of things, but for now at least it’s an easy way to mark a Bullet as no longer on screen so that it can be removed.

Next time I will probably refactor the Enemy class into an EnemyObject – but that shouldn’t take long. I’m thinking I could possibly create a HealthComponent once I’ve done that since both Player and the Enemies have health.