Theoretical Tile-Based Question

Started by
6 comments, last by Btobin98 9 years, 9 months ago

Hello all, I have a theoretical question in regards to tile based game engines:

Lets say in theory I was making a 2D RPG with a top-down view. I can also move in eight directions (forward, backward, left, right, and the diagonals).

Now lets say our player is in a typical peaceful village at the start of our journey. The player leaves north into the Forest and comes across a narrow Y in the road, narrow enough for a man to walk through but only just. He finds he can travel diagonally forward to the left or diagonally forward to the right.

Our hero can't travel through the forest, he must stay on the path. The problem is the tile that makes up the path also contains part of the forest. When our hero tries to walk on the tile that is half path half forest he cannot progress due to the forest half being present.

Is there a way to allow the player to pass through specific parts of a tile while stopping if he hits any other part? I'm not asking for specific code just the process of how someone would go about fixing this.

Perhaps an easier to explain example is this: Lets say we have a signpost tile sticking out of some ground similar to the ones you find in the Zelda games. In Zelda you can read the sign from only the front, you can bump into it from all sides but you can walk through part of the tile as long as you approach it from the back as the sign realistically isn't going to be ridiculously thick. How is that done? To my knowledge you can have tiles that the player can walk through and tiles that they cannot but not a mixture of the two. This is how it was in RPG Maker VX Ace (at least as far as I know).

I've attached a horribly drawn visual of the forest description above and also a screenshot from the amazing Zelda: A Link Between Worlds that contains a signpost to help visualize my question.

Thanks so much for the help I appreciate it!

Advertisement

You could potentially have a tile layer mask that represents which pixels in a tile are walkable. The image can just contain 0's and 1's and it will look like the tile image but be black and white. When moving around in the tile, you check the mask associated with the tile and if the next pixel they would walk to is a 0, then they can't walk there.

There are several ways. You can use masking within a pixel to indicate collision or interactable areas, like megadan says.

For the collision issue, you can also solve it using math, in order to figure figure out all kinds of things apart from just "is this tile full-on collision?".

You might have a tile which is flagged as "collision starting from bottom left, going upwards in a 45 degree angle to the right". The actual collision for the tile's pixels can then be determined by a simple linear formula: mx + b, with m being the slope and b being the start offset.

You might also then have collision which is only checked if the player is below (or above, or from the left/right), which would allow you to pass through the collision in some directions. Collision does not need to be "nothing can ever penetrate this square tile" -- although it can be. It depends on what you need/want.

In both cases, you need to do more checking that just on a tile level. You'll want to store and check a more finely detailed position.

Hello to all my stalkers.

For the signs in zelda, the sign exists in two tiles, but only the base is blocking movement. For your other picture you could also increase your tile granularity (ie decrease tilesize), and the 'half forest', 'half path' tiles are actually fully unblocked tiles.

I guess what I'm getting at, is you can separate what is rendered in a tile from how a tile is navigated.

Out of curiosity, how are you implementing collision now? I think the easiest answer will depend on that. It could be as simple as just increasing a value on your collision detection, or require you to re-think how you're currently implementing it. If you're simply just saying, "if tile = X type of tile, don't move," then probably the easiest solution would be to make your diagonally textured tiles the same "type" as your road tiles and only return a collision on tiles that are 100% forest. But, again, this really all depends on how you're currently doing things.

I haven't used rpgmaker though, so perhaps the collision detection doesn't allow for much programming wiggle-room. Are you able to define what constitutes a road tile?

Beginner here <- please take any opinions with grain of salt

From what I've seen, a lot of developers these days just use the overkill method of a full-on 3D physics engine, simply because the tools are available, cheap or free, and high quality, and gaming devices are powerful enough to run basic avatar collision with ease. For a while there weren't many non-custom options that were specifically for 2D, so 3D physics engines were used with various constraints to make them behave more or less in 2D space. Fortunately there are now more options for natively 2D engines, such as Box2D or Chipmunk.

So if using the above strategy, in your case you'd just end up defining a basic collision shape that was close enough to the visual representation to work for each terrain tile image you use, another collision shape for your avatar (a circle might even be sufficient), and then just let the physics engine do the rest of the work for you. It might seem heavy-handed, but it can save a ton of development time, makes certain feature easy that you might not have even considered beforehand, and the CPU itself is barely even gonna notice in most cases.

"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke

There's lots of ways to handle finer-grained collision --

One simple way is is to not have just one Boolean 'collidable' flag for the tile, but multiple flags. For example, you could have 4 flags that correspond to "can I move through this tile moving from left to right?", "...from right to left?", "... from top to bottom?", "...from bottom to top?". Or, 8 flags corresponding to "can I enter this tile from the top, bottom, left, and right? Can I leave this tile heading up, down, left, and right?" Or, have 16 flags that correspond to positions in a 4x4 grid that sub-divide the tile into collidable units. Sometimes people treat those 16 flags as a kind of 'code-word' that identifies a somewhat smoother collision segment (basically, connect the points of diagonally-adjacent collidable units, because no one wants to get eaten by a grue because they got caught on some non-obvious protrusion of the collision segments. FYI, in case its non-obvious, you probably want to encode these multiple-flags into one larger value, as having many separate Boolean's is wasteful and will blow out your cache for no good reason.

Another approach is to have a "collision mask" which is just an image equal in size to the tile where certain color values mean that the corresponding pixel in the tile is either passible or non-passible, using a single bit per pixel, or using 4/8 bits per pixel to implement the 4/8 flag schemes described above.

You can also mix and match them all -- only using the more details and more-expensive kinds of collision where you actually need it. The majority of tiles, I'd wager 80% or so, are fully passable or fully blocked and so don't need anything more than a simple boolean.

throw table_exception("(? ???)? ? ???");

Wow thanks guys, that makes a lot of sense. I am not currently working on any projects specifically but I've delved into RPG Maker a bit between college semesters, When I last worked in RPG Maker I had a pretty solid game going but was always confused on how to create more robust level designs through the use of directions other than up, down, left or right, which I couldn't do as I didn't know the things you guys just told me about. Im not planning on working in RPG maker for the time being. Im just trying to perfect my coding skills and I'd like to code my own engine some day. Thanks again everyone! :)

This topic is closed to new replies.

Advertisement