Jan-26-2023, 10:12 PM
(This post was last modified: Jan-26-2023, 10:12 PM by deanhystad.)
You should post your solution so others can benefit.
Pygame has lots of support for detecting collisions between things like players and platforms. In the code below I made the player and the platform Sprites This lets me use one line of code to check for a collision between the player and all the platforms: collision = pygame.sprite.spritecollide(self, objects, False).
I added sliding, which acts like jumping. When move keys are pressed the player accelerates instead of starting and stopping at full speed. I also added a bounce when the running into something.
I removed special code for stopping at the edges or the bottom of the screen. I get the same behavior by making side and bottom platforms that are just off the edge of the screen.
Pygame has lots of support for detecting collisions between things like players and platforms. In the code below I made the player and the platform Sprites This lets me use one line of code to check for a collision between the player and all the platforms: collision = pygame.sprite.spritecollide(self, objects, False).
import pygame GRAVITY = 0.1 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 MAP = ( # Walls, floor and assorted barriers (-20, -100, 20, SCREEN_HEIGHT + 100), (SCREEN_WIDTH, -100, 20, SCREEN_HEIGHT + 100), (0, SCREEN_HEIGHT, SCREEN_WIDTH, 20), (500, SCREEN_HEIGHT - 100, 20, 100), (0, 100), (300, 200), (500, 300), (200, 400), (400, 500), (500, 600), ) class EnhancedSprite(pygame.sprite.Sprite): """Add Rect x, y, right and bottom properties to sprite. Add draw method""" def __init__(self, image): super().__init__() self.image = image self.rect = image.get_rect() self._x = 0 self._y = 0 def draw(self, surface): surface.blit(self.image, self.rect) @property def x(self): return self._x @x.setter def x(self, value): self._x = value self.rect.x = value @property def y(self): return self._y @y.setter def y(self, value): self._y = value self.rect.y = value @property def right(self): return self._x + self.rect.width @right.setter def right(self, value): self._x = value - self.rect.width self.rect.x = self._x @property def bottom(self): return self._y + self.rect.height @bottom.setter def bottom(self, value): self._y = value - self.rect.height self.rect.y = self._y class Barrier(EnhancedSprite): """A stationary sprite for platform game""" def __init__(self, x, y, wide=200, high=20, color="green"): image = pygame.Surface((wide, high)) image.fill(color) super().__init__(image) self.x = x self.y = y class Ball(EnhancedSprite): """A player for the platform game""" def __init__(self, radius=15, speed=3, jump=6, color="red"): image = pygame.Surface((radius * 2, radius * 2)) image.fill("black") pygame.draw.circle(image, color, (radius, radius), radius) super().__init__(image) self.speed = speed self.jump_speed = jump self.jumping = False self.x_velocity = 0 self.y_velocity = 0 def jump(self): """Jump up in the air if standing on ground or platform""" if not self.jumping: self.y_velocity = -self.jump_speed self.jumping = True def move(self, direction, barriers=None): """Move player, detect collisions with barriers""" # Move in x direction if not self.jumping: # No changing direction while in the air. speed = self.speed * direction if speed > self.x_velocity: self.x_velocity = min(speed, self.x_velocity + GRAVITY) else: self.x_velocity = max(speed, self.x_velocity - GRAVITY) self.x += self.x_velocity if barriers: collision = pygame.sprite.spritecollide(self, barriers, False) if collision: # Bumped into something. collision = collision[0] if self.x_velocity > 0: self.right = collision.x else: self.x = collision.right self.x_velocity = -self.x_velocity / 2 # Move in y direciton self.y_velocity += GRAVITY self.y += self.y_velocity if barriers: collision = pygame.sprite.spritecollide(self, barriers, False) if collision: # Bumped into something collision = collision[0] if self.y_velocity >= 0: # Fell onto platform self.bottom = collision.y self.jumping = False else: # Jumped up into platform self.y = collision.bottom + 1 self.y_velocity = 0 def main(): pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) clock = pygame.time.Clock() player = Ball() barriers = pygame.sprite.Group() for barrier in MAP: barriers.add(Barrier(*barrier)) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: player.jump() keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: player.move(-1, barriers) elif keys[pygame.K_RIGHT]: player.move(1, barriers) else: player.move(0, barriers) clock.tick(100) screen.fill("black") player.draw(screen) barriers.draw(screen) pygame.display.flip() pygame.quit() main()I really like how pygame Rect works. Rect.right = Rect.y + Rect.width. Rect.bottom = Rect.y + Rect.height. I made a new Sprite class that can act like a Rect. It makes the collision correction code easier to write and understand.
I added sliding, which acts like jumping. When move keys are pressed the player accelerates instead of starting and stopping at full speed. I also added a bounce when the running into something.
I removed special code for stopping at the edges or the bottom of the screen. I get the same behavior by making side and bottom platforms that are just off the edge of the screen.