After using and modifying your Platforming Tutorial, I have a few additions I've thrown in. The main two (which I'd like to share) are an air control variable and one-way platforms.
I made a platforming game of my own a few years ago in GameMaker, and it turns out that you tend to do a lot of things the same way I had done. (I found your collision detection to be more effective in this case than the way I had done in GameMaker, however.)
This is kind of going out to everyone, by the way, meant as sort of an addition.
EDIT: I updated the actual engine files and posted them in a later post. The rest of this post is mostly pointless now, but it's still is an okay explanation I guess.
Anyway, air control is very simple. One-way platforms are a little trickier. I'll start with air control.
First, these are the player variables I'm using:
private var xVelocity:Number = 0;
private var yVelocity:Number = 0;
private var acceleration:Number = 1;
private var friction:Number = 2;
private var maxXVelocity:Number = 8;
private var jump:Number = 20;
private var gravity:Number = 2;
private var maxFall:Number = 20;
private var airControl:Number = .5;
private var onGround:Boolean = false;
They're mostly the same (though some have different names), but I've added maxFall, airControl, and onGround. onGround is fairly self-explanatory. maxFall is just another limit for the player's speed. Including this can give the player a lot more control over the character, which I always think is important. I almost always set this to the same as the jump variable. airControl is the percentage of control the player gets when in the air. I find that 50% airControl feels natural (even though 0% is the most natural). Removing perfect air control, interestingly, can actually give players
more control by allowing them to slow their jumps instead of simply changing direction. I've found that there are few situations where the player needs to change direction mid-air, but many where the player needs to adjust mid-air speed. By the way, the values I'm using are for 64x64 sprites. That just happens to be the size of the sprites I'm planning to eventually use. Until then I've just scaled up Noel's sprites.
The first thing I do in the update function is update onGround.
//ground check
onGround = collide("wall", x, y + 1);
All this actually does is make the code a little cleaner. It will also help a lot when we add one-way platforms.
Now, in the left and right checks, we just make a second check to see if the player is on the ground. If it isn't, multiply by airControl.
//moving left
if (Input.check("left")) {
sprPlayer.flipped = true;
sprPlayer.play("move");
if (onGround) {
xVelocity -= acceleration;
}
else {
xVelocity -= acceleration * airControl;
}
}
//moving right
if (Input.check("right")) {
sprPlayer.flipped = false;
sprPlayer.play("move");
if (onGround) {
xVelocity += acceleration;
}
else {
xVelocity += acceleration * airControl;
}
}
One little note here is that I'm using sprite mirroring. Depending on your sprites, you may or may not want this.
That's all there is to airControl. Be sure to test it before moving on. Next is one-way platforms. These are actually very easy. We only need to create them, and make a couple of extra checks.
Step one is making them. I'm calling them ledges. The name isn't important.
package {
/**
* ...
* @author Van Phelan
*/
import net.flashpunk.Entity;
public class Ledge extends Entity {
public function Ledge() {
setHitbox(64, 1, 0, 0);
type = "ledge";
}
}
}
They're identical to ordinary walls, except for their type and their hitbox. We only want to check collisions with the topmost pixels. Once again, my sprites are 64x64. Oh, and don't forget to include the sprite for ledges.
Next, we modify our onGround update to include ledges.
//ground check
onGround = (collide("wall", x, y + 1) || (collide("ledge", x, y + 1) && !collide("ledge", x, y)));
Now, in addition to checking if you're on a wall, it will check to see if you're on a ledge,
but not inside the ledge. Normally, when you check if something is one pixel under you, it will check if it is under
each of your pixels. That's why we have to also make sure the ledge doesn't intersect the player. Otherwise we can get stuck halfway through the ledge.
The only thing left is modifying vertical collision-checks. I have it formatted differently than Noel, but its otherwise about the same. I've also added in checks for our ledges.
//vertical motion and collisions
for (i = 0; i < Math.abs(yVelocity); i++) {
if (!collide("wall", x, y + FP.sign(yVelocity)) && !(collide("ledge", x, y + 1) && yVelocity > 0 && !collide("ledge", x, y))) {
y += FP.sign(yVelocity);
}
else {
yVelocity = 0;
break;
}
}
The ledge check is about the same as the wall check, but we want to make sure that it is under us (it's one-way, remember?), that we're actually moving downward, and that we aren't intersecting the ledge.
That's all their is to it, but if you want to also allow the player to drop from the platform, you can do so like this:
//dropping
if (Input.check("down") && Input.pressed("jump")) {
if (collide("ledge", x, y + 1) && !collide("wall", x, y + 1)) {
y++;
}
}
//jumping
else if (Input.pressed("jump") && onGround) {
yVelocity = -jump;
}
All dropping does is move you one pixel down. Since the ledge's hitbox is only one pixel, and our collision checks don't include intersections, this moves us completely through it. I put the dropping code before jumping so that jumping can become an else if. That way you won't accidentally jump in some cases. I used Input.pressed() for jumping, but Input.check() should work just as well.
Result:
http://flashgamedojo.com/u/7sdm7t/I probably forgot to mention a hundred things, so yeah, if this doesn't work, let me know.
Oh, and I forget to mention jump is the spacebar.