Jump to content

My approach to slopes (curious to see others)


Berzee
 Share

Recommended Posts

I didn't see any posts about slopes since April (which is a rare and astonishing thing for a 2d framework forum!) so I thought I'd share/ask. Maybe something's been added to Phaser proper since then and this post is needless ^_^ but here's what I did to get some fairly passable 45° slopes. It's just a replacement for the collideSpriteVsTilemapLayer function, that tweaks sprite.y after collision whenever the tile in question is a slope.

 

It seems to work pretty well, although it has that problem where the sprites look like just the tip of their toe is touching the ramp. (And it doesn't work with bounce-physics yet...but it's a start!). I had it in a collisionCallback for a while, but moved it inside the collide function when I wanted to prevent the "separateTile" from ever happening if the sprite was still on the "not solid" half of the tile.

 

Mostly, I am just interested to see how other people have tackled the problem and if anyone's discovered a more elegant and beautiful approach, or see if there's Phaser games out there using slopes that I could look at for entertainment and edification. Best regards!

 

Slopes test game: http://jake.brasee.com/games/phasertest/slopetest/

 

Codez:

var upwardSlopes = [13]; //list of tiles that slope up from left to rightvar downwardSlopes = [14]; //list of tiles that slope down from left to right//differences from ordinary collideSpriteVsTilemapLayer are in boldfunction collideSpriteVsTilemapLayer_forSlopes(sprite, tilemapLayer, collideCallback, processCallback, callbackContext) {    this._mapData = tilemapLayer.getTiles(sprite.body.x, sprite.body.y, sprite.body.width, sprite.body.height, true);    if (this._mapData.length === 0)    {        return;    }    for (var i = 0; i < this._mapData.length; i++)    {        var tile = this._mapData[i];        var slopeDistanceBeneathPlayer = 0;        if(upwardSlopes.indexOf(tile.tile.index) >= 0 && sprite.body.right < tile.right)        {            slopeDistanceBeneathPlayer = Math.max(0, tile.right - sprite.body.right);        }        else if(downwardSlopes.indexOf(tile.tile.index) >= 0 && sprite.body.x > tile.x)        {            slopeDistanceBeneathPlayer = Math.max(0, sprite.body.x - tile.x);        }                var shouldSeparate = (slopeDistanceBeneathPlayer == 0 || sprite.body.bottom > tile.y + y);                if (shouldSeparate && this.separateTile(sprite.body, this._mapData[i]))        {            //  They collided, is there a custom process callback?            if (processCallback)            {                if (processCallback.call(callbackContext, sprite, this._mapData[i]))                {                    this._total++;                    if (collideCallback)                    {                        collideCallback.call(callbackContext, sprite, this._mapData[i]);                    }                }            }            else            {                this._total++;                if (collideCallback)                {                    collideCallback.call(callbackContext, sprite, this._mapData[i]);                }            }                        if(y > 0)            {                sprite.body.y += y;                sprite.body.updateHulls();            }        }    }}function preload(){    // other stuff...    game.physics.collideSpriteVsTilemapLayer = collideSpriteVsTilemapLayer_forSlopes;}
Link to comment
Share on other sites

I've been working LOTS of tilemaps recently (not as much as I wanted this week as I've been ill, but will get back on it soon). I redid the way collision works entirely, it's all done with 'interesting faces' now and in a single sweep with no body hull, rather than being split out like it was before. This fixes a tonne of bugs like sprites tunneling if they were rotated and corner clipping. The best part is it's very easy to extend with slopes, so I'll look at that next. Just need some really tidy and compact math for all the various slope types (more than just 45 degrees)

Link to comment
Share on other sites

it's all done with 'interesting faces' now and in a single sweep with no body hull, rather than being split out like it was before

 

Interesting faces sound interesting! I look forward to my wonky workaround being obsolete. ^_^

 

Mike, the ball will surely return =) it was just spirited away (along with animations of all kinds) in order that the collision logic could bask in the spotlight.

Link to comment
Share on other sites

I assume from the "interesting faces" comment that you're using something akin to the 'xcom' method (written up in one of the 'game gems' books IIRC). I think the 'N' guys used this too...

 

if you support only triangular shaped sloped tiles, slopes only add a single extra axis to project (with SAT collision resolution). and if you limit to certain slopes then the normals for those slopes will be pre-calc'd and the projection isn't terribly expensive (and is only done for the "interesting" faces that are marked sloped). not as cheap as vertical and horizontal projections, obviously, but acceptable.

 

it would be great to see this implemented in Phaser. I have part of it hacked together to patch in, but I'll wait and see the new tilemap collision code before I go any further. no point in wasting time duplicating effort!

Link to comment
Share on other sites

Yup. I ditched the old system entirely and have re-written collision from scratch and am finding much better results from it. It works by walking the tiles and only making note of the faces that matter, ignoring those joined to an adjacent tile. And yes it then determines how far 'into' the tile it is for collision/separation. If more than one tile collides it'll poll them all together rather than one-by-one like it did before. This now works properly with rotated sprites, fast sprites and irrespective of body sizes (so properly offset bodies). I still need to solve camera following (it works, but deadzones aren't quite right).

 

post-1-0-26553000-1386637710.png

 

Also doing this meant I managed to support more Tiled features, such as multiple tile sets per layer and tile and layer properties.

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...