# Move a 2D sprite into an irregular terrain

With a tile based engine, in my knowledge, is not possible to move a sprite into an irregular terrain. So which are the techniques to use for implementing that? Maybe an hexagonal tile based engine?

• What do you mean exactly? Do you mean like in super mario brothers where you have 1 hole gaps but if you are running you can cross it? Or the terrain is wavy or something but the character moves well either way? Or like sonic where you go up walls and pass through loops and etc? Nov 28, 2012 at 14:35
• I mean that a sprite have to move on a surface following its path. Look, for example, at this game: youtube.com/watch?v=SrYUEa00dGM Nov 28, 2012 at 14:46
• So... it's obviously possible. You can have a tile based engine that allows for free movement of sprites. If everything is tile based, including the movement, then the terrain would not be made irregular. Nov 28, 2012 at 14:50
• Yes but, generally, a 2d tile base engine is done of rectangular sprite so how can a player sprite move on an irregular shape? Nov 28, 2012 at 14:55
• The game in that video is obviously not tile based at all. But even in a tile-based game you could have ramp/stair tiles, maybe even a few of varying angles. There's only going to be so much you can do with tiled terrain though if you want really nice curves. Nov 28, 2012 at 15:26

It remember me an interesting guide i saw: http://www.gamedev.net/page/resources/_/technical/game-programming/the-guide-to-implementing-2d-platformers-r2936

"The Tile based smooth" subject explain how it works for a game like Megaman. Hope it help!

(I agree with Eric B -probably not best to make it a tile game - but thought i would answer anwyay)

If the amount of variation is less then one tile, then you could have tiles that allow user movement through them, and a corresponding table of heights for those tiles. SO lets say you divide each tile up in to 16 px portions, (64px wide tiles / 16px parts = 4 per tile), then as the center of the player moves over the tile, you could determine which of the 4 parts your player was currently on, and adjust the height. If the player was wider or had wheels, you could do the same thing for each wheel, get the height and then rotate the player to match.

But, you still need to have tiles for each shape, so you would need a lot of tiles for this. Just an idea.

I'm sorry i cannot give credits : i can't remember where i saw this gem, but here's one technique that is worth mentionning :
imagine the floor of the game is drawn on a separate layer. The floor might be any shape.

1) how do you know the sprite is on the floor ?
easiest way is to pixel test one point (or two points, one for each foot) , to see if we touched something.
Obviously first optimisation is too see wether the player is in an 'empty' tile or not. Then to have, for each non empty tiles, a few contiguous segments [ {x: , y: } , {x:, y: } ] (sorted on x) describing the slope with a settable precision. So you can quickly test a point against those segments. The segments needs to be computed once per tile type.

2) how do i know the normal to the point of contact ?
this normal is required to compute the rotation of our player.
If we have the list of segment, you can use the slope of the current segment to compute the normal. And you have tu use neighboring segments to smoothen the changes. Could be tricky with arbitrary length (x2-x1) segments. And how to be precise enough ? not too slow ? work whatever the game's scale/resolution ?
That's where comes the gem :
1) take the 3X3 pixel array surrounding the point of contact.
2) now sum up every vectors coming from center point (1,1), but only if the corresponding pixel is not transparent.
3) norm the resulting vector, reverse it ( {x: -x, y; -y } ) and here we go ! we have our estimation of the normal.
Yes : the end : Magic !

Rq1) you might want to use a 5X5 or 7X7 grid. In fact in the article i saw that a 3X3 was perfect for a game with gentle slopes ( < Pi/8 ).
Rq2) get the image with getImageData or webkitGetImageDataHD, then iterate through the image.data. You might want to test a pixel for being null in one read if you set up a 32 bits view on the image.data, ( which is originaly a UInt8ClampedArray ) :

var my32BitView = new Int32Array(image.data.buffer);
var pixelIndex = 0,
var isPixelEmpty = ( my32BitView[pixelIndex] == 0 );
pixelIndex+=;


Rq3) if you go for a 5X5 matrix, compute first the norm of the 3X3, then end the matrix computation to get the 5X5 norm. if you compare the two norms you can know about a near edge : another magic !!!
Rq4) if you have two points of contact... do it twice !! :-)
Rq5) you can precompute the (x-xcenter) (y-ycenter) of the vectors within an array (of { x :, y: }) or two (of numbers) then you can go and add linarly sum the x and y if there's a pixel in corresponding image data array. One while (--) loop !