1 decade ago by Silent
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:
If I move left-up, I should end up here:
The problem is I end up sliding up and then teleporting into position, like so:
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:
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; } }); });