Hello :)

I am currently developing a game with grid-based movement, and I happened to stumble across this code. I really liked Joncom's work, so I ended up using it. I even put a link to the thread in my source.

I wanted to be able to move in 8 directions so I modded the code a bit. It works as it should, except when colliding with corners. Consider the following example(0 is a wall, @ is the player):

Assume the following situation:
   
00@
   

If I move left-up, I should end up here:
 @
00
   

The problem is I end up sliding up and then teleporting into position, like so:
  @
00
   

 @
00
   

As far as I understand, the code properly moves the player into position, but the engine detects that it's going into a wall and won't let it move in the y axis. When it's done moving, it snaps to the grid based on it's target tile.
What I want is a system that checks for such situations and prevents diagonal movement.

Could someone please help?

Here's my code:
// Taken from here:
// http://impactjs.com/forums/code/top-down-rpg-style-tile-based-grid-movement

ig.module(
    'game.entities.base.gridEntity'
)
.requires(
    'impact.entity'
)
.defines( function () {

    EntityGridEntity = ig.Entity.extend({

        // Override
        // 50 fits 8x8 entities
        speed: 50,

        moveType: {
            'UP':         1,
            'UP_RIGHT':   2,
            'RIGHT':      3,
            'RIGHT_DOWN': 4,
            'DOWN':       5,
            'DOWN_LEFT':  6,
            'LEFT':       7,
            'LEFT_UP':    8,

            'NONE':  0
        },

        moveIntention: null,
        lastMove:      null,
        destination:   null,
        
        init: function (x, y, settings) {
            this.parent(x, y, settings);
            this.maxVel.x = this.maxVel.y = this.speed;
        },

        update: function () {
            // It's iportant to call the parent first because I don't know.
            // It works, don't mess with it.
            this.parent();

            this.moveIntention = this.getMoveIntention();

            // Stop the moving entity if at the destination.
            if(this.isMoving() && this.justReachedDestination() && !this.moveIntention) {
                this.stopMoving();
            }
            // Stop the moving entity when it hits a wall.
            else if(this.isMoving() && this.justReachedDestination() && this.moveIntention &&
                    !this.canMoveDirectionFromTile(this.destination.x, this.destination.y, this.moveIntention)) {
                this.stopMoving();
            }
            // Destination reached, but set new destination and keep going.
            else if(this.isMoving() && this.justReachedDestination() && this.moveIntention &&
                    this.canMoveDirectionFromTile(this.destination.x, this.destination.y, this.moveIntention) &&
                    this.moveIntention === this.lastMove) {
                this.continueMovingFromDestination();
            }
            // Destination reached, but changing direction and continuing.
            else if(this.isMoving() && this.justReachedDestination() && this.moveIntention &&
                    this.canMoveDirectionFromTile(this.destination.x, this.destination.y, this.moveIntention) &&
                    this.moveIntention !== this.lastMove) {
                this.changeDirectionAndContinueMoving(this.moveIntention);
            }
            // Destination not yet reached, so keep going.
            else if(this.isMoving() && !this.justReachedDestination()) {
                this.continueMovingToDestination();
            }
            // Not moving, but wanting to, so start!
            else if(!this.isMoving() && this.moveIntention &&
                    this.canMoveDirectionFromCurrentTile(this.moveIntention)) {
                this.startMoving(this.moveIntention);
            }
        },

        getCurrentTile: function() {
            var tilesize = ig.game.collisionMap.tilesize;
            var tileX = this.pos.x / tilesize;
            var tileY = this.pos.y / tilesize;

            return {
                x: tileX,
                y: tileY
            };
        },

        getTileAdjacentToTile: function(tileX, tileY, direction) {
            if(direction === this.moveType.UP) {
                tileY += -1;
            } else if(direction === this.moveType.UP_RIGHT) {
                tileY += -1;
                tileX +=  1;
            } else if(direction === this.moveType.RIGHT) {
                tileX += 1;
            } else if(direction === this.moveType.RIGHT_DOWN) {
                tileX += 1;
                tileY += 1;
            } else if(direction === this.moveType.DOWN) {
                tileY += 1;
            } else if(direction === this.moveType.DOWN_LEFT) {
                tileY +=  1;
                tileX += -1;
            } else if(direction === this.moveType.LEFT) {
                tileX += -1;
            } else if(direction === this.moveType.LEFT_UP) {
                tileX += -1;
                tileY += -1;
            }

            return {
                x: tileX,
                y: tileY
            };
        },

        startMoving: function(direction) {
            // Get current tile position.
            var currTile = this.getCurrentTile();
            // Get new destination.
            this.destination = this.getTileAdjacentToTile(currTile.x, currTile.y, direction);
            // Move.
            this.setVelocityByTile(this.destination.x, this.destination.y, this.speed);
            // Remember this move for later.
            this.lastMove = direction;
        },

        continueMovingToDestination: function() {
            // Move.
            this.setVelocityByTile(this.destination.x, this.destination.y, this.speed);
        },

        continueMovingFromDestination: function() {
            // Get new destination.
            this.destination = this.getTileAdjacentToTile(this.destination.x, this.destination.y, this.lastMove);
            // Move.
            this.setVelocityByTile(this.destination.x, this.destination.y, this.speed);
        },

        changeDirectionAndContinueMoving: function(newDirection) {
            // Method only called when at destination, so snap to it now.
            this.snapToTile(this.destination.x, this.destination.y);
            // Get new destination.
            this.destination = this.getTileAdjacentToTile(this.destination.x, this.destination.y, newDirection);
            // Move.
            this.setVelocityByTile(this.destination.x, this.destination.y, this.speed);
            // Remember this move for later.
            this.lastMove = newDirection;
        },

        stopMoving: function() {
            // Method only called when at destination, so snap to it now.
            this.snapToTile(this.destination.x, this.destination.y);
            // We are already at the destination.
            this.destination = null;
            // Stop.
            this.vel.x = this.vel.y = 0;
        },

        snapToTile: function(x, y) {
            var tilesize = ig.game.collisionMap.tilesize;
            this.pos.x = x * tilesize;
            this.pos.y = y * tilesize;
        },

        justReachedDestination: function() {
            var tilesize = ig.game.collisionMap.tilesize;
            var destinationX = this.destination.x * tilesize;
            var destinationY = this.destination.y * tilesize;
            var result = (
                (this.pos.x >= destinationX && this.last.x < destinationX) ||
                (this.pos.x <= destinationX && this.last.x > destinationX) ||
                (this.pos.y >= destinationY && this.last.y < destinationY) ||
                (this.pos.y <= destinationY && this.last.y > destinationY)
            );
            return result;
        },

        isMoving: function() {
            return this.destination !== null;
        },

        canMoveDirectionFromTile: function(tileX, tileY, direction) {
            var newPos = this.getTileAdjacentToTile(tileX, tileY, direction);
            return ig.game.collisionMap.data[newPos.y][newPos.x] === 0;
        },

        canMoveDirectionFromCurrentTile: function(direction) {
            var currTile = this.getCurrentTile();
            return this.canMoveDirectionFromTile(currTile.x, currTile.y, direction);
        },

        // Sets the velocity of the entity so that it will move toward the tile.
        setVelocityByTile: function(tileX, tileY, velocity) {
            var tilesize = ig.game.collisionMap.tilesize;
            var tileCenterX = tileX * tilesize + tilesize / 2;
            var tileCenterY = tileY * tilesize + tilesize / 2;
            var entityCenterX = this.pos.x + this.size.x / 2;
            var entityCenterY = this.pos.y + this.size.y / 2;

            this.vel.x = this.vel.y = 0;

            if(entityCenterX > tileCenterX) {
                this.vel.x = -velocity;
            } else if(entityCenterX < tileCenterX) {
                this.vel.x = velocity;
            }

            if(entityCenterY > tileCenterY) {
                this.vel.y = -velocity;
            } else if(entityCenterY < tileCenterY) {
                this.vel.y = velocity;
            }
        },

        // Override
        getMoveIntention: function() {
            return this.moveType.NONE;
        }
    });
});