1
\$\begingroup\$

This question already has an answer here:

I have for some time now been struggling with movement in my game. I want a Zelda like 8 directional top-down movement.

I have tried different things, but non of them have been perfect.

EDIT:

Because my question is unclear, I've tried to boil it down to this:

What I'm looking for is someone who can explain me how to do this properly: 8 directional movement that can move the empty space between an entity and a tile, even though it's less than the movement speed, and also allows the entity to move along a wall of tiles with two directions activated. eg. a south wall you'd be able to hold down 'down' and 'right' to move along the wall.

The following is just some background information on how the relevant parts of my games are made. As I mention in the bottom, you are welcome to disregard everything I've written underneath, if you have a solution that works.

EDIT 2:

I have read (also before making this post, and re-read them now) the posts that my post has been marked a duplicate as.

I will try to be really specific, as none of these has solved my problem.

I have a game that is tile based. Each tile is 32*32 pixels. I have a player entity in this game, the player is 12*12 pixels.

I want the player to be able to walk around on the tiles that are not solid, and then stop at the ones that are solid. Movement is controlled by the arrow keys.

I explained how I handle the players movement beneath, but I'm willing to scrap that, if someone has a better or easier way of doing it.

The movement/collisions have some criteria:

  • The player has to "stick" to the wall, even though his speed doesn't exceed the distance to the tile he is moving at, he should move the remaining distance to the wall.
  • If a player travels along a wall, he should also be able to press the direction of the wall without it hindering his movement.

I'm looking for examples and techniques on how to achieve this. It could be an explanation, code or just the math behind. I'm open to anything that could point in the right direction.

I hope this might clear up my question.

END EDITS

Explanation on how some of my game logic works right now

First of, I'm doing this game in JavaScript, but pseudo code or other languages are welcome.

My player entity:

  • has a position which is of a 'Point' object with a 'x' and a 'y' value
  • has a velocity which is of a 'Velocity' object with a 'x' and a 'y' value (can obviously be positive or negative)
  • has a size which is of a 'Dimensions' object with a 'w' and a 'h' value
  • has a speed value called 'speed' (float)

lets for the sake of this example say the player has a dimension of 12*12px.

My map is made up of an array, like so:

var map = [
    [1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,1],
    [1,0,0,1,1,1,0,0,1],
    [1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1],
];

where all 0's and 1's are objects of the type 'Tile' that has a 'solid' value (true/false), a position value of a 'Point' object and a size value of a 'Dimensions' object (like the player).

The dimension of the tiles are 32*32 pixels.

I could also have a 'mapTiles' array with all the objects, which I have chosen to do in my example further down (each Tile has a position and their dimensions, so there is really no need to keep them in a 2d array for this example).

The movement:

When my game ticks, the player movement looks at the current input being pressed.

var move = new Velocity(0,0);

//check if whether straight or diagonal movement

var speed;

if((input.up || input.down) && (input.left || input.right)){
    //diagonal
    speed = this.speed*Math.sin(45);
} else if((input.up || input.down) || (input.left || input.right)){
    //Straight
    speed = this.speed;
} else {
    //None..
    speed = 0;
}

now, the way I have chosen to do the collision detection is with what I call boxes. A box is a simple object with 'x1', 'y1', 'x2' and 'y2' values.

The box object also has a build in function that can check if it overlaps another box. Like so:

var ovarlaps = !(box.x2 < other.x1 || box.x1 > other.x2 || box.y2 < other.y1 || box.y1 > other.y2);

when the velocity is > 0, a movement and and moveBox gets made:

//get the players box
var curBox = this.getBox();

//make the movement box - modified later
var moveBox = new Box(curBox.x1, curBox.y1, curBox.x2, curBox.y2);

//add speed to movement and expand movebox
if(input.down){
    move.y = speed;
    moveBox.y2 += speed;
} else if(input.up){
    move.y = -speed;
    moveBox.y1 -= speed;
}

if(input.right){
    move.x = speed;
    moveBox.x2 += speed;
} else if(input.left){
    move.x = -speed;
    moveBox.x1 -= speed;
}

This all works great so far.

Now I want to check for collisions. I have my moveBox, which is, just to clarify, the players box expanded to fit the velocity - this way you can't move over really small objects if you were going fast.

I check all the Tiles for collision with the player, and return the solid Tiles that actually collided in an array.

//asuming that all the map tiles, which is also in the 'map' array, is also in a 'mapTile' array

var collisionObjects = []; //the array to keep the collided solid objects

for(i=0; i<mapTiles.length; i++){

    if(mapTiles[i].solid){
        if(mapTiles[i].overlaps(moveBox)){
            collisionObjects.push(mapTiles[i]);
        }
    }

}

Now I have an array with all the tiles colliding with the moveBox.

And this is where my code messes up, and this is where I need help!

If I collide with one or more tiles, I want to move to the edge of the tiles. I also want to be able to move along walls with two directional movement.

I don't need to be able to move around corners if I'm close or any fancy stuff like that.

I imagine iterating trough the objects and modifying the 'move' variable (applied to the position a little further down).

Problems I usually run into in this part of my code is typically not being able to move along walls with two directional movement (usually teleports the player into the wall or something), being stuck in the wall with 1 pixel, and more.

in the last part of my movement code I just add the 'move' variable to the current position:

this.pos.x += move.x;
this.pos.y += move.y;

I hope someone can help me, I'm open to ANY suggestions - even scrapping my current movement logic. Code and/or math is very welcome.

I also want to make clear, that this is not code from my actual game, this is just examples I copied over / wrote on the spot.

Thanks for reading!

\$\endgroup\$

marked as duplicate by Josh Jun 25 '14 at 18:41

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ What is the actual problem? If none of that is your code, what have you tried? This is very unclear. \$\endgroup\$ – Josh Jun 25 '14 at 17:42
  • 1
    \$\begingroup\$ There is no errors in my code per se, and i'm not looking for someone to write my code for me. What i'm looking for is someone who can explain me how to do this properly: 8 directional movement that can move the empty space between an entity and a tile, even though it's less than the movement speed, and also allows the entity to move along a wall of tiles with two directions activated. eg. a south wall you'd be able to hold down 'down' and 'right' to move along the wall. I can update the OP with some code i have tried, but i don't see the point since the logic behind simply doesn't work? \$\endgroup\$ – user1441619 Jun 25 '14 at 18:15
  • \$\begingroup\$ That's pretty broad, but I do think there is a duplicate question here that might help you. Let me find it. \$\endgroup\$ – Josh Jun 25 '14 at 18:24
  • \$\begingroup\$ yes, unfortunately it is... That would be very helpful if you could find that! It's the logic behind the movement / collision i'm looking for. \$\endgroup\$ – user1441619 Jun 25 '14 at 18:27

Browse other questions tagged or ask your own question.