@TommyRefenes PARCEIL ONIY!!! (Today)

@AsherVo @ADAMATOMIC I'm pretty sure making a game that isn't playable in a weekend is impossible (Yesterday)

@tom_hunt haha oh man that's a slippery slope... (Yesterday)

@GreyAlien Hmm yeah that's good. Right now I'm tinkering with a board game and having fun editing spread sheets full of stuff. (Yesterday)

@GreyAlien I feel like I run out of simple things to do... haha (Yesterday)

Really wish I could figure out why my brain goes from being super productive to having no motivation at all UGH (Yesterday)

@kertgartner @gabrielverdon It seems that people are really getting into this "internet" stuff! Some are even using it for businesses! (2 days ago)

@gabrielverdon @kertgartner I thought canadian internet lines were wood. (2 days ago)

@gabrielverdon @kertgartner The internet lines get cold and moose nibble on 'em so they're pretty slow, eh? (2 days ago)

@kertgartner Canada has awesome healthcare but damn it seems like all the ISPs and mobile carriers suck. (2 days ago)

@pietepiet t.co/CZoX8s1A7E (2 days ago)

@spinning_ebooks nope all that stuff is determined by demand. I didn't even know about the gem stuff until it launched haha. (2 days ago)

@infinite_ammo I charge $200 an hour for tween consulting. (2 days ago)

@infinite_ammo I pretty much only play Street Fighter IV... ;_; #indiedevconfessions (2 days ago)

RT @danielben: If you want to be a better programmer, watch this industry veteran make a full professional game from scratch *live*: http:/… (3 days ago)

@dasCameo1 the final super secret levels are unlocked through rainbow flowers ;D (3 days ago)

@konjak I'm now trained in the art of Select layer. Draw some pixels. Erase them. Now commence drawing. (4 days ago)

@TommyRefenes what are you gonna do are you gonna get googly eyes from spencers gifts and put em on my face for twitter why would you do tha (4 days ago)

I can't believe how insane the geminids are it's been like 3 or 4 meteors a minute for 5 hours ahhhhh SPACE (4 days ago)

YOOOO RED FOCUS (5 days ago)

follow
search

2013 - 2 - 20 / 10:49 am / tutorials

Colliding with Slopes?!

Colliding with Slopes?!

In my last blog post I talked a little bit about how I've implemented slopes in my latest project, but I only talked about how I was actually importing them from Ogmo Editor into Flashpunk and not about how I'm actually using them for platforming. In this post I'll attempt to explain how I actually use slopes in my movement system, which means my platformer characters can walk up and down them without any problems.

The first thing to keep in mind is that all of my slope code only really works with slopes that increase or decrease by 1 pixel. I could rework some of it to make it work with a step of any size that the programmer could define, but for now 1 step is all I really need.

Pixel Sweepin'
The first thing to know is how I actually go about moving my platformer characters, and other moving objects around my game world. I use a method that I refer to as pixel sweeping. Basically whenever an object moves in my games, I move it one pixel at a time and check for collisions at each step! This might sound a little crazy to some folk, but this is the most reliable way I've been able to do stuff like platforming and other moving objects and still collide with even the tiniest pixel of a floor or wall. I've been using this technique since the very beginning of Bonesaw: The Game.

Flashpunk actually has some functions built in that allow you to move things in this manner! You should check out the moveBy() function on the "Entity" class. This function will move the entity by an integer value, and has the option to sweep which will check each pixel for a collision. When there is a collision, it will call the functions moveCollideX() and moveCollideY() which you can override to figure out how you want to respond to collisions in each axis.

The Slope Code
In order to do slopes, I needed to basically make my own moveBy() function so that I could inject my slope code into it at the right spot. First, here's my logic behind it. We'll start with just moving horizontally, and in this example we'll say that I'm only moving to the right.

If the pixel to my right is occupied (there's a collision) then check to see if the pixel to the right, and up one pixel is free. If that's the case, then move one pixel to the right, and one pixel up. We've just moved up a slope by one pixel!

If the pixel to my right is open, then we need to check for a downward slope below! So check to see if the pixel to the right, and down one pixel is open AND check to see if one pixel to the right and two pixels down is occupied. If that is the case, then move one pixel to the right and down one pixel. That's moving down a slope! If we checked one pixel to the right, and down one pixel, and that pixel was occupied, then there is no slope, so just move one pixel to the right.

Actual Source Code
Sorry if that's a little difficult to follow. If it helps any, here is my complete function for moving in the X direction. Note that these functions are still very much a work in progress, so some stuff might not make sense... (like I don't even use that sweep boolean at all? haha!)

public function moveX(collideAgainst:Array, speed:int, sweep:Boolean = true ):void {			
var t:String;
var e:Entity;

_move.x += speed;

var movement:uint = Math.abs(_move.x);
var step:int = FP.sign(_move.x);

while (movement >= speedScale) {
var clear:Boolean = true;

e = collideTypes(collideAgainst, x + step, y);
if (e) {
if (!collideTypes(collideAgainst, x + step, y - 1)) {
y -= 1;
e = null;
}
if (!collideTypes(collideAgainst, x + step, y + 1)) {
y += 1;
e = null;
}
}
else {
if (!collideTypes(collideAgainst, x + step, y + 1)) {
if (collideTypes(collideAgainst, x + step, y + 2)) {
y += 1;
}
}
}

if (e) {
collisionX(e);
movement = 0;
_move.x = 0;
}
else {
x += step;
movement -= speedScale;
_move.x = FP.approach(_move.x, 0, speedScale);
}

}

}


And since I do some checks for slopes in the y direction as well, here's how that looks:

public function moveY(collideAgainst:Array, speed:int, sweep:Boolean = true ):void {
_move.y += speed;

var movement:uint = Math.abs(_move.y);
var step:int = FP.sign(_move.y);

while (movement >= speedScale) {
var clear:Boolean = true;


var e:Entity = collideTypes(collideAgainst, x, y + step);
if (step < 0) {
if (e) {
if (!collideTypes(collideAgainst, x + 1, y + step)) {
x += 1;
e = null;
}
if (!collideTypes(collideAgainst, x - 1, y + step)) {
x -= 1;
e = null;
}
}
}


if (e) {
collisionY(e);
movement = 0;
_move.y = 0;
}
else {
y += step;
movement -= speedScale;
_move.y = FP.approach(_move.y, 0, speedScale);
}
}
}


Both of these functions go on my "Actor" class, which extends "Entity" for some extra functionality.

As far as slopes go in the y direction, it can be a little weird. Right now the way that I use slopes in the Y direction is if you're moving upwards and hit into a slope, you'll slide along it to maintain your upward speed. This feels a little bit more natural to me, but not nearly as necessary as the horizontal movement slope code.

Don't Neglect Downward Slopes!
One thing I want to note is the IMPORTANCE of having code that sticks your objects to slopes that move downward. You might think you can get away with just code that moves your characters up slopes and let gravity do the work for the downward slopes but you are WRONG!

When you try and let gravity do the work for downward slopes you end up with an awkward bouncy walk down every slope. The worst part about this is that your character will actually be leaving the ground every time they walk off the slope to let gravity take them downward. That means whenever the player attempts to jump during this time that they are temporarily off the ground, they will fail. (That is unless you have some sort of jump forgiveness frames, but even with that there is still the issue of the awkward bouncing down the slope.) So that is why I put in the code for checking downward slopes and sticking to those as well.

That's All
Alright I think that's all I got for slopes! If you want to know more feel free to post a comment or whatever. I'll try to answer any question you might have, or if you want to see more code or more examples I can try that too.

1 Comment
Avatar

2013 - 5 - 31 2:57 AM

Shawn McCool

Great article, I like this method and I like the concept of pixel sweeping. I've been using a more traditional collision detection algorithm and I wasn't extremely happy with its reliability.

Do you notice any negatives to extending the capability to check for slopes more than 1 pixel in difference?

Avatar

Post your comment!

POST COMMENT

about

About

Hi there, my name is Kyle, and I'm a kid disguised as a grown up. I'm making video games and living the indie game developer life in Tempe, Arizona. Here you will find my thoughts, games, websites, doodles, and other stuff like that. I worked on Snapshot, Offspring Fling, and a whole bunch of other games. I also created and maintain Otter, a 2d game making framework. If you want to get a hold of me use the form on the bottom of the page, leave a comment, or just tweet at me. I try to post three times a week. Thanks for stoppin' by! You're the coolest.

facebook

videos

Do you want to make a Let's Play of one of my games, or a just a video featuring footage of my games? You have my full permission to do so! Even if you are monetizing your videos, you still have my full permission to use any footage from any of my games. Go for it!

contact

Your message has been sent! Thanks :)
SEND MESSAGE