0
\$\begingroup\$

I have a tile-based game with dimensions of 28 x 31 (I'm recreating Mrs. Pacman), and inverted y-axis. The upper-left tile is 1,1 and the lower right is 28,31. Due to the map being very small, I'm scaling it up by 6 times the original size to fit an available screen of 318 x 217 pixels. There is also a character in the game, with a size of 1 x 1 units, so will by 6 x 6 pixels when scaled up (Note: The tiles are only re-scaled when drawn).

Looks like this (You will notice that the width doesn't match that of the actual tilemap, because extra collision is required for the side walls).

The tilemap:

-- 1's are walls; 0's are empty space.

nodemap = {
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
    {1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1},
    {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,1},
    {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
}

In order to make the character move with fluidity, it will given a speed of .1. The character will constantly move forwards, will stop upon hitting a wall, and can only turn if there is an empty space in that direction.

The issue I'm having is that when the characters speed is 1, the collision detection is fine, but the movement is ugly; teleporting to the next tile. That's why I gave it a speed of .1, but in doing so, this creates an floating-point index, which messes up the collision.

To counter this, I used the following code to round the characters position based on the decimal:

if (mrspacman.x - math.floor(mrspacman.x) >= .5) then
    if (mrspacman.dz == 0 and nodemap[math.ceil(mrspacman.y)][math.ceil(mrspacman.x)+1].id ~= 1) then
        moving = true
        mrspacman.x = mrspacman.x + mrspacman.speed
    elseif mrspacman.dz == 90 and nodemap[math.ceil(mrspacman.y)-1][math.ceil(mrspacman.x)].id ~= 1 then
        moving = true
        mrspacman.y = mrspacman.y - mrspacman.speed
    elseif mrspacman.dz == 180 and nodemap[math.ceil(mrspacman.y)][math.ceil(mrspacman.x)-1].id ~= 1 then
        moving = true
        mrspacman.x = mrspacman.x - mrspacman.speed
    elseif mrspacman.dz == 270 and nodemap[math.ceil(mrspacman.y)+1][math.ceil(mrspacman.x)].id ~= 1 then
        moving = true
        mrspacman.y = mrspacman.y + mrspacman.speed
    end
else
    if (mrspacman.dz == 0 and nodemap[math.floor(mrspacman.y)][math.floor(mrspacman.x)+1].id ~= 1) then
        moving = true
        mrspacman.x = mrspacman.x + mrspacman.speed
    elseif mrspacman.dz == 90 and nodemap[math.floor(mrspacman.y)-1][math.floor(mrspacman.x)].id ~= 1 then
        moving = true
        mrspacman.y = mrspacman.y - mrspacman.speed
    elseif mrspacman.dz == 180 and nodemap[math.floor(mrspacman.y)][math.floor(mrspacman.x)-1].id ~= 1 then
        moving = true
        mrspacman.x = mrspacman.x - mrspacman.speed
    elseif mrspacman.dz == 270 and nodemap[math.floor(mrspacman.y)+1][math.floor(mrspacman.x)].id ~= 1 then
        moving = true
        mrspacman.y = mrspacman.y + mrspacman.speed
    end
end

end

This results in some funky behaviour. Does anyone have any ideas to how this can be fixed?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.