Python Forum
player just randomly teleporting to the edge of a platform in pygame
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
player just randomly teleporting to the edge of a platform in pygame
#6
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).
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.
Reply


Messages In This Thread
RE: player just randomly teleporting to the edge of a platform in pygame - by deanhystad - Jan-26-2023, 10:12 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] Sprites just randomly appear and dissapear in my pygame.sprite.GoupeSingle trueShadoWrr 2 2,093 Feb-13-2023, 09:34 AM
Last Post: Vadanane
  [PyGame] Players not falling from the platform, and some other errors. urmom33 1 1,717 Jan-23-2023, 10:28 PM
Last Post: deanhystad
  [PyGame] pygame, help with making a function to detect collision between player and enemy. Kris1996 3 3,428 Mar-07-2020, 12:32 PM
Last Post: Kris1996
  Randomly selecting sprite from group? michael1789 5 4,247 Nov-14-2019, 10:43 PM
Last Post: michael1789
  [PyGame] Rectangle keeps teleporting? keyfive 1 3,280 Jun-27-2018, 11:49 PM
Last Post: sonnekrieger7
  [PyGame] move randomly sprites reutB 4 8,350 Mar-29-2017, 01:12 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020