Jun-06-2024, 07:22 PM
Hello,
I'm currently programming a small game and, apart from 2 topics, I'm almost finished. There is one topic I would like to ask about today. When an enemy is hit by a missile, an explosion animation occurs. I would like the final image of the explosion to collide with other enemies and cause them to explode as well. Unfortunately I haven't been able to fully implement it yet.
In the class Explosion all explosions with the size 1 to 4 are yellow (I use yellow images).
When the rocket Explosion hits some enemies, the enemies shall explode with a red animation. The reason is that you can differentiate the small explosions of the enemies from the big one of the rocket explosion. If they would have all the same color then you perhaps can't notice it.
In the class RocketExplosion I'm trying to check for collisions between the last image of the rocket explosion ("explosion7.png") and the enemies in the update method.
But I think the check for collisions should be in the class Explosion in the for loop (# rocket hits alien). When the rocket hits an alien the big explosion (size 4) is created.
There the picture "explosion7.png" occurs. "explosion7.png" shall be a sprite and at this place the collision detection, should be done.
It would be great, if I could get a hint how this could be done.
Thanks a lot in advance for your help!!
I'm currently programming a small game and, apart from 2 topics, I'm almost finished. There is one topic I would like to ask about today. When an enemy is hit by a missile, an explosion animation occurs. I would like the final image of the explosion to collide with other enemies and cause them to explode as well. Unfortunately I haven't been able to fully implement it yet.
In the class Explosion all explosions with the size 1 to 4 are yellow (I use yellow images).
When the rocket Explosion hits some enemies, the enemies shall explode with a red animation. The reason is that you can differentiate the small explosions of the enemies from the big one of the rocket explosion. If they would have all the same color then you perhaps can't notice it.
In the class RocketExplosion I'm trying to check for collisions between the last image of the rocket explosion ("explosion7.png") and the enemies in the update method.
But I think the check for collisions should be in the class Explosion in the for loop (# rocket hits alien). When the rocket hits an alien the big explosion (size 4) is created.
There the picture "explosion7.png" occurs. "explosion7.png" shall be a sprite and at this place the collision detection, should be done.
It would be great, if I could get a hint how this could be done.
Thanks a lot in advance for your help!!
import pygame
from PIL import Image
from pygame import mixer
from pygame.locals import *
import random, math
from itertools import product
pygame.mixer.pre_init(44100, -16, 2, 512)
mixer.init()
pygame.init()
# define fps
clock = pygame.time.Clock()
fps = 60
screen_width = 1280
screen_height = 720
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Space Invaders')
# define fonts
font30 = pygame.font.SysFont('Constantia', 30)
font40 = pygame.font.SysFont('Constantia', 40)
alien_cooldown = 1000 # bullet cooldown in milliseconds
last_count = pygame.time.get_ticks()
last_alien_shot = pygame.time.get_ticks()
# define colours
red = (255, 0, 0)
green = (0, 255, 0)
white = (255, 255, 255)
# load image
bg = pygame.image.load("bg.png")
screen_rect = bg.get_rect()
def draw_bg():
screen.blit(bg, (0, 0))
# define function for creating text
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
################ space invaders things ###############################################################################
# create spaceship class
class Spaceship(pygame.sprite.Sprite):
def __init__(self, x, y, health):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.health_start = health
self.health_remaining = health
self.image = pygame.image.load("ship.png")
self.rect = self.image.get_rect()
self.rect.center = x, y
self.xmin = self.rect.width // 2 # Compute Spaceship x range.
self.xmax = screen_width - self.xmin
self.last_shot = pygame.time.get_ticks()
def move(self, xpos):
self.xpos = xpos
self.rect.centerx = max(self.xmin, min(self.xmax, xpos))
def update(self):
# set a cooldown variable
cooldown = 500 # milliseconds
game_over = 0
# record current time
time_now = pygame.time.get_ticks()
# shoot, get key press
key = pygame.key.get_pressed()
if key[pygame.K_SPACE] and time_now - self.last_shot > cooldown:
# single bullet
single_bullet = SingleBullets(self.rect.centerx, self.rect.top)
single_bullet_group.add(single_bullet)
self.last_shot = time_now
# for later use (double bullets)
# bullet_1 = Bullets(self.rect.centerx - 43, self.rect.top)
# bullet_2 = Bullets(self.rect.centerx + 43, self.rect.top)
# update mask
self.mask = pygame.mask.from_surface(self.image)
# draw health bar
pygame.draw.rect(screen, red, (self.rect.x, (self.rect.bottom + 10), self.rect.width, 15))
if self.health_remaining > 0:
pygame.draw.rect(screen, green, (
self.rect.x, (self.rect.bottom + 10),
int(self.rect.width * (self.health_remaining / self.health_start)),
15))
elif self.health_remaining <= 0:
explosion = Explosion(self.rect.centerx, self.rect.centery, 3, "yellow")
explosion_group.add(explosion)
self.kill()
game_over = -1
return game_over
# create player
spaceship = Spaceship(screen_width / 2, screen_height - 100, 3)
# create SingleBullets class
class SingleBullets(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
weapon_list = ["bullet.png", "flash.png", "rocket.png"]
self.chosen = random.choice(weapon_list)
self.image = pygame.image.load(self.chosen)
self.rect = self.image.get_rect()
self.rect.center = x, y
def update(self):
self.rect.y -= 5
if self.rect.bottom < 0:
self.kill()
hits = pygame.sprite.spritecollide(self, alien_group, True, pygame.sprite.collide_mask)
if hits:
self.kill()
for alien in hits:
x, y = alien.hit()
if self.chosen == "rocket.png":
explosion = Explosion(x, y, 4, "yellow")
else:
explosion = Explosion(x, y, 2, "yellow")
explosion_group.add(explosion)
# create RocketExplosion class
# for hits between aliens and rocket explosion
class RocketExplosion(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
# this is the last image of the rocket's explosion, it
self.image = pygame.image.load("explosion7.png")
self.rect = self.image.get_rect()
self.rect.center = x, y
def update(self):
hits_rocket_expl_and_alien_group = pygame.sprite.spritecollide(self, alien_group, True,
pygame.sprite.collide_mask)
if hits_rocket_expl_and_alien_group:
for alien in hits_rocket_expl_and_alien_group:
x, y = alien.hit()
explosion = Explosion(x, y, 2, "red")
alien_red_explosion_group.add(explosion)
# create Aliens class
class Aliens(pygame.sprite.Sprite):
def __init__(self, x, y, move_direction):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("alien" + str(random.randint(1, 6)) + ".png")
self.x = x
self.y = y
self.move_direction = move_direction
self.rect = self.image.get_rect()
self.rect.center = x, y
def hit(self):
x = self.rect.centerx
y = self.rect.centery
self.kill()
return x, y
def update(self, move_direction):
self.rect.x += self.move_direction
if self.rect.right >= screen_width or self.rect.left <= 0:
self.move_direction = -self.move_direction
self.rect.y += 10
# update mask
self.mask = pygame.mask.from_surface(self.image)
# create Alien Bullets class
class Alien_Bullets(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("alien_bullet.png")
self.rect = self.image.get_rect()
self.rect.center = x, y
def update(self):
self.rect.y += 2
if self.rect.top > screen_height:
self.kill()
if pygame.sprite.spritecollide(self, spaceship_group, False, pygame.sprite.collide_mask):
self.kill()
# explosion2_fx.play()
# reduce spaceship health
spaceship.health_remaining -= 1
explosion = Explosion(self.rect.centerx, self.rect.centery, 1, "yellow")
explosion_group.add(explosion)
# create Explosion class
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y, size, color):
pygame.sprite.Sprite.__init__(self)
self.images = []
if color == "yellow":
for num in range(1, 8):
img = pygame.image.load(f"explosion{num}.png")
# ship is hit
if size == 1:
img = pygame.transform.scale(img, (20, 20))
# alien is hit
if size == 2:
img = pygame.transform.scale(img, (100, 100))
# ship gameover
if size == 3:
img = pygame.transform.scale(img, (160, 160))
# rocket hits alien
if size == 4:
img = pygame.transform.scale(img, (500, 500))
# add the image to the list
self.images.append(img)
self.index = 0
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.rect.center = x, y
self.counter = 0
# add the image to the list
if color == "red":
# rocketExplosion hits alien, it occurs a red explosion
for num1 in range(1, 8):
img = pygame.image.load(f"explosion2_{num1}.png")
img = pygame.transform.scale(img, (100, 100))
# add the image to the list
self.images.append(img)
self.index = 0
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.rect.center = x, y
self.counter = 0
def update(self):
explosion_speed = 3
# update explosion animation
self.counter += 1
if self.counter >= explosion_speed and self.index < len(self.images) - 1:
self.counter = 0
self.index += 1
self.image = self.images[self.index]
# if the animation is complete, delete explosion
if self.index >= len(self.images) - 1 and self.counter >= explosion_speed:
self.kill()
# create sprite groups
spaceship_group = pygame.sprite.Group()
spaceship_group.add(spaceship)
paddle_group = pygame.sprite.Group()
ball_group = pygame.sprite.Group()
single_bullet_group = pygame.sprite.Group()
flash_group = pygame.sprite.Group()
alien_group = pygame.sprite.Group()
alien_bullet_group = pygame.sprite.Group()
explosion_group = pygame.sprite.Group()
rocket_explosion_group = pygame.sprite.Group()
# a different red explosion
alien_red_explosion_group = pygame.sprite.Group()
lives_group = pygame.sprite.Group()
def create_aliens(rows, cols, move_direction):
# generate aliens
for row in range(rows):
for item in range(cols):
alien = Aliens(100 + item * 100, 100 + row * 100, move_direction)
alien_group.add(alien)
def play_space_invaders(level, move_direction):
game_over = 0
create_aliens(4, 10, move_direction)
last_count = pygame.time.get_ticks()
last_alien_shot = pygame.time.get_ticks()
countdown = 3
run = True
while run:
clock.tick(fps)
# draw background
draw_bg()
# space invaders single bullets level
if countdown == 0:
# create random alien bullets
# record current time
time_now = pygame.time.get_ticks()
# shoot
if time_now - last_alien_shot > alien_cooldown and len(alien_bullet_group) < 5 and len(
alien_group) > 0:
attacking_alien = random.choice(alien_group.sprites())
alien_bullet = Alien_Bullets(attacking_alien.rect.centerx, attacking_alien.rect.bottom)
alien_bullet_group.add(alien_bullet)
last_alien_shot = time_now
# check if all the aliens have been killed
if len(alien_group) == 0:
game_over = 1
level += 1
return level
if game_over == 0:
# update spaceship
game_over = spaceship.update()
# update sprite groups
single_bullet_group.update()
alien_group.update(move_direction)
alien_bullet_group.update()
explosion_group.update()
rocket_explosion_group.update()
alien_red_explosion_group.update()
else:
if game_over == -1:
draw_text('GAME OVER!', font40, white, int(screen_width / 2 - 100),
int(screen_height / 2 + 50))
if game_over == 1:
draw_text('YOU WIN!', font40, white, int(screen_width / 2 - 100),
int(screen_height / 2 + 50))
if countdown > 0:
draw_text('GET READY!', font40, white, int(screen_width / 2 - 110), int(screen_height / 2 + 50))
draw_text(str(countdown), font40, white, int(screen_width / 2 - 10), int(screen_height / 2 + 100))
count_timer = pygame.time.get_ticks()
if count_timer - last_count > 1000:
countdown -= 1
last_count = count_timer
# update explosion group
explosion_group.update()
rocket_explosion_group.update()
alien_red_explosion_group.update()
# draw sprite groups
spaceship_group.draw(screen)
single_bullet_group.draw(screen)
alien_group.draw(screen)
alien_bullet_group.draw(screen)
explosion_group.draw(screen)
rocket_explosion_group.draw(screen)
alien_red_explosion_group.draw(screen)
# event handlers
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEMOTION:
# space invaders level
spaceship.move(event.pos[0])
pygame.display.flip()
pygame.quit()
