Dec-28-2019, 02:54 AM
When I collide into a platform, the player is supposed to stop moving, and it did, but it also glitched slightly into the rectangle, so I found a work-around which is supposed to make the background move slightly over in order to compensate, but it only moves one platform, and if you were to repeatedly run into a platform it would cause it to shift indefinitely. I'm also currently just making it equal to the players left and right sides, but when I use Level(self).bgX += 10 inside the if statement in the player class that controls collisions it doesn't work, and I end up just glitching inside of it.
Here is my code:
Here is my code:
import pygame BLACK = (0, 0, 0) WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) BLUE = (0, 255, 255) SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() width = 40 height = 60 self.image = pygame.Surface([width, height]) self.image.fill(RED) self.rect = self.image.get_rect() self.xVel = 0 self.yVel = 0 self.level = None def update(self): self.calc_grav() Level(self).bgX += self.xVel block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) for block in block_hit_list: if self.xVel < 0: self.friction() block.rect.left = 350 + 40 elif self.xVel > 0: self.friction() block.rect.right = 350 self.rect.y += self.yVel block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) for block in block_hit_list: if self.yVel > 0: self.rect.bottom = block.rect.top elif self.yVel < 0: self.rect.top = block.rect.bottom self.yVel = 0 if isinstance(block, MovingPlatform): Level(self).bgX += block.xVel def calc_grav(self): if self.yVel == 0: self.yVel = 1 else: self.yVel +=0.5 if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.yVel >= 0: self.yVel = 0 self.rect.y = SCREEN_HEIGHT - self.rect.height def jump(self): self.rect.y += 2 platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) self.rect.y -= 2 if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT: self.yVel = -15 def moveLeft(self): self.xVel = 6 def moveRight(self): self.xVel = -6 def friction(self): self.xVel = 0 class Platform(pygame.sprite.Sprite): def __init__(self, width, height): super().__init__() self.image = pygame.Surface([width, height]) self.image.fill(GREEN) self.rect = self.image.get_rect() class MovingPlatform(Platform): xVel = 0 yVel = 0 boundary_top = 0 boundary_bottom = 0 boundary_left = 0 boundary_right = 0 player = None level = None def update(self): self.rect.x += self.xVel hit = pygame.sprite.collide_rect(self, self.player) if hit: if self.xVel < 0: self.player.rect.right = self.rect.left else: self.player.rect.left = self.rect.right self.rect.y += self.yVel hit = pygame.sprite.collide_rect(self, self.player) if hit: if self.yVel < 0: self.player.rect.bottom = self.rect.top else: self.player.rect.top = self.rect.bottom if self.rect.bottom > self.boundary_bottom or self.rect.top < self.boundary_top: self.yVel *= -1 cur_pos = self.rect.x - self.level.bgX if cur_pos < self.boundary_left or cur_pos > self.boundary_right: self.xVel *= -1 class Level(object): def __init__(self, player): self.platform_list = pygame.sprite.Group() self.enemy_list = pygame.sprite.Group() self.player = player self.background = None self.bgX = 0 self.level_limit = -1000 def update(self): self.platform_list.update() self.enemy_list.update() def draw(self, screen): screen.fill(BLUE) self.platform_list.draw(screen) self.enemy_list.draw(screen) for platform in self.platform_list: platform.rect.x += self.player.xVel for enemy in self.enemy_list: enemy.rect.x += self.player.xVel class Level_01(Level): def __init__(self, player): Level.__init__(self, player) self.level_limit = -1500 level = [[210, 70, 500, 500], [210, 70, 800, 400], [210, 70, 1000, 500], [210, 70, 1120, 280], ] for platform in level: block = Platform(platform[0], platform[1]) block.rect.x = platform[2] block.rect.y = platform[3] block.player = self.player self.platform_list.add(block) block = MovingPlatform(70, 40) block.rect.x = 1350 block.rect.y = 280 block.boundary_left = 1350 block.boundary_right = 1600 block.xVel = 1 block.player = self.player block.level = self self.platform_list.add(block) class Level_02(Level): def __init__(self, player): Level.__init__(self, player) self.level_limit = -1000 level = [[210, 70, 500, 550], [210, 70, 800, 400], [210, 70, 1000, 500], [210, 70, 1120, 280], ] for platform in level: block = Platform(platform[0], platform[1]) block.rect.x = platform[2] block.rect.y = platform[3] block.player = self.player self.platform_list.add(block) block = MovingPlatform(70, 70) block.rect.x = 1500 block.rect.y = 300 block.boundary_top = 100 block.boundary_bottom = 550 block.yVel = -1 block.player = self.player block.level = self self.platform_list.add(block) def main(): pygame.init() size = [SCREEN_WIDTH, SCREEN_HEIGHT] screen = pygame.display.set_mode(size) pygame.display.set_caption("Platformer with moving platforms") player = Player() level_list = [] level_list.append(Level_01(player)) current_level_no = 0 current_level = level_list[current_level_no] active_sprite_list = pygame.sprite.Group() player.level = current_level player.rect.x = 350 player.rect.y = SCREEN_HEIGHT - player.rect.height active_sprite_list.add(player) done = False clock = pygame.time.Clock() # -------- Main Program Loop ----------- while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: player.moveLeft() if event.key == pygame.K_RIGHT: player.moveRight() if event.key == pygame.K_UP: player.jump() if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT and player.xVel > 0: player.friction() if event.key == pygame.K_RIGHT and player.xVel < 0: player.friction() active_sprite_list.update() current_level.update() current_position = current_level.bgX if current_position < current_level.level_limit: if current_level_no < len(level_list)-1: player.rect.x = 350 current_level_no += 1 current_level = level_list[current_level_no] player.level = current_level else: done = True current_level.draw(screen) active_sprite_list.draw(screen) clock.tick(60) pygame.display.flip() pygame.quit() if __name__ == "__main__": main()Is there a way to make the entire background shift as opposed to just the platform? It would also help if someone could tell me why you can't just hold the right arrow key and jump simultaneously after you collide with a platform.