[Pygame] Issue displaying a group of sprites
gaffeur -
Hello,
I'm starting with Python and I would like to make my own games with Pygame.
In my program, when I try to display my group of sprites, it doesn't work and I don't know why.
Here is my code:
import pygame pygame.init() background = pygame.image.load("PygameAssets-main/bg.jpg") ecran = pygame.display.set_mode((1080, 720)) joueur = pygame.image.load("PygameAssets-main/player.png") x = 400 y = 450 ecran.blit(joueur, (x, y)) velocity = 5 pygame.key.set_repeat(4,20) class projectile(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load("PygameAssets-main/projectile.png") self.rect = self.image.get_rect() running = True v = 0 while running == True: projectilegroup = pygame.sprite.Group() def launch(): global v v += 1 print(v) projectilegroup.add(projectile()) ecran.blit(background, (0, -250)) projectilegroup.draw(ecran) ecran.blit(joueur, (x,y)) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT and x < 915: x += velocity elif event.key == pygame.K_LEFT and x > -30: x -= velocity elif event.key == pygame.K_SPACE: print(event.key) launch() pygame.display.update() pygame.quit() Thanks in advance.
1 answer
-
Good evening, the problem is that you declare your group of sprites in every loop iteration, the same goes for your launch function; it should not be inside your loop. What should happen roughly in your code is: the player shoots, a new projectile is created, its position should then automatically move in a given direction, it should be destroyed if it encounters an obstacle or if it leaves the screen. This movement, you can implement in your Projectile class by modifying the rectangle’s coordinate, and one advantage of using groups is that you can perform a group.update, which will automatically update every sprite in the group; we can take advantage of this here by using the update method to move the projectiles. Prefer using pygame.key.get_pressed() rather than pygame.key.set_repeat(), this will allow using multiple keyboard keys simultaneously. It is also wise to regulate the game’s fps by using pygame.time.Clock() I preferred that the Projectile class manages its own groups. Here is a rough idea of what it would look like following these indications. Since I don’t have the images, I’ve slightly modified it to make a simple reproducible example; you can replace the images with your own code.
import pygame FPS = 60 PLAYER_VELOCITY = 3 FIRE_DELAY = 150 # delay between shots in ms SCREEN_WIDTH = 1080 SCREEN_HEIGHT = 720 pygame.init() ecran = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # background= pygame.image.load("PygameAssets-main/bg.jpg") background = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)).convert_alpha() background.fill(pygame.Color('black')) # joueur = pygame.image.load("PygameAssets-main/player.png") joueur = pygame.Surface((50, 20)).convert_alpha() joueur.fill(pygame.Color('blue')) projectile_group = pygame.sprite.Group() x = 400 y = 450 class projectile(pygame.sprite.Sprite): speed = 12 def __init__(self, x, y, group): super().__init__() group.add(self) self.group = group # self.image = pygame.image.load("PygameAssets-main/projectile.png") self.image = pygame.Surface((25, 5)).convert_alpha() self.image.fill(pygame.Color('yellow')) self.rect = self.image.get_rect() self.rect.topleft = x, y def update(self): self.rect.x += self.speed if self.rect.x > SCREEN_WIDTH: self.group.remove(self) clock = pygame.time.Clock() running = True fire_last_time = 0 while running: ecran.blit(background, (0, -250)) # déplacements des projectiles projectile_group.update() projectile_group.draw(ecran) ecran.blit(joueur, (x, y)) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False keys = pygame.key.get_pressed() if keys[pygame.K_RIGHT] and x < SCREEN_WIDTH - joueur.get_width(): x += PLAYER_VELOCITY if keys[pygame.K_LEFT] and x > 0: x -= PLAYER_VELOCITY if keys[pygame.K_SPACE] and fire_last_time + FIRE_DELAY < pygame.time.get_ticks(): projectile(x + joueur.get_width(), y, projectile_group) fire_last_time = pygame.time.get_ticks() pygame.display.update() clock.tick(FPS) pygame.quit()There are obviously many things to modify: the projectile’s vertical position, its direction, if the player moves to the left, the projectile should be fired in that same direction.