2017-02-03 20 views
2

Я хотел бы создать сверху вниз RPG в pygame, используя спрайт-листы.pygame animation sprite sheet

Я хочу, чтобы иметь возможность нажать пробел, например, для атаки, которая вызовет атакующую анимацию, а затем вернуться к нормальной

import pygame 
from pygame.locals import * 

pygame.init() 

image = pygame.image.load("sprite_sheet.png") 

clock = pygame.time.Clock() 

screen = pygame.display.set_mode((400, 250)) 

class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     super().__init__() 

     self.current_animation = 0 
     self.max_animation = 5 

     self.animation_cooldown = 150 
     self.last_animation = pygame.time.get_ticks() 

     self.status = {"prev": "standing", 
         "now": "standing"} 

    def animate_attack(self): 
     time_now = pygame.time.get_ticks() 

     if time_now - self.last_animation >= self.animation_cooldown: 
      self.last_animation = pygame.time.get_ticks() 
      if self.current_animation == self.max_animation: 
       self.current_animation = 0 

       joshua.status["now"] = joshua.status["prev"] 
      else: 
       self.current_animation += 1 


joshua = Player() 

while True: 
    screen.fill(0) 
    for event in pygame.event.get(): 
     if event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_SPACE: 
       joshua.status["prev"] = joshua.status["now"] 
       joshua.status["now"] = "attacking" 

    if joshua.status["now"] == "attacking": 
     joshua.animate_attack() 

    screen.blit(image, (0, 0), (joshua.current_animation * 64, 0, 64, 64)) 

    pygame.display.flip() 

    clock.tick(60) 

выше кусок кода является то, что я есть. Если я нажимаю пробел, как только он пройдет анимацию и остановится, но если я дважды коснусь его, он будет зацикливать его из-за того, как он запрограммирован.

Хотела некоторую помощь в анимации, спасибо

ответ

0

Проблема вызвана следующим вызовом, когда пространство нажимается во второй раз:

joshua.status["prev"] = joshua.status["now"] 

Это устанавливает как «предыдущий» и «сейчас «заявляет, что« атакует ». В результате, когда состояние сбрасывается в animate_attack() методе он будет оставаться «атаковать»:

joshua.status["now"] = joshua.status["prev"] 

Как быстро исправить, убедитесь, что только изменить состояние, если он еще не установлен :

if event.key == pygame.K_SPACE: 
    if not joshua.status["now"] == "attacking": 
     joshua.status["prev"] = joshua.status["now"] 
     joshua.status["now"] = "attacking" 

Как лучше исправить, вы должны инкапсулировать состояние, так, что только класс игрока когда-либо имеет дело со своим состоянием, например:

class Player(): 
    def __init__(self): 
     self.current_animation = 0 
     self.max_animation = 5 
     self.animation_cooldown = 150 
     self.last_animation = pygame.time.get_ticks() 
     self.status = "standing" # Simplified state 

    def attack(self): 
     self.status = "attacking" 

    def animate_attack(self): 
     if self.status == "attacking": 
      time_now = pygame.time.get_ticks() 
      if time_now - self.last_animation >= self.animation_cooldown: 
       self.last_animation = pygame.time.get_ticks() 
       if self.current_animation == self.max_animation: 
        self.current_animation = 0 
        self.status = "standing" # Reset state 
       else: 
        self.current_animation += 1 

Таким образом, нет необходимости знать что-либо о состоянии за пределами класса:

while True: 
    for event in pygame.event.get(): 
     if event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_SPACE: 
       joshua.attack() 

    joshua.animate_attack() 

    screen.fill(0) 
    screen.blit(image, (0, 0), (joshua.current_animation * 64, 0, 64, 64)) 
    pygame.display.flip() 
    clock.tick(60) 
+0

большое спасибо. Скажем, у меня были элементы управления для WASD, и я попытался перемещаться, установив статус влево для перемещения влево. если я нахожусь в центре атаки и нажимаю W, он перезаписывает атаку и останавливает анимацию. Есть ли способ сделать завершение анимации до запуска другого события? –

+0

Вы можете использовать отдельные переменные состояния: , например 'self.movement' (« стоя »,« левый », ...) и' self.attacking' (True, False). Таким образом, вы можете обновить состояние перемещения независимо от состояния атаки. Для анимации, если 'self.attacking' является True , тогда вычислите текущий атакующий кадр, иначе используйте соответствующий кадр для текущего движения . – Meyer