简体   繁体   中英

Collision detection for 2D platformer

I am working on platformer game and I want to do basic collision with platforms, sadly still can't do it properly. Player movement is calculated like this:

velocity += acceleration
position += velocity + 0.5 * acceleration

All variables are vectors with x and y value. This works as expected, problem is with collision. My rules are:

  • Stop falling when land on platform.
  • Start falling when run from platform.
  • Stop moving upwards when hit a platform during jump.
  • Stop moving to side when hit wall, but be able to move to opposite direction.

Checking if bottom collide with platform is quite simple, but tricky part is detect, which side collided with platform and be able to set proper position for player.

I was trying to detect corners and middle from every side, but since my speed is not 1px per frame, sometimes player fall to quick and was detected as side as well.

What is good approach to detect which side collided?

I have a couple of platformer-like games in javascript, and this is how I implemented collision:

1. Stop falling when land on the platform: You can give your sprite a rectangle as a boundary area, and then use Pygames built-in Rect class to detect intersection. When this intersection happens between your sprites hitbox (the rectangle) and the platforms rectangle (another rectangle) you would set your players Y velocity to 0.

2. Start falling when running off-platform. I usually have a variable devoted to gravity, and simple constantly apply this to the sprite to push it down. This way, after you are no longer intersecting with a platform, it will fall downwards.

3. Stop moving upwards when hit a platform during a jump: The same thing as the before the intersection simply set the Y velocity to 0 after a rectangle collision, and let the player fall because of the constant gravity.

4. Stop moving to the side when hit wall, but be able to move to the opposite direction: Same thing, but set X velocity to 0 this time. (if you are getting stuck in a wall, you could always set X to more than 0 to nudge you back into play)

One more note, if you only want to do something when your sprite hits a certain edge of a platform, you can just create a rectangle that aligns with the side of a sprite. For example, if I wanted to see if something intersected with the left side of my sprite, I could use - height: same height - width: 1 - x: x + width - y: same y

Documentation on rectangles: https://www.pygame.org/docs/ref/rect.html

Well here is come code that can help to detect when you can jump from a platform:

self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2

# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0:
    velocity += acceleration
    position += velocity + 0.5 * acceleration

Then code for detecting when you fall onto a platform:

if self.rect.y >= constants.SCREEN_HEIGHT and self.change_y >= 0:
    self.change_y = 0
    self.rect.y = constants.SCREEN_HEIGHT

And finally collision code:

block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
    # If we are moving right,
    # set our right side to the left side of the item we hit
    if self.change_x > 0:
        self.rect.right = block.rect.left
    elif self.change_x < 0:
        # Otherwise if we are moving left, do the opposite.
        self.rect.left = block.rect.right

# Move up/down
velocity += acceleration
position += velocity + 0.5 * acceleration

# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:

    # Reset our position based on the top/bottom of the object.
    if self.change_y > 0:
        self.rect.bottom = block.rect.top
    elif self.change_y < 0:
        self.rect.top = block.rect.bottom

    # Stop our vertical movement
    self.change_y = 0

Hope this all will help in some way to provide you with the answer that you require. Note that the blocks are referring to platforms and will be checking through every platform in a given list, and I use rects as it's one of the best ways to check collisions. As for change_x and change_y it's simply variables that store how much the player will be moving by.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM