Play animation upon collision with enemy

ghz 14hours ago ⋅ 4 views

so I have loaded the images into pygame:

Explosion = [pygame.image.load('Explosion1.png'), pygame.image.load('Explosion2.png'), pygame.image.load('Explosion3.png'), pygame.image.load('Explosion4.png'), pygame.image.load('Explosion5.png'), pygame.image.load('Explosion6.png'), pygame.image.load('Explosion7.png'), pygame.image.load('Explosion8.png'), pygame.image.load('Explosion9.png'), pygame.image.load('Explosion10.png')]

and I would like, when the bullet, which is a separate class, makes a collision with the missile, it plays this animation at the position where both the bullet and the enemy collide, I'm not sure how I go around doing this?

Collision Script (In the main loop):

hits = pygame.sprite.groupcollide(enemies, bullets, True, True)

Bullet Class:

class Bullet (pygame.sprite.Sprite):
    def __init__ (self, x, y):
        super (Bullet, self).__init__()
        self.surf = pygame.image.load("Bullet.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.rect = self.surf.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.speedx = bullet_speed
    def update(self):
        self.rect.x += self.speedx

        if self.rect.left > SCREEN_WIDTH:
            self.kill()

Enemy Class:

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.image.load("Missiles.png").convert()
        self.surf.set_colorkey((255,255,255), RLEACCEL)
        self.rect = self.surf.get_rect(
            center=(
                random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
                random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(Enemy_SPEED_Min, Enemy_SPEED_Max)



    def update(self):
        self.rect.move_ip(-self.speed, 0)
        if self.rect.right < 0:
            self.kill()

all of the code is here https://pastebin.com/CG2C6Bkc if you need it!

Answer

To create an explosion animation at the point of collision between the bullet and the enemy, you need to do the following:

  1. Create a Explosion class: This class will handle the animation of the explosion (playing the frames one by one).
  2. Detect the collision: Once the collision is detected, trigger the explosion animation at the position of the collision.
  3. Update the explosion in the game loop: Each frame of the explosion will be displayed in the location where the collision occurred.
  4. Remove the explosion after the animation is completed.

Here's how you can implement these steps:

1. Create an Explosion class:

The Explosion class will handle the animation by cycling through the frames in the Explosion list.

class Explosion(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super(Explosion, self).__init__()
        self.images = [pygame.image.load(f'Explosion{i}.png') for i in range(1, 11)]
        self.current_frame = 0
        self.image = self.images[self.current_frame]
        self.rect = self.image.get_rect(center=(x, y))
        self.animation_speed = 0.1  # Adjust this to change the speed of the animation
        self.time_since_last_frame = 0
    
    def update(self, dt):
        self.time_since_last_frame += dt
        if self.time_since_last_frame >= self.animation_speed:
            self.time_since_last_frame = 0
            self.current_frame += 1
            if self.current_frame >= len(self.images):
                self.kill()  # Remove the explosion when it finishes
            else:
                self.image = self.images[self.current_frame]

2. Detect the collision:

In your main game loop, when a collision is detected using pygame.sprite.groupcollide(), you can create an Explosion object at the location of the collision.

# Collision detection (as in your current code)
hits = pygame.sprite.groupcollide(enemies, bullets, True, True)

# Create explosions at the location of the collision
for hit in hits:
    explosion = Explosion(hit.rect.centerx, hit.rect.centery)
    all_sprites.add(explosion)  # Assuming you have a sprite group for all sprites

3. Update the explosion animation:

In your main game loop, make sure to update the explosion with the correct delta time (dt), which will control the speed of the animation.

# Inside your main game loop
dt = clock.tick(60) / 1000  # Assuming you have a clock object to control framerate

all_sprites.update(dt)  # Update all sprites, including the explosion

4. Adding the explosion to the all_sprites group:

Make sure that your explosions are being added to the correct sprite group (all_sprites) so that they are drawn and updated along with other game objects (like the bullets and enemies).

Full Example:

Here's a more complete version of your code that includes these changes:

import pygame
import random
import os

# Initialize Pygame
pygame.init()

# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Explosion Animation")

# Define colors
WHITE = (255, 255, 255)

# Setup the game clock
clock = pygame.time.Clock()

# Define sprite groups
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()

# Bullet class
class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super(Bullet, self).__init__()
        self.surf = pygame.image.load("Bullet.png").convert()
        self.surf.set_colorkey(WHITE, pygame.RLEACCEL)
        self.rect = self.surf.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.speedx = 10  # Adjust the bullet speed

    def update(self):
        self.rect.x += self.speedx
        if self.rect.right > SCREEN_WIDTH:
            self.kill()

# Enemy class
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.image.load("Missiles.png").convert()
        self.surf.set_colorkey(WHITE, pygame.RLEACCEL)
        self.rect = self.surf.get_rect(
            center=(random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100), random.randint(0, SCREEN_HEIGHT))
        )
        self.speed = random.randint(2, 5)

    def update(self):
        self.rect.move_ip(-self.speed, 0)
        if self.rect.right < 0:
            self.kill()

# Explosion class
class Explosion(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super(Explosion, self).__init__()
        self.images = [pygame.image.load(f'Explosion{i}.png') for i in range(1, 11)]
        self.current_frame = 0
        self.image = self.images[self.current_frame]
        self.rect = self.image.get_rect(center=(x, y))
        self.animation_speed = 0.1  # Adjust this to change the speed of the animation
        self.time_since_last_frame = 0

    def update(self, dt):
        self.time_since_last_frame += dt
        if self.time_since_last_frame >= self.animation_speed:
            self.time_since_last_frame = 0
            self.current_frame += 1
            if self.current_frame >= len(self.images):
                self.kill()  # Remove the explosion when it finishes
            else:
                self.image = self.images[self.current_frame]

# Main game loop
running = True
while running:
    dt = clock.tick(60) / 1000  # Time elapsed since last frame in seconds

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # Shoot a bullet (example)
                bullet = Bullet(100, 300)
                all_sprites.add(bullet)
                bullets.add(bullet)

    # Update all sprites
    all_sprites.update(dt)

    # Collision detection
    hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
    for hit in hits:
        explosion = Explosion(hit.rect.centerx, hit.rect.centery)
        all_sprites.add(explosion)

    # Draw everything
    screen.fill(WHITE)
    all_sprites.draw(screen)
    pygame.display.flip()

pygame.quit()

Key Changes:

  1. Explosion class: Manages the animation of the explosion.
  2. update() method in Explosion: Updates the current frame of the explosion.
  3. Collision detection: When a collision is detected, an Explosion object is created at the position of the enemy's rect.centerx and rect.centery.
  4. all_sprites.update(dt): Updates all sprites in the game, including the explosions.
  5. all_sprites.add(explosion): Adds the explosion to the sprite group, allowing it to be drawn and updated.

With this setup, when the bullet collides with the enemy, the explosion animation will play at the point of collision, and once the animation is done, the explosion will be removed from the screen.