The “real” (x, y) just means it’s a floating point value. This is used to keep track of your position while you are moving from one tile to another and is used for things like scrolling the map (so you have a smooth scroll rather than a choppy one).

Introducing pixel movement

In the default system, whenever you take a step, you move one tile. This is what I call tile-based movement.

“Pixel-based Movement” refers to how many pixels you move per step. So in the default system, I would say you move 32 pixels at a time.

But what if you would like to move 16 pixels at a time? Or 8 pixels at a time? Or even 4 pixels at a time? We would need to do something about how our positions are stored. If one tile is represented by 32 pixels, then doing a little math we have something like this:

16 pixels = 0.5 tiles

8 pixels = 0.25 tiles

4 pixels = 0.125 tiles

So rather than storing our position as integers, why not just store it as real values?

Implementing our pixel movement

When you look at how movement works, you will find that it is pretty straightforward. This is how move_straight is implemented in Game_CharacterBase:

And now we are moving at half a tile per step, or 16 pixels. Which is what we wanted!

Impacts on the tilemap

There are a number of issues, however, that comes with changing how your position is stored.

Remember that a map is stored in a tilemap? This means that all of the tiles are referenced in terms of tile coordinates. This means that if you want to get the tile in the upper-left corner, you would access it as (0, 0).

So what happens if you are at position (0.5, 0) because you only move half a tile at a time? Fortunately, the game truncates your arguments.

Is this correct? In terms of backwards compatibility, I would say so. Since the map editor only supports 32×32 tiles, it is ok to assume that if you are walking anywhere within one tile, then you would use the properties for that particular tile.

Impacts on Collision

Collision detection becomes an issue. Collision is used in different places

Checking whether a tile is passable

Checking whether an event will be triggered

Remember that it truncates your position, so even if you’re at (0.9, 0), it will still think you’re at (0, 0). Now, if you’re at (0.9, 0), your sprite is already very close to the next tile beside it. If the next tile is a wall, you will look like you’re sticking in a wall.

Why? Because the way collision is checked is check a single-point, namely your position, and NOT the size of your sprite.

This same problems occurs with event triggers, except with events the issue is more obvious. Event triggering again uses character positions for comparison, but they check whether the values are exactly the same.

This means that if you’re standing at (1.5, 0) and the event is at (1.0, 0), even if you look like you’re touching it, it isn’t triggered. You have to be exactly aligned with the event to trigger it.

Improvement

There is plenty of room for improvement, however, at this point we have a very basic pixel movement system working (and I use the term “working” very loosely).

Spread the Word

If you liked the post and feel that others could benefit from it, consider tweeting it or sharing it on whichever social media channels that you use. You can also follow @HimeWorks to get the latest updates or suggest topics that you would like to read about.

To create code blocks or other preformatted text, indent by four spaces:

This will be displayed in a monospaced font. The first four
spaces will be stripped off, but all other whitespace
will be preserved.
Markdown is turned off in code blocks:
[This is not a link](http://example.com)