agtv
agtv

Reputation: 127

advanced Collision detection?

Hi i'm currently making an RPG similar to Legend of Zelda. I have a feature in my game where when Player attacks enemy with his sword, the enemy is knocked back n units. i have a collision detection that sometimes works as intended, and other times the enemy goes through the wall and gets stuck on the other side, and then other times the enemy can simply walk right through the wall. If possible, making the enemy move toward player upon collision with wall would be one possible solution to this problem I believe, but I do not know how to implement this. Here is my current collision code:

// Enemy Collides with Wall
        counter1 = 0;
        for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
        {
            counter2 = 0;
            for (iter15 = wallArray.begin(); iter15 != wallArray.end(); iter15++)
            {
                if (enemyArray[counter1].rect.getGlobalBounds().intersects(wallArray[counter2].rect.getGlobalBounds()))
                {
                    enemyArray[counter1].isCollided = true;
                        //Hit Wall
                    if ((enemyArray[counter1].direction == 1 || enemyArray[counter1].rect.getPosition().y >= wallArray[counter2].rect.getPosition().y)) //up
                        {
                            enemyArray[counter1].canMoveUp = false;
                            enemyArray[counter1].canMoveLeft = false;
                            enemyArray[counter1].canMoveRight = false;
                            enemyArray[counter1].rect.move(0, 7);
                        }
                    else if ((enemyArray[counter1].direction == 2 || enemyArray[counter1].rect.getPosition().y <= wallArray[counter2].rect.getPosition().y)) //Down
                        {
                            enemyArray[counter1].canMoveDown = false;
                            enemyArray[counter1].canMoveRight = false;
                            enemyArray[counter1].canMoveLeft = false;
                            enemyArray[counter1].rect.move(0, -7);
                        }
                    else if ((enemyArray[counter1].direction == 3 || enemyArray[counter1].rect.getPosition().x >= wallArray[counter2].rect.getPosition().x)) //Left
                        {
                            enemyArray[counter1].canMoveLeft = false;
                            enemyArray[counter1].canMoveUp = false;
                            enemyArray[counter1].canMoveDown = false;
                            enemyArray[counter1].rect.move(7, 0);
                        }
                    else if ((enemyArray[counter1].direction == 4 || enemyArray[counter1].rect.getPosition().x <= wallArray[counter2].rect.getPosition().x)) //Right
                        {
                            enemyArray[counter1].canMoveRight = false;
                            enemyArray[counter1].canMoveUp = false;
                            enemyArray[counter1].canMoveDown = false;
                            enemyArray[counter1].rect.move(-7, 0);
                        }
                }
                counter2++;
            }
            counter1++;
        }



//Knock Back enemy away from sword && sword2
        counterKnockBack++;
        counter2 = 0;
        for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
        {
                    if (enemyArray[counter2].knockback == true)
                    {
                        if (enemyArray[counter2].isCollided == false)
                        {
                            if ((Player1.rect.getPosition().y > enemyArray[counter2].rect.getPosition().y))
                            {
                                enemyArray[counter2].rect.move(0, -3);  //up
                            }
                            else if ((Player1.rect.getPosition().y < enemyArray[counter2].rect.getPosition().y))
                            {
                                enemyArray[counter2].rect.move(0, 3);    //down
                            }
                            if ((Player1.rect.getPosition().x > enemyArray[counter2].rect.getPosition().x))
                            {
                                enemyArray[counter2].rect.move(-3, 0);   //left
                            }
                            else if ((Player1.rect.getPosition().x < enemyArray[counter2].rect.getPosition().x))
                            {
                                enemyArray[counter2].rect.move(3, 0);    //right
                            }
                            if (counterKnockBack >= 20)
                            {
                                enemyArray[counter2].knockback = false;
                            }
                        }
                    }
            counter2++;
        }

        //turn off collided counter
        counterCollided++;
        counter2 = 0;
        for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
        {
            if (enemyArray[counter2].isCollided == true)
            {
                if (counterCollided >= 30)
                    enemyArray[counter2].isCollided = false;
            }
            counter2++;
        }

I have no idea why the enemy is able to sometimes simply walk right through the wall without being knocked back. So how can I fix this, any ideas?

Upvotes: 0

Views: 257

Answers (1)

DennisS
DennisS

Reputation: 253

Without reading the code completely I can already tell you that your collision detection code is wrong. Mostly because you are moving your objects directly, probably without checking for collisions within your rect::move function.

It is possible that the rect::move function will move objects through the walls without triggering any collision reaction code. Consider the following scenario:

First frame:
enter image description here
enemyArray[counterX].rect.move(3, 0);

Second frame:
enter image description here

The enemy object is moved behind the wall and will not trigger the collision detection code.

My advise is (despite the obvious one: read some books): for each enemy store its previous location and check for collision not between the enemy and the wall's rectangle but between wall and a rectangle between two enemy positions. Something like that:
enter image description here

This is of course only one of the possible scenarios when your collision detection code would be error-prone.

Upvotes: 1

Related Questions