Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411485 Posts in 69371 Topics- by 58428 Members - Latest Member: shelton786

April 24, 2024, 06:36:48 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsBasic Platformer Physics
Pages: [1]
Print
Author Topic: Basic Platformer Physics  (Read 6439 times)
aschearer
Level 1
*



View Profile WWW
« on: April 13, 2009, 11:43:12 PM »

I'm currently working on a platformer and thought I'd write about some of the lessons learned along the way. I just finished writing my first post which focuses on writing the physics for a platformer. Here's an early demo of my engine in action:

*Click to play*



In order to accomplish this I needed to implement three things. First, some form of collision detection. In this case I use AABB's and the grid data structure (originally borrowed from the N tutorials.) This approach divides the game up into a set of cells and then checks the bodies in a given cell against eachother for intersection. With this in place we're able to determine when two bodies intersect.

With boolean hit detection in place we next need to implement an interface which the grid can use. I generally use something like so:

Code:
interface PhysicalActor {
    public float getX(); // top left corner
    public float getY();
    public float getWidth();
    public float getHeight();
    public float getXVelocity();
    public float getYVelocity();
    public void setPosition(float x, float y); // sets top left corner
    public void setVelocity(float x, float y);
    public void onCollision(PhysicalActor body, int side); // put custom response logic here
}

Since most platformers involve running and jumping we'll need some way to represent gravity. The easiest way is to simply increase the speed of an object downwards a given amount on each update of the game loop. You'll probably want an additional interface to represent this:

Code:
interface GravityActor {
    public boolean isGrounded(); // is on the ground
    public void setGrounded(boolean b);
    public void applyGravity(); // should be called on update whenever not grounded
}

In practice I take the following approach:

  1. Set each object as not being grounded
  2. Sweep for intersections
  3. Resolve any intersections as necessary
  4. Mark objects as being grounded as necessary
  5. Update each object, accelerating those which are falling

In order to address step #3 and #4 we need to develop a way to resolve collisions and determine on which side a collision occurs. I use a simple approach, imagine you have two AABB's object A and object B, if

  * A is moving down, i.e. has y velocity greater than zero, AND
  * Before A moved it was above B, i.e. A’s bottom - A’s y velocity less than B’ top
  * THEN A struck B's top side, therefore A should be grounded.

You can easily adapt this approach to determine whether A struck B's bottom, left, and right sides.

Anyway, that about covers this whirlwind tour :-) Feel free to check out my original post for additional details, links, and code. You'll also find source code for the grid data structure I touched on above. Hopefully this will be helpful for someone and I look forward to continuing the series in the near future!

p.s. if anyone can tell me how to directly embed flash I'd appreciate it. The "flash" button doesn't seem to have done the trick.
« Last Edit: May 12, 2009, 06:59:25 PM by Derek » Logged

My site: Spotted Zebra
Kneecaps
Level 3
***



View Profile
« Reply #1 on: April 15, 2009, 04:52:26 PM »

I'm not sure that it's a good thing to sweep for intersections in a place that the object is already in, which (if I'm not mistaken) it looks like you're doing.  When doing collision detection, I usually test an where an object is going to be, rather than where it currently is.  This keeps objects from having that awkward bounce at the end of a jump that occurs in your demo.
Logged
aschearer
Level 1
*



View Profile WWW
« Reply #2 on: April 15, 2009, 05:01:05 PM »

Ah, the demo has a problem because it actually updates the objects then checks for collisions. It should have reversed those steps. In practice this is a relatively simple approach which I find works. If I follow you you're suggesting projecting the object along it's movement vector and seeing if it intersects anything along the way? That's a more thorough approach but is also considerably more complex.

What I do is the following:

  1. Check for intersections
  2. Resolve them
  3. Update objects (i.e. move them)
  4. Render everything

Obviously this can lead to instances where an object tunnels through a second one, but so far I haven't had any real problems with it.

Thanks for pointing out the flaw with the demo. I will update it tomorrow with the latest build of the platformer.
Logged

My site: Spotted Zebra
Martin 2BAM
Level 10
*****


@iam2bam


View Profile WWW
« Reply #3 on: May 10, 2009, 02:13:13 AM »

yep, updating (moving) should be before collision checks to avoid what Kneecaps said.

Quote
  * A is moving down, i.e. has y velocity greater than zero, AND
  * Before A moved it was above B, i.e. A’s bottom - A’s y velocity less than B’ top
  * THEN A struck B's top side, therefore A should be grounded.

I don't see the reason for the second check. With y-vel > 0 and the intersection it should suffice.

Regards
-Martín
Logged

Working on HeliBrawl
aschearer
Level 1
*



View Profile WWW
« Reply #4 on: May 10, 2009, 05:29:28 AM »

No you need the second check for some cases. For instance, what if the player runs into a wall on his left side then turns around to move right. In my experience it's possible for the player's bounding box to clip the wall on the left but without the second check we'd register the collisions as hitting the wall's left side (because the player is moving right) which is incorrect.
Logged

My site: Spotted Zebra
Martin 2BAM
Level 10
*****


@iam2bam


View Profile WWW
« Reply #5 on: May 10, 2009, 11:59:47 AM »

You're correct, but I'm not talking about collision response (i.e. push the collided object away), but the "on ground" thingy   Grin

You couldn't instantly have an opposite y-vel as you can only jump when "grounded".
Logged

Working on HeliBrawl
Zaratustra
Level 7
**



View Profile WWW
« Reply #6 on: May 10, 2009, 03:51:44 PM »

I jumped at the right wall, clipped through it, and fell into space.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic