Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm having a problem with mapping logical coordinates to graphical ones when my character is walking. I've been able to map them without the graphical walking in between, i.e it just "jumps" from one tile to the other.

The logical coordinates are represented such as [0,0], [0,1] etc. and a character can only be in one of these tiles at a time. I want my character to graphically move from one tile to the next at a given speed/pixels per rendering update until it hits the logical tile's graphical position.

If I didn't phrase myself good, please don't be afraid to tell me.

share|improve this question
Most tutorials use something like OffsetX, OffsetY in addition to your PoisitonX and PositionY. When you walk you increase your Offset until its equal to tilesize and then you increase position and reset offset. And you draw to Position * TileSize + Offset –  Kikaimaru Aug 8 '13 at 11:44
Thank you. I implemented a solution with offsets but I don't like that it mixes graphics and logic too much. Maybe you could give me a hint on how to do it better? –  Oakin Aug 8 '13 at 13:01
Personaly I use absolute position as logical position even if game is tile based. And then I have getter that will recompute absolute position to tile position (for collisions etc). –  Kikaimaru Aug 8 '13 at 14:45
It's best to separate questions and answers. Why not put your solution as an answer? –  Byte56 Aug 8 '13 at 16:42
add comment

2 Answers

Probably I should ask this as a comment, but I'm not yet allowed to. So I'll blatantly formulate this as a semi-answer.

It sounds like entity.getX() is returning an integer between [0, maxTileNumberX] representing the tile position. In the end you're trying to interpolate the movement between getX() and getX()+1 using integers only. Why not make xOffset a float between [0,1]? Then do the calculation

Math.round((entity.getX() + entity.getXOffset()) * tileSize)

Of course this means speed must also be a float and scaled appropriately. Is there a reason not to use float? If you want to decouple the logic and graphic, that would be the first natural step. Only the graphic layer needs integers, the logic should be allowed to operate with its own data types suitable for the problem.

share|improve this answer
My solution is similar to that, check my own answer for how I did it. Cheers for your answer by the way. –  Oakin Aug 9 '13 at 7:23
add comment

Alright, I think it's time I posted my solution as an answer(thanks Byte56). It's not the prettiest but it works well enough for me.

I basically have a method for moving in the different directions. The goal variables are the tile we want to move to. In the next iteration of the game loop the entity's update method will take care of the goal variable.

 * Move the entity right.
public void moveRight() {
    if(goalY == y) {
        goalX = x+1;
        horizontalSpeed = speed;
        //  resetGoalY();

I got a bug with this method that I will fix later on but I think it's good if you get the bigger picture of how my movement works. As long as goalX != x we will update the offset on each axis with the given speed. Note that the two different speeds can either be negative or positive depending on what direction we want to go. I then check if the offset equals the maximum offset (in my case, this is the tile size) and seeing as it can be either tilesize or -tilesize I will check with Math.abs which gives the absolute value of the values. If the values are equal it's time for the logic to move to that tile and I then reset the offsets.

 * Update the entity's movement.
private void updateMovement() {
    if(map.isTileWalkable(goalX, goalY)) {
        if(goalX != x) {
            xOffset += horizontalSpeed;
        else if(goalY != y) {
            yOffset += verticalSpeed;

        if(Math.abs(xOffset) == maxXOffset) {
            x = goalX;
        else if(Math.abs(yOffset) == maxYOffset) {
            y = goalY;
share|improve this answer
add comment

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.