0

I am writing a game with libGDX named TaskWarrior, where the player is in the middle of the screen and has to move around to kill enemies. All the characters in the game are seen from above (more like a satellite view). I made different movement behaviors for enemies (based on a book named "steering behaviors for autonomous agents"), like seek (the enemy moves towards the player), flee (the enemy runs away from the player, so that if the player catches and kills him, it received upgrades), etc. My problem is because the characters moves, after some time the enemy textures overlap and they appear like one single enemy. How can I fix this (maybe find another steering vector I can add to the velocity so that minions reject each other, but at the same time continue moving towards/away from the player)?

//steering vector of the enemy I then add to the velocity and later to the position
//seek
    protected Vector2 seek(Vector2 target, float deltaTime){
        Vector2 desired = target.sub(this.position);
        desired.setLength(maxSpeed*deltaTime);
        Vector2 steering = desired.sub(velocity);
        steering.limit(deltaTime*maxForce);
        return steering;
    }

    //flee
    protected Vector2 flee(Vector2 target, float deltaTime){
        Vector2 desired = target.sub(this.position);
        desired.setLength(maxSpeed*deltaTime);
        desired.scl(-1);
        Vector2 steering = desired.sub(velocity);
        steering.limit(deltaTime*maxForce);
        return steering;
    }

//adding steering behavior to the velocity and then to the position in respect to the map limits
    //applying steering behaviour
    protected void applySteeringBehaviour(Vector2 steering){
        velocity.add(steering);
        //make enemy recognize walls
        if(position.x > 0 && position.x < TaskWarrior.WIDTH - getSprite().getRegionWidth()) {
            position.x += velocity.x;
        } else if(position.x <= 0 && isLooking("right") || position.x >= TaskWarrior.WIDTH - getSprite().getRegionWidth() && isLooking("left")){
            position.x += velocity.x;
        }

        if(position.y > 0 && position.y < TaskWarrior.HEIGHT - getSprite().getRegionHeight()){
            position.y += velocity.y;
        } else if(position.y <= 0 && isLooking("up") || position.y >= TaskWarrior.HEIGHT - getSprite().getRegionHeight() && isLooking("down")){
            position.y += velocity.y;
        }
    }

1 Answers1

0

The situation is such that each enemy doesn't have access to the position of the other enemies (for direct avoidance) and some overlapping is acceptable?

What I guess you want is some kind of Brownian rotation. So as far as the bearing from the target is concerned, they are spread around the full 360 degrees i.e. as the enemies approach the target they inherently spread themselves out on the perimeter of an approaching circle.

So as they move towards the target they must also randomly spread with respect to bearing the target has to them i.e. enemies all around.

So you could try instead of heading directly to the target, then take the mod of the current second (or whatever duration), and if its odd head to the target but with a heading 20 degrees left, and if its even then 20 degrees right. Overall they head to the target still but they will randomly spread on a conceptual approaching circle. You can change the parameters of the heading offset (20 or more whichever), enemy velocity (has to increase to keep approach speed as the offset bearing becomes larger), and whichever mechanism for deciding left or right offset maybe more often than a second, maybe each enemy is born with a left or right bias permanently (could be better and easier).

The offset bearing won't matter when they are close enough for a collision.

londonBadger
  • 611
  • 2
  • 5
  • 5