代码之家  ›  专栏  ›  技术社区  ›  ScalaBoy

如何在动画期间更改精灵的图像?

  •  1
  • ScalaBoy  · 技术社区  · 6 年前

    我想更改对象的图像 worker 每次停下来。

    班级 Worker 是根据 @sloth 在里面 this thread .

    class Worker(pygame.sprite.Sprite):
        def __init__(self, image_file, location, *groups):
            # we set a _layer attribute before adding this sprite to the sprite groups
            # we want the workers on top
            self._layer = 1
            pygame.sprite.Sprite.__init__(self, groups)
            self.image = pygame.transform.scale(pygame.image.load(image_file).convert_alpha(), (40, 40))
            self.rect = self.image.get_rect(topleft=location)
            # let's call this handy function to set a random direction for the worker
            self.change_direction()
            # speed is also random
            self.speed = random.randint(1, 3)
    
        def change_direction(self):
            # let's create a random vector as direction, so we can move in every direction
            self.direction = pygame.math.Vector2(random.randint(-1,1), random.randint(-1,1))
    
            # we don't want a vector of length 0, because we want to actually move
            # it's not enough to account for rounding errors, but let's ignore that for now
            while self.direction.length() == 0:
                self.direction = pygame.math.Vector2(random.randint(-1,1), random.randint(-1,1)) 
    
            # always normalize the vector, so we always move at a constant speed at all directions
            self.direction = self.direction.normalize()
    
        def update(self, screen):
            # there is a less than 1% chance every time that direction is changed
            if random.uniform(0,1)<0.005:
                self.change_direction()
    
            # now let's multiply our direction with our speed and move the rect
            vec = [int(v) for v in self.direction * self.speed]
            self.rect.move_ip(*vec)
    
            # if we're going outside the screen, move back and change direction
            if not screen.get_rect().contains(self.rect):
                self.change_direction()
            self.rect.clamp_ip(screen.get_rect())
    

    我试图创建预加载图像的缓存

    image_cache = {}
    def get_image(key):
        if not key in image_cache:
            image_cache[key] = pygame.image.load(key)
        return image_cache[key]
    

    然后我假设有必要将以下代码添加到 def __init__ :

    images = ["worker.png", "worker_stopped.png"]
    for i in range(0,len(images)):
       self.images[i] = get_image(images[i])
    

    以及以下代码 def update(self) :

    if self.direction.length() == 0:
        self.image = self.images[1]
    else:
        self.image = self.images[0]
    

    然而,它似乎不能正常工作。旧形象 worker.png 不会消失并且整个动画被锁定。

    1 回复  |  直到 6 年前
        1
  •  1
  •   sloth JohnnBlade    6 年前

    我认为您应该引入某种状态来表示工人是否正在运行。这里有一个例子。注意评论:

    class Worker(pygame.sprite.Sprite):
    
        # we introduce to possible states: RUNNING and IDLE
        RUNNING = 0
        IDLE = 1
    
        def __init__(self, location, *groups):
    
            # each state has it's own image
            self.images = {
                Worker.RUNNING: pygame.transform.scale(get_image("worker.png"), (40, 40)),
                Worker.IDLE: pygame.transform.scale(get_image("worker_stopped.png"), (40, 40))
            }
    
            self._layer = 1
            pygame.sprite.Sprite.__init__(self, groups)
    
            # let's keep track of the state and how long we are in this state already            
            self.state = Worker.IDLE
            self.ticks_in_state = 0
    
            self.image = self.images[self.state]
            self.rect = self.image.get_rect(topleft=location)
    
            self.direction = pygame.math.Vector2(0, 0)
            self.speed = random.randint(2, 4)
            self.set_random_direction()
    
        def set_random_direction(self):
            # random new direction or standing still
            vec = pygame.math.Vector2(random.randint(-100,100), random.randint(-100,100)) if random.randint(0, 5) > 1 else pygame.math.Vector2(0, 0)
    
            # check the new vector and decide if we are running or fooling around
            length = vec.length()
            speed = sum(abs(int(v)) for v in vec.normalize() * self.speed) if length > 0 else 0
    
            if length == 0 or speed == 0:
                new_state = Worker.IDLE
                self.direction = pygame.math.Vector2(0, 0)
            else:
                new_state = Worker.RUNNING
                self.direction = vec.normalize()
    
            self.ticks_in_state = 0
            self.state = new_state
    
            # use the right image for the current state
            self.image = self.images[self.state]
    
        def update(self, screen):
            self.ticks_in_state += 1
            # the longer we are in a certain state, the more likely is we change direction
            if random.randint(0, self.ticks_in_state) > 30:
                self.set_random_direction()
    
            # now let's multiply our direction with our speed and move the rect
            vec = [int(v) for v in self.direction * self.speed]
            self.rect.move_ip(*vec)
    
            # if we're going outside the screen, change direction
            if not screen.get_rect().contains(self.rect):
                self.direction = self.direction * -1
    
            self.rect.clamp_ip(screen.get_rect())