1
\$\begingroup\$

I've already had some experiences about the work of 2 dimensional square-based playfields and moving a player on them. Though, when a square has multiple pixel sizes, and player moves e.g. 1 pixel per frame, I have some problems. Currently, my program counts the coordinates of tile Player stands on like this:

Tile X coordinate = floor of Player X coordinate divided by the X size of a tile a.k.a TileX = floor(PlayerX/TileXsize)

and same for Y. However, when I increase the moving speed to bigger px/frame speed, sometimes the player sinks into the tile that should stop it. How can I prevent this problem?

EDIT: codes. Language is Lua, framework is LOVE2D, gamefield is stored in tables. Player has an X, an Y, and Tilex&TileY, count this way on every frames:

Player.TileX = math.floor((Player.X)/TileSize)
Player.TileY = math.floor((Player.Y)/TileSize)

Moving belongs to key actions, they are simply like Player.X = Player.X + 1

There's a Gravity function as well, called on every frames:

function Gravity()
    if not Solidchecker(Field[Player.TileX][Player.TileY+1]) then
        Player.Y = Player.Y +GForce
    end
end

In case of anyGforce (which is a constant) where value is different from the size of the tile (24) the player sinks into the ground. Obviously in that case, everythings the same as if the system would be counted with only tiles, without separated Player.TileX calculations. Otherwise, it can't handle the occuring alignment.

Possibly I forgot showing some code parts, but I can't see now that any other functions would influence these variables.

\$\endgroup\$
2
  • \$\begingroup\$ It might be easier to help if you share some code. Can you show how you process collisions? \$\endgroup\$
    – Victor T.
    May 14, 2014 at 20:11
  • \$\begingroup\$ @VictorT. Done! \$\endgroup\$ May 14, 2014 at 20:23

2 Answers 2

2
\$\begingroup\$

If you want a quick solution to your algorithm, there's something that you may like :

function Gravity()
    for var i=1,GForce do       
        if not Solidchecker(Field[Player.TileX][Player.TileY+1]) then
            Player.Y = Player.Y + 1
        end
    end
end

I'm only guessing that GForce is not a float number, and that it's close to 1.

This way it will move one tile at a time, stopping either at the closest Solidchecker being true, either at GForce.

\$\endgroup\$
1
  • \$\begingroup\$ I dropped the idea since I asked, but thank you anyway! I'm sure I'm gonna try adapting it in the future. \$\endgroup\$ May 21, 2014 at 16:42
2
\$\begingroup\$

First, stucking and penetrating are common problems in physics simulation: on high enough speeds objects may teleport through obstacles or stuck deepd inside in solid volumes.

Typical solution will be either to move object back to last known non-stuck position (you need to save these coordinates somewhere) or gradually move object back to that position until you hit unobstructed place.

But these methods wont solve issue with teleportation throuh obstacles, when objects are moving fast or when obstacles are small (like 1 px walls). So if you want really good physics, use physics engine, it will save tons of headache.

Second, if players collision bounds are bigger than single pixel, or he is one pixel size but physics precision is better than 1 pixel, then player can actually occupy multiple tiles. Imagine him standing right between adjacent 2 tiles, or in center of 2x2 box. This may or may not be issue depending on game.

\$\endgroup\$
1
  • \$\begingroup\$ "So if you want really good physics, use physics engine, it will save tons of headache." but what if I wanna do my own? \$\endgroup\$ May 21, 2014 at 16:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .