Spriteanimation (Explosion)
Verfasst: Mittwoch 24. November 2021, 21:21
hi, habe mal wieder ein Problem, im ff Code versuche ich nach einer Player-Gegner-Kollision eine Explosion zu animieren.
Wenn ich eine Spritegruppe verwende, so läuft die Animation mit korrekter Geschwindigkeit ab . Mein Ziel war jedoch, ohne Spritegruppe auszukommen.
Dann aber läuft die Animation sehr schnell ab. Vermute da muss irgendwo noch ein delay eingebaut werden ... ?
Vielleicht kann mir irgend eine Mensch aus dem Forum auf die Sprünge helfen , bitte?
Der Code - ohne Explosion -- stammt von metulburr aus dem englischsprachigen Forum.
Wenn ich eine Spritegruppe verwende, so läuft die Animation mit korrekter Geschwindigkeit ab . Mein Ziel war jedoch, ohne Spritegruppe auszukommen.
Dann aber läuft die Animation sehr schnell ab. Vermute da muss irgendwo noch ein delay eingebaut werden ... ?
Vielleicht kann mir irgend eine Mensch aus dem Forum auf die Sprünge helfen , bitte?
Der Code - ohne Explosion -- stammt von metulburr aus dem englischsprachigen Forum.
Code: Alles auswählen
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()
BLACK = (0, 0, 0)
FPS = 60
def enemy_image_load():
image = pygame.image.load('data/enemy.png').convert()
image.set_colorkey((255,0,255))
transformed_image = pygame.transform.rotate(image, 180)
orig_image = pygame.transform.scale(transformed_image, (40,80))
mask = pygame.mask.from_surface(orig_image)
return (orig_image, mask)
class Enemy:
def __init__(self, images, screen_rect):
self.screen_rect = screen_rect
self.image = images[0]
self.mask = images[1]
start_buffer = 0
self.rect = self.image.get_rect(
center=(screen_rect.centerx, screen_rect.centery + start_buffer)
)
self.distance_above_player = 100
self.speed = 2
self.bullet_color = (255,0,0)
self.is_hit = False
self.range_to_fire = False
self.timer = 0.0
self.bullets = [ ]
self.dead = False
def pos_towards_player(self, player_rect):
c = math.sqrt((player_rect.x - self.rect.x) ** 2 + (player_rect.y - self.distance_above_player - self.rect.y) ** 2)
try:
x = (player_rect.x - self.rect.x) / c
y = ((player_rect.y - self.distance_above_player) - self.rect.y) / c
except ZeroDivisionError:
return False
return (x,y)
def update(self, dt, player):
new_pos = self.pos_towards_player(player.rect)
if new_pos: #if not ZeroDivisonError
self.rect.x, self.rect.y = (self.rect.x + new_pos[0] * self.speed, self.rect.y + new_pos[1] * self.speed)
self.check_attack_ability(player)
if self.range_to_fire:
if pygame.time.get_ticks() - self.timer > 1500.0:
self.timer = pygame.time.get_ticks()
self.bullets.append(Laser(self.rect.center, self.bullet_color))
self.update_bullets(player)
def draw(self, surf):
if self.bullets:
for bullet in self.bullets:
surf.blit(bullet.image, bullet.rect)
surf.blit(self.image, self.rect)
def check_attack_ability(self, player):
#if player is lower than enemy
if player.rect.y >= self.rect.y:
try:
offset_x = self.rect.x - player.rect.x
offset_y = self.rect.y - player.rect.y
d = int(math.degrees(math.atan(offset_x / offset_y)))
except ZeroDivisionError: #player is above enemy
return
#if player is within 15 degrees lower of enemy
if math.fabs(d) <= 15:
self.range_to_fire = True
else:
self.range_to_fire = False
def update_bullets(self, player):
if self.bullets:
for obj in self.bullets[:]:
obj.update('down')
#check collision
if obj.rect.colliderect(player.rect):
offset_x = obj.rect.x - player.rect.x
offset_y = obj.rect.y - player.rect.y
if player.mask.overlap(obj.mask, (offset_x, offset_y)):
player.take_damage(1)
self.bullets.remove(obj)
class Laser:
def __init__(self, loc, screen_rect):
self.screen_rect = screen_rect
self.image = pygame.Surface((5,40)).convert_alpha()
#self.image.set_colorkey((255,0,255))
self.mask = pygame.mask.from_surface(self.image)
self.image.fill((255,255,0))
self.rect = self.image.get_rect(center=loc)
self.speed = 5
def update(self,direction='up'):
if direction == 'down':
self.rect.y += self.speed
else:
self.rect.y -= self.speed
def render(self, surf):
surf.blit(self.image, self.rect)
class Player:
def __init__(self, screen_rect):
self.screen_rect = screen_rect
self.image = pygame.image.load('data/spaceship.png').convert()
self.image.set_colorkey((255,0,255))
self.mask = pygame.mask.from_surface(self.image)
self.transformed_image = pygame.transform.rotate(self.image, 180)
self.transformed_image = pygame.transform.scale(self.transformed_image, (63,108))
start_buffer = 300
self.rect = self.image.get_rect(
center=(screen_rect.centerx, screen_rect.centery + start_buffer)
)
self.dx = 300
self.dy = 300
self.lasers = []
self.timer = 0.0
self.laser_delay = 500
self.add_laser = False
self.damage = 10
def take_damage(self, value):
self.damage -= value
def get_event(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if self.add_laser:
self.lasers.append(Laser(self.rect.center, self.screen_rect))
self.add_laser = False
def update(self, keys, dt, enemies):
self.rect.clamp_ip(self.screen_rect)
if keys[pygame.K_LEFT]:
self.rect.x -= self.dx * dt
if keys[pygame.K_RIGHT]:
self.rect.x += self.dx * dt
if keys[pygame.K_UP]:
self.rect.y -= self.dy * dt
if keys[pygame.K_DOWN]:
self.rect.y += self.dy * dt
if pygame.time.get_ticks()-self.timer > self.laser_delay:
self.timer = pygame.time.get_ticks()
self.add_laser = True
self.check_laser_collision(enemies)
def check_laser_collision(self, enemies):
for laser in self.lasers[:]:
laser.update()
for e in enemies:
if laser.rect.colliderect(e.rect):
offset_x = laser.rect.x - e.rect.x
offset_y = laser.rect.y - e.rect.y
if e.mask.overlap(laser.mask, (offset_x, offset_y)):
# alternativ-Code ohne Spritegruppe
#expl = Explosion(e.rect.centerx, e.rect.centery)
#expl.update()
#expl.draw()
explosion = Explosion(e.rect.centerx, e.rect.centery)
explosion_group.add(explosion)
e.dead = True
self.lasers.remove(laser)
def draw(self, surf):
for laser in self.lasers:
laser.render(surf)
surf.blit(self.transformed_image, self.rect)
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.images = []
for num in range(1, 6):
img = pygame.image.load(f"img/exp{num}.png")
img = pygame.transform.scale(img, (120, 120))
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 = 4
#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 self.index >= len(self.images) - 1 and self.counter >= explosion_speed:
self.kill()
def draw(self):
screen.blit(self.image, self.rect)
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()
player = Player(screen_rect)
ENEMY_IMAGE = enemy_image_load()
enemies = []
enemies.append(Enemy(ENEMY_IMAGE, screen_rect))
explosion_group = pygame.sprite.Group()
clock = pygame.time.Clock()
done = False
while not done:
#clock.tick(FPS)
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
player.get_event(event)
screen.fill((0,0,0))
explosion_group.draw(screen)
explosion_group.update()
delta_time = clock.tick(60)/1000.0
player.update(keys, delta_time, enemies)
for e in enemies[:]:
e.update(delta_time, player)
if e.dead:
enemies.remove(e) # remove: Listenmethode
e.draw(screen)
player.draw(screen)
pygame.display.update()