@twobitart @RayMPerry @pietepiet t.co/cQFOUQC6v3 (Today)

RT @rabbit_nabokov: momo 3 is 95% approved to top 100! please vote and RT to spread the word, minna!! t.co/Aw9zjkSpeZ t.co/Xo… (Today)

@legobutts Its a tool to teach american children that eating a sandwich of marshmallows is a perfectly fine meal. #diabetes (Today)

@twobitart nuuuuuudistu beachu~ (Today)

@djcoreynolan <3 (Today)

RT @djcoreynolan: dammit, life would be so excellent if I didn't have some mysterious autoimmune disease continuously sapping my HP (Today)

The fade away jumper: t.co/qaSLcckISB #TowerFall t.co/1Z1U1YF72t (Today)

@SeeBeeWhitman @NoelFB You challenge Father Time to a cage match with no ref. OOHH YEAAAH #savage (Today)

Hmm so far time boxing is working out a lot better for me if I just accept the fact that my first one or two blocks of the day might suck. (Today)

@Seagaia2 humble avocado bundle (Today)

@initials_games Whoa thanks! (Today)

@mushbuh @theBanov fuck yeah. giant metal holographic slammers! t.co/padUe7h1nL (Yesterday)

@snakepixel @ADAMATOMIC its like you have access to colors that the rest of us don't even know about JEEZ (Yesterday)

RT @snakepixel: Here we go. This is how I would do a new Breath of Fire game.You know, if I was given the option. t.co/k8iPDjBWap (Yesterday)

@infinite_ammo I haven't actually read a game review in years. If people I know like the game I'll research it a little bit then decide. (Yesterday)

@Patashu0 Maybe on Steam but not for awhile yet ;D (Yesterday)

@NorthernlionLP I am laughing with JOY! ;D (Yesterday)

@amora_b hey THANKS! :3 (Yesterday)

@NorthernlionLP hahahah <3 (Yesterday)

Added a minimap and now it totally feels like a real game. Almost. t.co/KMmutMoIdZ (Yesterday)

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 27 year old kid with adult powers. 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