Creating enemies artificial intelligence on Phaser JS - Skate Platformer Game Devlog #09

Written in October 30, 2020 - Games

Hey guys! For today’s game devlog I’m going to show more details of the enemies AI that I implemented.

I decided to create some mixin functions for the artificial intelligence logic, which means I need to call the function binding it to the class that it’s calling it, and for that I’m using the ES7 bind operator so I can call the function like this::someExternalFunction(). Another way to do that would be by running Object.assign(this, { someExternalFunction }) inside the constructor, and then call the function as if it was a class method, like this.someExternalFunction(), then you don’t need to bind it.

update(time, delta) {
    this::platformWalkingBehavior();
}

For the logic inside platformWalkingBehavior, I did it in the simplest way possible, but I still need to improve it for efficiency when many enemies are on the screen. First I check if the enemy has a collidable ground tile in front of it, if it does, it means it can continue walking. Then I also check if there’s any collidable tile right in front of the enemy, if it does, it means the enemy must turn and walk the other direction. Check the code below:

function platformWalkingBehavior() {
    // checks if the next ground tile is collidable
    const nextGroundTile = isNextGroundTileCollidable(
        this,
        this.touchingDownObject.layer.tilemapLayer,
        this.body.velocity.x > 0 ? 'right' : 'left'
    );

    // checks if the next tile is collidable
    const nextTile = isNextTileCollidable(
        this,
        this.touchingDownObject.layer.tilemapLayer,
        this.body.velocity.x > 0 ? 'right' : 'left'
    );

    if (!nextGroundTile || nextTile) {
        this.body.setVelocityX(
            -this.body.velocity.x
        );
    }
}
const isNextGroundTileCollidable = (
    gameObject,
    dynamicLayer,
    direction = FACING_RIGHT
) => {
    const { width } = gameObject.getBounds();
    const { x, y } = gameObject;
    const posX = direction === FACING_RIGHT ? x + width : x - 0.5;
    const tile = dynamicLayer.getTileAtWorldXY(posX, y + 0.5);
    return tile?.properties?.collideUp;
};

const isNextTileCollidable = (
    gameObject,
    dynamicLayer,
    direction = FACING_RIGHT
) => {
    const { width, height } = gameObject.getBounds();
    const { x, y } = gameObject;
    const posX = direction === FACING_RIGHT ? x + width : x - 0.5;
    const tile = dynamicLayer.getTileAtWorldXY(posX, y - 0.5);
    if (direction === FACING_RIGHT) {
        return tile?.properties?.collideLeft;
    }

    return tile?.properties?.collideRight;
};

And this is what it looks like in the game:

Enemy walking on platform

That’s all for today, don’t forget to like my video and subscribe to my channel.

Tags:


Post a comment

Comments

No comments yet.