Sunday, April 26, 2015

2d - Sidescroller variable terrain heightmap for walking/collision


I've been fooling around with moving on sloped tiles in XNA and it is semi-working but not completely satisfactory. I also have been thinking that having sets of predetermined slopes might not give me terrain that looks "organic" enough. There is also the problem of having to construct several different types of tile for each slope when they're chained together (only 45 degree tiles will chain perfectly as I understand it).


I had thought of somehow scanning for connected chains of sloped tiles and treating it as a new large triangle, as I was having trouble with glitching at the edges where sloped tiles connect. But, this leads back to the problem of limiting the curvature of the terrain.


So...what I'd like to do now is create a simple image or texture of the terrain of a level (or section of the level) and generate a simple heightmap (of the Y's for each X) for the terrain. The player's Y position would then just be updated based on their X position.


Is there a simple way of doing this (or a better way of solving this problem)? The main problem I can see with this method is the case where there are areas above the ground that can be walked on. Maybe there is a way to just map all walkable ground areas?


I've been looking at this helpful bit of code: http://thirdpartyninjas.com/blog/2010/07/28/sloped-platform-collision/ but need a way to generate the actual points/vectors.



EDIT: I did try pregenerating sloped paths using the link I posted but now I'm convinced I should use per-pixel collision as you suggested. I've been looking at the example at: http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel and am trying to figure out how to adjust the sprite once a collision has been detected. As David suggested, I made a few sensor points (feet, sides, bottom center, etc.) and can easily detect when these points actually collide with non-transparent portions of a second texture (simple slope). I'm having trouble with the algorithm of how I would actually adjust the sprite position based on a collision.


Say I detect a collision with the slope at the sprite's right foot. How can I scan the slope texture data to find the Y position to place the sprite's foot so it is no longer inside the slope? The way it is stored as a 1D array in the example is a bit confusing, should I try to store the data as a 2D array instead?


I also noticed several people mention that it's best to separate collision checks horizontally and vertically, why is that exactly?



Answer



I don't think you should try converting the entire map into a single height map, exactly because of the problem you described. Maps can have arbitrary complexity which you wouldn't be able to represent in a height map.


But you don't need to have a fixed slope for each type of tile either. You could store collision information on a per pixel basis for each type of tile or compute it from the tile's alpha channel and use it to determine where the character should stand at each moment based on the tiles he's currently intersecting. Here's an example of the collision data for one tile:


enter image description here


Using this scheme you can have any type of slope you want just by varying the tile's collision mask. This is how Sonic games were implemented back in the day, and as such I suggest reading the following page in its entirety for a better understanding:


http://info.sonicretro.org/SPG:Solid_Tiles#Slopes_And_Curves


Then in order to process collisions between your character and the environment, I suggest defining a few sensors or collision points on your character, such as the magenta dots on the image below:



enter image description here


For instance, the top sensors could be used to detect and react to collisions with the ceiling, the middle sensors could be used to detect and react to collisions against walls, and the bottom sensors could be used to detect collisions with the floor and determine the correct height for the player. By moving the middle sensors up and down you can control how steep a slope has to be before the player can no longer climb it.


Another neat trick you can do with the bottom sensors, is depending on how many of them are colliding with the floor, you can detect when the player is near a ledge and possibly play a different animation such as the image below.


enter image description here


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...