[Python] Python (pygame), Error with sprites position [duplicate]

Discussão em 'Python' iniciado por Stack, Março 28, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to devellop a game with powerups, but the smoke powerup doesn't work as intended. If you move after shooting the smoke powerup, you will be teleported onto the powerup, and the smoke cloud will follow you. wich is absolutely not what wass intended. You will be teleported on it only if you move within a certain time frame (about 1 to 2 seconds. it tends to be random), and I don't know why any of that happens.

    The full code is here: https://drive.google.com/drive/folders/1C4ABYU3ZCtwTySNzQiWJl9qtAhx4AZHI?usp=drive_link

    If you need extra information, and/or more detailled explanation of the issue, ask me.

    main.py

    import pygame
    from game import Game

    #imports settings
    pygame.init()

    #base variables
    VERSION = "Beta 2.0"
    display_info = pygame.display.Info()
    WIDTH = display_info.current_w #ou 1080 ou 1500 #display_info.current_w
    HEIGHT = display_info.current_h-60 #ou 720 ou 790 #display_info.current_h-60
    game = Game(WIDTH, HEIGHT)
    print(WIDTH, HEIGHT)
    TITLE = "Projet Alpha 3 (version: "+VERSION+")" + " Round "+str(game.round)
    FPS = 60
    require_names = False

    #player names
    if require_names:
    game.name1 = input("player1 name >>> ")
    game.name2 = input("player2 name >>> ")
    game.name3 = input("player3 name >>> ")
    game.name4 = input("player4 name >>> ")

    #screen definition
    screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.RESIZABLE | pygame.SHOWN)

    pygame.display.set_caption(TITLE)

    #other variables
    running = True
    Clock = pygame.time.Clock()
    bg_color = (200, 200, 200)
    keys = {pygame.K_UP:False, pygame.K_DOWN:False, pygame.K_LEFT:False, pygame.K_RIGHT:False,
    pygame.K_z:False, pygame.K_s:False, pygame.K_q:False, pygame.K_d:False,
    pygame.K_KP8:False, pygame.K_KP5:False, pygame.K_KP4:False, pygame.K_KP6:False}

    #load maze
    game.generate_maze()
    game.load_maze()
    game.load_poteaux()

    #start loop
    while running:

    #FPS limiter
    Clock.tick(FPS)

    #check for win
    game.check_for_win()
    TITLE = "Projet Alpha 3 (version: "+VERSION+")" + " Round "+str(game.round)
    pygame.display.set_caption(TITLE)

    #event detection
    for event in pygame.event.get():
    #close window
    if event.type == pygame.QUIT:
    running = False
    #keyboard inputs
    if event.type == pygame.KEYDOWN:
    keys[event.key] = True
    #player1 shoot
    if game.alive_players.has(game.player1):
    if event.key == pygame.K_SPACE:
    if game.player1.powerups:
    game.shoot_powerup(game.player1)
    else:
    game.player1.shoot()
    #player2 shoot
    if game.alive_players.has(game.player2):
    if event.key == pygame.K_w:
    if game.player2.powerups:
    game.shoot_powerup(game.player2)
    else:
    game.player2.shoot()
    #player3 shoot
    if game.alive_players.has(game.player3):
    if event.key == pygame.K_KP0:
    if game.player3.powerups:
    game.shoot_powerup(game.player3)
    else:
    game.player3.shoot()
    if event.type == pygame.KEYUP:
    keys[event.key] = False

    #player1 controls
    if game.alive_players.has(game.player1):
    if keys[pygame.K_UP]:
    game.player1.forward()
    game.clearance(game.player1, "f")
    if keys[pygame.K_DOWN]:
    game.player1.backward()
    game.clearance(game.player1, "b")
    if keys[pygame.K_LEFT]:
    game.player1.left()
    game.clearance(game.player1, "l")
    if keys[pygame.K_RIGHT]:
    game.player1.right()
    game.clearance(game.player1, "r")

    #player2 controls
    if game.alive_players.has(game.player2):
    if keys[pygame.K_z]:
    game.player2.forward()
    game.clearance(game.player2, "f")
    if keys[pygame.K_s]:
    game.player2.backward()
    game.clearance(game.player2, "b")
    if keys[pygame.K_q]:
    game.player2.left()
    game.clearance(game.player2, "l")
    if keys[pygame.K_d]:
    game.player2.right()
    game.clearance(game.player2, "r")

    #player3 controls
    if game.alive_players.has(game.player3):
    if keys[pygame.K_KP8]:
    game.player3.forward()
    game.clearance(game.player3, "f")
    if keys[pygame.K_KP5]:
    game.player3.backward()
    game.clearance(game.player3, "b")
    if keys[pygame.K_KP4]:
    game.player3.left()
    game.clearance(game.player3, "l")
    if keys[pygame.K_KP6]:
    game.player3.right()
    game.clearance(game.player3, "r")

    #spawn powerups
    game.spawn_powers()

    #update powerups related stuff
    game.update_powers()
    for i in game.powers.balles:
    i.update()
    for i in game.powers.particules:
    i.update()

    #projectile update
    for i in game.players:
    for b in i.own_bullets:
    b.update()

    #screen filling
    screen.fill(bg_color)

    #sprites drawing
    game.powerups.draw(screen)
    for i in game.mines:
    if i.visible:
    screen.blit(i.image, i.rect)
    game.powers.balles.draw(screen)
    game.alive_players.draw(screen)
    game.walls.draw(screen)
    game.poteaux.draw(screen)
    for i in game.players:
    i.own_bullets.draw(screen)
    game.powers.particules.draw(screen)

    #load HUD
    game.load_HUD(screen)

    #tests

    #bullet collisions
    game.check_bullet_collisions()
    game.powers.check_collisions()

    #refresh screen
    pygame.display.flip()


    game.py collision function

    def check_bullet_collisions(self):
    for i in self.players:
    for b in i.own_bullets:
    b.reversed_x = False
    b.reversed_y = False
    #ball-player collisions
    for player in self.alive_players:
    if pygame.sprite.collide_rect(b, player):
    if i == player:
    if not b.invincible:
    b.kill()
    self.alive_players.remove(player)
    self.dead_players.add(player)
    else:
    b.will_invincible = 4
    else:
    b.kill()
    self.alive_players.remove(player)
    self.dead_players.add(player)
    if i == self.player1:
    self.p1_score += 1
    elif i == self.player2:
    self.p2_score += 1
    elif i == self.player3:
    self.p3_score += 1
    elif i == self.player4:
    self.p4_score += 1
    else:
    b.will_invincible -= 1
    if b.will_invincible == 0:
    b.invincible = False

    #ball-wall colisions
    for wall in self.walls:
    if b.rect.colliderect(wall.uprect) and not b.reversed_y:
    b.velocity[1] *= -1
    b.reversed_y = True
    elif b.rect.colliderect(wall.downrect) and not b.reversed_y:
    b.velocity[1] *= -1
    b.reversed_y = True
    elif b.rect.colliderect(wall.leftrect) and not b.reversed_x:
    b.velocity[0] *= -1
    b.reversed_x = True
    elif b.rect.colliderect(wall.rightrect) and not b.reversed_x:
    b.velocity[0] *= -1
    b.reversed_x = True

    #ball-poteau collisions
    for wall in self.poteaux:
    if b.rect.colliderect(wall.uprect) and not b.reversed_y:
    b.velocity[1] *= -1
    b.reversed_y = True
    elif b.rect.colliderect(wall.downrect) and not b.reversed_y:
    b.velocity[1] *= -1
    b.reversed_y = True
    elif b.rect.colliderect(wall.leftrect) and not b.reversed_x:
    b.velocity[0] *= -1
    b.reversed_x = True
    elif b.rect.colliderect(wall.rightrect) and not b.reversed_x:
    b.velocity[0] *= -1
    b.reversed_x = True
    #player-powerup collisions
    for player in self.alive_players:
    for powerup in self.powerups:
    if player.rect.colliderect(powerup.rect):
    powerup.power(player, self)
    #player-mines collision
    for mine in self.mines:
    for player in self.alive_players:
    if pygame.sprite.collide_rect(mine, player):
    if not player == mine.owner:
    self.alive_players.remove(player)
    self.dead_players.add(player)
    mine.kill()
    self.add_point(mine.owner, 1)


    powers.py

    import pygame
    import random
    from player import Player
    from wall import Wall
    from poteau import Poteau
    from powerup import Powerup
    from all_powerups.mine import Mine
    from particule import Particule
    from balle import Balle

    class Powers:

    def __init__(self, game):
    self.balles = pygame.sprite.Group()
    self.game = game
    self.particules = pygame.sprite.Group()

    def get_particule_image(self, type):
    if type == "smoke_cloud":
    return pygame.image.load('assets/smoke_cloud.png')
    if type == "bullet":
    return pygame.image.load('assets/projectile2.png')

    def check_collisions(self):
    for b in self.balles:
    b.reversed_x = False
    b.reversed_y = False
    #ball-player collisions
    for player in self.game.alive_players:
    if pygame.sprite.collide_rect(b, player):
    if b.owner == player:
    if not b.invincible:
    if b.type != "smoke":
    b.kill()
    self.game.alive_players.remove(player)
    self.game.dead_players.add(player)
    else:
    b.act()
    else:
    b.will_invincible = 4
    else:
    if b.type != "smoke":
    b.kill()
    self.game.alive_players.remove(player)
    self.game.dead_players.add(player)
    if b.owner == self.game.player1:
    self.game.p1_score += 1
    elif b.owner == self.game.player2:
    self.game.p2_score += 1
    elif b.owner == self.game.player3:
    self.game.p3_score += 1
    elif b.owner == self.game.player4:
    self.game.p4_score += 1
    else:
    b.act()
    else:
    b.will_invincible -= 1
    if b.will_invincible == 0:
    b.invincible = False

    #ball-wall colisions
    for wall in self.game.walls:
    if b.rect.colliderect(wall.uprect) and not b.reversed_y:
    if b.type != "smoke":
    b.velocity[1] *= -1
    b.reversed_y = True
    else:
    b.act()
    elif b.rect.colliderect(wall.downrect) and not b.reversed_y:
    if b.type != "smoke":
    b.velocity[1] *= -1
    b.reversed_y = True
    else:
    b.act()
    elif b.rect.colliderect(wall.leftrect) and not b.reversed_x:
    if b.type != "smoke":
    b.velocity[0] *= -1
    b.reversed_x = True
    else:
    b.act()
    elif b.rect.colliderect(wall.rightrect) and not b.reversed_x:
    if b.type != "smoke":
    b.velocity[0] *= -1
    b.reversed_x = True
    else:
    b.act()

    #ball-poteau collisions
    for wall in self.game.poteaux:
    if b.rect.colliderect(wall.uprect) and not b.reversed_y:
    if b.type != "smoke":
    b.velocity[1] *= -1
    b.reversed_y = True
    else:
    b.act()
    elif b.rect.colliderect(wall.downrect) and not b.reversed_y:
    if b.type != "smoke":
    b.velocity[1] *= -1
    b.reversed_y = True
    else:
    b.act()
    elif b.rect.colliderect(wall.leftrect) and not b.reversed_x:
    if b.type != "smoke":
    b.velocity[0] *= -1
    b.reversed_x = True
    else:
    b.act()
    elif b.rect.colliderect(wall.rightrect) and not b.reversed_x:
    if b.type != "smoke":
    b.velocity[0] *= -1
    b.reversed_x = True
    else:
    b.act()


    balle.py

    import pygame
    from particule import Particule

    class Balle(pygame.sprite.Sprite):

    def __init__(self, powers, pos, angle, image, speed, owner, life, type):
    super().__init__()
    self.powers = powers
    self.angle = angle
    self.type = type
    self.origin_image = image
    self.image = pygame.transform.rotozoom(self.origin_image, self.angle, 1)
    self.pos = pos
    self.speed = speed
    self.velocity = pygame.math.Vector2(0, self.speed)
    self.velocity = self.velocity.rotate(-self.angle)
    self.rect = self.image.get_rect(center=self.pos)
    self.lifetime = life
    if life == "normal":
    self.lifetime = 900
    self.invincible = True
    self.will_invincible = 4
    self.reversed_x = False
    self.reversed_y = False
    self.owner = owner

    def update(self):
    self.pos -= self.velocity
    self.rect = self.image.get_rect(center=self.pos)
    self.lifetime -= 1
    if self.lifetime == 0:
    self.kill()

    def act(self):
    if self.type == "smoke":
    self.powers.particules.add(Particule(self.pos, 0, 0, pygame.transform.scale(pygame.image.load('assets/Smoke_cloud.png'), (500, 500)), "smoke", 2000))
    self.kill()


    particule.py

    import pygame

    class Particule(pygame.sprite.Sprite):

    def __init__(self, pos, angle, speed, image, type, life):
    super().__init__()
    self.pos = pos
    self.angle = angle
    self.speed = speed
    self.velocity = pygame.math.Vector2(0, self.speed).rotate(-self.angle)
    self.origin_image = image
    self.image = pygame.transform.rotozoom(self.origin_image, self.angle, 1)
    self.type = type
    self.lifetime = life
    self.rect = self.image.get_rect(center=self.pos)

    def update(self):
    self.pos += self.velocity
    self.rect = self.image.get_rect(center=self.pos)
    self.lifetime -= 1
    if self.lifetime == 0:
    self.kill()

    Continue reading...

Compartilhe esta Página