Class player - 动画停止第一帧

Class player - Animation stop first frame

快速提问。我的播放器 Class 运行良好。除了一个小细节。这是 class:

from dict.entity_dict import player, player_class
from collections import OrderedDict
import pyglet, random

key = pyglet.window.key

class Player(pyglet.sprite.Sprite):

    dir_stand = "south"
    dir_run = "south"
    sprite_stand = 3
    sprite_run = 3
    image = None
    s = 0

    def __init__(self, game):
        self.game = game

        self.keyboard = key.KeyStateHandler()

        self.statistics_base = OrderedDict()

        self.image_stand = pyglet.resource.image(player.get("player_stand", {'x': None}).get("resource"))
        self.image_run = pyglet.resource.image(player.get("player_run", {'x': None}).get("resource"))
        self.image_stand_width = player.get("player_stand", {'x': None}).get("width")
        self.image_stand_height = player.get("player_stand", {'x': None}).get("height")
        self.image_run_width = player.get("player_run", {'x': None}).get("width")
        self.image_run_height = player.get("player_run", {'x': None}).get("height")

        self.vx = self.game.wd / 2
        self.vy = self.game.wh / 2

        self.load_sprite()

    def class_player(self, type):
        self.statistics_base["hp"] = player_class.get(type, {'x': None}).get("hp")
        self.statistics_base["atk"] = player_class.get(type, {'x': None}).get("atk")
        self.statistics_base["dif"] = player_class.get(type, {'x': None}).get("dif")
        self.statistics_base["atk_sp"] = player_class.get(type, {'x': None}).get("atk_sp")
        self.statistics_base["dif_sp"] = player_class.get(type, {'x': None}).get("dif_sp")
        self.statistics_base["vel"] = player_class.get(type, {'x': None}).get("vel")
        for stat in self.statistics_base:
            if self.statistics_base[stat] is None:
                self.statistics_base[stat] = 10


    def animation(self, image, da, width, height):
        frame_list = [image.get_region(x=width * i, y=height * da, width=46, height=58) for i in range(22)]
        image_animation = pyglet.image.Animation.from_image_sequence(frame_list, 0.10, True)

        return image_animation

    def direction_sprite(self):
        if self.dir_stand == "north":
            self.sprite_stand = 7
        elif self.dir_stand == "east":
            self.sprite_stand = 5
        elif self.dir_stand == "south":
            self.sprite_stand = 3
        elif self.dir_stand == "west":
            self.sprite_stand = 1
        if self.dir_run == "north":
            self.sprite_run = 7
        elif self.dir_run == "north-east":
            self.sprite_run = 6
        elif self.dir_run == "east":
            self.sprite_run = 5
        elif self.dir_run == "south-east":
            self.sprite_run = 4
        elif self.dir_run == "south":
            self.sprite_run = 3
        elif self.dir_run == "south-west":
            self.sprite_run = 2
        elif self.dir_run == "west":
            self.sprite_run = 1
        elif self.dir_run == "north-west":
            self.sprite_run = 0

    def load_sprite(self):
        if not self.keyboard[key.W] and not self.keyboard[key.S] and not self.keyboard[key.D] and not self.keyboard[key.A]:
            self.keyboard.clear()
            img = self.image_stand
            img_width = self.image_stand_width
            img_height = self.image_stand_height
            da = self.sprite_stand
        else:
            img = self.image_run
            img_width = self.image_run_width
            img_height = self.image_run_height
            da = self.sprite_run

        self.direction_sprite()
        self.image = self.animation(img, da, img_width, img_height)
        self.image.width, self.image.height = img_width, img_height
        self.image.anchor_x, self.image.anchor_y = img_width // 2, img_height // 2

        self.sprite = pyglet.sprite.Sprite(self.image, batch=self.game.Batch, group=self.game.GroupEntitySprite)


        self.sprite.x = self.vx
        self.sprite.y = self.vy

    def key_player(self):
        if self.keyboard[key.W]:
            self.vy += 1
            self.dir_stand = "north"
            self.dir_run = "north"
        if self.keyboard[key.S]:
            self.vy -= 1
            self.dir_stand = "south"
            self.dir_run = "south"
        if self.keyboard[key.D]:
            self.vx += 1
            self.dir_stand = "east"
            self.dir_run = "east"
        if self.keyboard[key.A]:
            self.vx -= 1
            self.dir_stand = "west"
            self.dir_run = "west"
        if self.keyboard[key.W] and self.keyboard[key.D]:
            random1 = random.randint(1, 2)
            if random1 == 1:
                self.dir_stand = "north"
            else:
                self.dir_stand = "east"
            self.dir_run = "north-east"
        if self.keyboard[key.S] and self.keyboard[key.D]:
            random2 = random.randint(1, 2)
            if random2 == 1:
                self.dir_stand = "south"
            else:
                self.dir_stand = "east"
            self.dir_run = "south-east"
        if self.keyboard[key.W] and self.keyboard[key.A]:
            random3 = random.randint(1, 2)
            if random3 == 1:
                self.dir_stand = "north"
            else:
                self.dir_stand = "west"
            self.dir_run = "north-west"
        if self.keyboard[key.S] and self.keyboard[key.A]:
            random4 = random.randint(1, 2)
            if random4 == 1:
                self.dir_stand = "south"
            else:
                self.dir_stand = "west"
            self.dir_run = "south-west"

    def update(self):
        self.key_player()
        self.load_sprite()

由于要更新Player的精灵,我需要调用"load_sprite"函数,导致动画不断被调用。因此,不会出现相同的动画,而是在第一帧保持静止。那我怎么解决呢?

编辑:修改了脚本,包括 for 循环。如果您看到,我修改了组,改为使用 Batch 和 OrderedGroup。这样我们就可以清楚的看到我遇到的问题了。

我遇到的问题是因为调用 pyglet.sprite.Sprite 是为了更新执行的动画。然而,同时这样做,由于pyglet.sprite.Sprite.

的不断调用,动画并没有完全显示出来。

首先,您可以通过设置精灵的 image 属性来更改精灵的动画,而不用创建新的精灵实例。其次,只有在真正需要时才更改它的动画。那就是方向改变的时候。

我添加了一个简单的示例(伪)代码来大致说明我的意思。

def animation(image, da, width, height):
    frame_list = [image.get_region(x=width * i, y=height * da, width=46, height=58) for i in range(22)]
    image_animation = pyglet.image.Animation.from_image_sequence(frame_list, 0.10, True)
    return image_animation


class Player:

    def __init__(self, standing_animations, running_animations):
        # ... code ...
        self.standing_animations = standing_animations   # List of animations 
        self.running_animations  = running_animations    # List of animations
        self.current_animation = standing_animations[0]  # Just to have a default animation
        self.previous_running_direction  = None
        self.previous_standing_direction = None

    def load_sprite(self):
        self.sprite.x = self.vx
        self.sprite.y = self.vy

        if self.previous_running_direction == self.dir_run and self.previous_standing_direction == self.dir_stand:
            return  # Don't do anything more in here

        if not self.keyboard[key.W] and not self.keyboard[key.S] and not self.keyboard[key.D] and not self.keyboard[key.A]:
            self.keyboard.clear()
            self.current_animation = self.standing_animations[self.sprite_stand]
        else:
            self.current_animation = self.running_animations[self.sprite_run]

        self.sprite.image = self.current_animation

    def update(self):
        self.previous_running_direction  = self.dir_run
        self.previous_standing_direction = self.dir_stand
        self.key_player()
        self.load_sprite()