Fixing my collision errors + cleaning up

So I’ve made a promise to myself to write a post once a week. I actually started this 3 weeks ago then promptly went to Spain on holidays and missed two weeks. And I’m still not quite in the habit of doing it yet, so I seem to be leaving things to the last minute and writing my posts up on Sunday evening. In fact with my last post I managed to not finish before a house guest arrived, then frantically tried to get it done while the house guest was out one night seeing the sights of Amsterdam.

I’m happy that I do at least end up motivating myself to do some work once a week (in fact once I do get going I really enjoy myself) but I really need to work on not leaving it until the last minute. Because when I do that I rush and make mistakes.

Which brings me to today’s post. It seems my attempt at collisions was not quite perfect. For some reason the bullets were not being removed on collision, and in my search to find out why I discovered other minor bugs and ended up tidying up a bit.

Firstly I noticed that ships were being hurt by their own bullets as they were shooting them (because the bullet and shooting ship overlap for a brief time). To solve this I decided that the bullet should store a reference to the ship that shot it, and when checking collisions I should just discount any bullets that come from my own ship. I added a ShipObject pointer to bullet and the following code to the ShipObject Update function:

else if (collisionTag == BULLET_COLLIDER) {
    BulletObject* bullet = dynamic_cast<BulletObject*>(m_colliderComponent->m_pOtherCollider->m_pGameObject);
    if (bullet->m_pOwner != nullptr && bullet->m_pOwner != this) {
        m_healthComponent->TakeDamage(bullet->GetPower());
}

I also added a “power” variable to the bullets, so that I can change how much damage is done by enemy and player bullets. So in the above code the power of the bullet is obtained and passed to the health component.

I then noticed that some components of the game objects remain active even when the game object itself is deactivated, and my tests to see if game objects or components are active were just all over the place. So I added the following function to GameObject:

void GameObject::SetActive(bool a_bValue)
{
    if (m_bActive != a_bValue) {
        m_bActive = a_bValue;
        for (unsigned int i = 0; i < m_components.size(); i++) {
            m_components[i]->m_bActive = m_bActive;
        }
    }
}

This way the components are all set accordingly when a GameObject becomes active or inactive. I also made sure I was checking the active boolean in all Updates and other relevant functions. Also I added some code to the AddComponent class so that newly added components are set up with the active flag set the same as it is on the GameObject they are being added to at the time.

After all this my bullets were STILL not being removed after hitting a ship. I spent an embarrassingly long amount of time trying to work out why. In the end it turned out to be the first line of the IsCollidingWith function in the ColliderComponent. I was setting the pointer to the “other collider” (which I’m also using as a flag to determine whether there has been a collision) to be null.

What an idiotic thing to do – since I check every collider against every other collider right now then the other collider pointer is being overwritten with the very next collider I check. Really it only worked if the last collider I check against a particular collider results in a collision. To fix it I just reset all the “other collider” pointers before going into my collision checking loops.

The last thing I changed was to cache the references to the components I need in each class. Previously I was calling GetComponent multiple times per Update loop, which seemed like a not very good decision performance wise (since I’d have to check references to each component in the component list for that game object, and these are not stored very closely together in memory.

So in each of my derived GameObject classes I added a pointer to the Components it uses – then created a “setComponentPointers” private function, that is called at the end of the AddComponent function. The GetComponent call is done in here, like so:

void ShipObject::setComponentPointers()
{
    m_spriteComponent = dynamic_cast<SpriteComponent*>(GameObject::GetComponent(SPRITE));
    m_colliderComponent = dynamic_cast<ColliderComponent*>(GameObject::GetComponent(COLLIDER));
    m_healthComponent = dynamic_cast<HealthComponent*>(GameObject::GetComponent(HEALTH));
}

Next week I think I might take a look at trying to separate out the game logic code from the engine code. Also perhaps try to make it a bit easier to use the engine code, to foolproof it a bit somewhat. It would be great for the gameplay coder to not have to write the setComponentPointers function – right now they have to kind of add components in two places (using the AddComponent function as well as setting up the pointers in the GameObject class and making sure they are filled properly by the setComponentPointers function). It would be awesome if, after calling AddComponent, a gameplay coder never had to worry about doing anything else…

Feel free to have a closer look at my code on GitHub and let me know any suggestions you might have in the comments below.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s