2014-10-30 2 views
0

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

SCREEN_SIZE = (1024, 768) 
import sys 
import pygame 
from pygame.locals import * 

from random import randint, choice 
from Vector2 import Vector2 

NEST_POSITION = (SCREEN_SIZE[0]/2, SCREEN_SIZE[1]/2) 
NEST_POSITION_VECTOR2 = Vector2(NEST_POSITION) 
ANT_COUNT = 20 
NEST_SIZE = 100. 

class State(object): 
    def __init__(self, name): 
    self.name = name 

    def do_actions(self): 
    pass 

    def check_conditions(self): 
    pass 

    def entry_actions(self): 
    pass 

    def exit_actions(self): 
    pass 


class StateMachine(object): 
    def __init__(self): 
    self.states = {} 
    self.active_state = None 


    def add_state(self, state): 
    self.states[state.name] = state 


    def think(self): 
    if self.active_state is None: return 

    self.active_state.do_actions() 
    new_state_name = self.active_state.check_conditions() 
    if new_state_name is not None: 
     self.set_state(new_state_name) 


    def set_state(self, new_state_name): 
    if self.active_state is not None: 
     self.active_state.exit_actions() 

    self.active_state = self.states[new_state_name] 
    self.active_state.entry_actions() 



class World(object): 
    def __init__(self): 

    self.entities = {} 
    self.entity_id = 0 
    self.background = pygame.surface.Surface(SCREEN_SIZE).convert() 
    self.background.fill((255, 255, 255)) 
    pygame.draw.circle(self.background, (200, 255, 200), NEST_POSITION, int(NEST_SIZE)) 

    def add_entity(self, entity): 
    self.entities[self.entity_id] = entity 
    entity.id = self.entity_id 
    self.entity_id += 1 

    def remove_entity(self, entity): 
    del self.entities[entity.id] 

    def get(self, entity_id): 
    if entity_id in self.entities: 
     return self.entities[entity_id] 
    else: 
     return None 

    def process(self, time_passed): 
    time_passed_seconds = time_passed/1000.0 
    for entity in self.entities.values(): 
     entity.process(time_passed_seconds) 

    def render(self, surface): 
    surface.blit(self.background, (0, 0)) 
    for entity in self.entities.itervalues(): 
     entity.render(surface) 


    def get_close_entity(self, name, location, range=100.): 
    for entity in self.entities.itervalues(): 
     if (entity.name == name): 
     distance = location.get_distance_to(entity.location) 
     if (distance < range): 
      return entity 
    return None 

############################# GameEntity #################################### 
## This is a "template" object - that is, we never actually create one of 
## these objects in the game. 
## This object is used as a base templet for other game objects that "extend" 
## or "inherit from" this object. 
## The leaf, Spider and And objects all extend the GameEntity object 
class GameEntity(object): 
    def __init__(self, world, name, image): 

    self.world = world 
    self.name = name 
    self.image = image 
    self.location = Vector2(0, 0) 
    self.destination = Vector2(0, 0) 
    self.speed = 0. 

    self.brain = StateMachine() 

    self.id = 0 

    def render(self, surface): 
    w, h = self.image.get_size() 
    surface.blit(self.image, (self.location.x-w/2, self.location.y-h/2)) 

    def process(self, time_passed): 
    self.brain.think() 

    if ((self.speed > 0.) and (self.location != self.destination)): 

     vec_to_destination = self.destination - self.location 
     distance_to_destination = vec_to_destination.get_magnitude() 
     heading = vec_to_destination.get_normalized() 
     travel_distance = min(distance_to_destination, time_passed * self.speed) 
     self.location += heading * travel_distance 


############################# Leaf ########################################## 
class Leaf(GameEntity): 
    def __init__(self, world, image): 
    GameEntity.__init__(self, world, "leaf", image) 



############################# Ant ########################################## 
class Spider(GameEntity): 
    def __init__(self, world, image): 
    GameEntity.__init__(self, world, "spider", image) 
    self.dead_image = pygame.transform.flip(image, 0, 1) 
    self.health = 25 
    self.speed = 50. + randint(-20, 20) 

    def bitten(self): 
    self.health -= 1 
    if (self.health <= 0): 
     self.speed = 0. 
     self.image = self.dead_image 
    self.speed = 140. 

    def render(self, surface): 
    GameEntity.render(self, surface) 

    w, h = self.image.get_size() 
    bar_x = self.location.x - 12 
    bar_y = self.location.y + h/2 
    surface.fill((255, 0, 0), (bar_x, bar_y, 25, 4)) 
    surface.fill((0, 255, 0), (bar_x, bar_y, self.health, 4)) 

    def process(self, time_passed): 
    if (self.location.x > SCREEN_SIZE[0] + 2): 
     self.world.remove_entity(self) 
     return 

    GameEntity.process(self, time_passed) 



############################# Ant ########################################## 
class Ant(GameEntity): 

    def __init__(self, world, image): 
    GameEntity.__init__(self, world, "ant", image) 

    exploring_state = AntStateExploring(self) 
    seeking_state = AntStateSeeking(self) 
    delivering_state = AntStateDelivering(self) 
    hunting_state = AntStateHunting(self) 

    self.brain.add_state(exploring_state) 
    self.brain.add_state(seeking_state) 
    self.brain.add_state(delivering_state) 
    self.brain.add_state(hunting_state) 

    self.carry_image = None 

    def carry(self, image): 
    self.carry_image = image 

    def drop(self, surface): 
    if self.carry_image: 
     x = self.location.x 
     y = self.location.y 
     w, h = self.carry_image.get_size() 
     surface.blit(self.carry_image, (x-w, y-h/2)) 
     self.carry_image = None 

    def render(self, surface): 
    GameEntity.render(self, surface) 
    if (self.carry_image): 
     x = self.location.x 
     y = self.location.y 
     w, h = self.carry_image.get_size() 
     surface.blit(self.carry_image, (x-w, y-h/2)) 

############################# AntStateExploring ############################# 
class AntStateExploring(State): 

    def __init__(self, ant): 
    State.__init__(self, "exploring") 
    self.ant = ant 

    def random_destination(self): 
    w, h = SCREEN_SIZE 
    self.ant.destination = Vector2(randint(0, w), randint(0, h)) 

    def do_actions(self): 
    if (randint(1, 20) == 1): 
     self.random_destination() 

    def check_conditions(self): 
    leaf = self.ant.world.get_close_entity("leaf", self.ant.location) 
    if (leaf is not None): 
     self.ant.leaf_id = leaf.id 
     return "seeking" 

    spider = self.ant.world.get_close_entity("spider", NEST_POSITION_VECTOR2, NEST_SIZE) 
    if (spider is not None): 
     if (self.ant.location.get_distance_to(spider.location) < 100.): 
     self.ant.spider_id = spider.id 
     return "hunting" 
    return None 

    def entry_actions(self): 
    self.ant.speed = 120. + randint(-30, 30) 
    self.random_destination() 

############################# AntStateSeeking ############################### 
class AntStateSeeking(State): 

    def __init__(self, ant): 
    State.__init__(self, "seeking") 
    self.ant = ant 
    self.leaf_id = None 

    def check_conditions(self): 
    leaf = self.ant.world.get(self.ant.leaf_id) 
    if (leaf is None): return "exploring" 

    if (self.ant.location.get_distance_to(leaf.location) < 5.0): 
     self.ant.carry(leaf.image) 
     self.ant.world.remove_entity(leaf) 
     return "delivering" 

    return None 

    def entry_actions(self): 
    leaf = self.ant.world.get(self.ant.leaf_id) 
    if (leaf is not None): 
     self.ant.destination = leaf.location 
     self.ant.speed = 160. + randint(-20, 20) 

############################# AntStateDelivering ############################ 
class AntStateDelivering(State): 

    def __init__(self, ant): 
    State.__init__(self, "delivering") 
    self.ant = ant 


    def check_conditions(self): 
    if (self.ant.location.get_distance_to(NEST_POSITION) < NEST_SIZE): 
     if (randint(1, 10) == 1): 
     self.ant.drop(self.ant.world.background) 
     return "exploring" 

    return None 


    def entry_actions(self): 
    self.ant.speed = 60. 
    random_offset = Vector2(randint(-20, 20), randint(-20, 20)) 
    self.ant.destination = random_offset + NEST_POSITION 



############################# AntStateHunting ############################### 
class AntStateHunting(State): 

    def __init__(self, ant): 
    State.__init__(self, "hunting") 
    self.ant = ant 
    self.got_kill = False 

    def do_actions(self): 
    spider = self.ant.world.get(self.ant.spider_id) 

    if (spider is None): return 

    self.ant.destination = spider.location 

    if (self.ant.location.get_distance_to(spider.location) < 15.): 

     if (randint(1, 5) == 1): 
     spider.bitten() 

     if (spider.health <= 0): 
     self.ant.carry(spider.image) 
     self.ant.world.remove_entity(spider) 
     self.got_kill = True 


    def check_conditions(self): 
    if (self.got_kill): return "delivering" 

    spider = self.ant.world.get(self.ant.spider_id) 

    if (spider is None): return "exploring" 

    if (spider.location.get_distance_to(NEST_POSITION) > NEST_SIZE * 3): 
     return "exploring" 

    return None 

    def entry_actions(self): 
    self.speed = 160. + randint(0, 50) 

    def exit_actions(self): 
    self.got_kill = False 





############################# Set up Game ############################### 
def run(): 
    pygame.init() 
    screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32) 
    pygame.display.set_caption("The Super Amazing Ant Simulation") 

    world = World() 

    w, h = SCREEN_SIZE 

    clock = pygame.time.Clock() 

    ant_image = pygame.image.load("ant.png").convert_alpha() 
    ant2_image = pygame.image.load("ant6.gif").convert_alpha() 
    ant3_image = pygame.image.load("ant7.gif").convert_alpha() 
    leaf_image = pygame.image.load("leaf.png").convert_alpha() 
    spider_image = pygame.image.load("spider.png").convert_alpha() 

    ############# Place ants in starting locations ######################### 
    for ant_no in xrange(ANT_COUNT): 
    ant = Ant(world, ant_image) 
    ant.location = Vector2(randint(0, w), randint(0, h)) 
    ant.brain.set_state("exploring") 
    world.add_entity(ant) 

    ############################# Game Loop ############################### 

    while (True): 
    for event in pygame.event.get(): 
     if (event.type == QUIT): 
     pygame.quit() 
     return 

    time_passed = clock.tick(30) 

    if (randint(1, 50) == 1): 
     leafX = randint(0, w) 
     leafY = randint(0, h) 
     numberOfLeafs = randint(5,25) 
     for leafNumber in range(numberOfLeafs): 
     leaf = Leaf(world, leaf_image) 
     leaf.location = Vector2(leafX, leafY) 
     world.add_entity(leaf) 


    if (randint(1, 100) == 1): 
     spider = Spider(world, spider_image) 
     spider.location = Vector2(-50, randint(0, h)) 
     spider.destination = Vector2(w+50, randint(0, h)) 
     world.add_entity(spider) 

    world.process(time_passed) 
    world.render(screen) 

    pygame.display.update() 


############################# Call run to start game ######################### 
try: 
    if (Vector2.version() != "Version 2014-04-09"): 
    raise() 
except: 
    print "****ERROR**** Vector2 version mis-matched with AntSimulation.py" 
    sys.exit() 

run() 
+2

Вам придется урезать эту книгу статьи размера кусок кода, оставьте только в соответствующих битах, и объяснить, почему вы думаете, что это не делает то, что он должен делать –

+0

@Puciek Я предполагаю, что главная проблема, с которой он столкнулся, заключается в том, что это отображение g статическое изображение для каждого объекта, а не для анимированного. – Wlerin

ответ

1

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

Вот простой пример класса анимации (вы, вероятно, захотите добавить немного функциональности к этому):

class Animation(object): 
    def __init__(self, image_list): 
     self.image_list = image_list #a list of pygame images 
     self.total_frames = len(image_list) 
     self.index = 0 
    def next(self): 
     image = self.image_list[self.index] 
     self.index = (self.index+1) % self.total_frames #loops back around 
     return image 

Теперь в вашем классе спрайтов, когда вы готовы к переходу на следующий кадр анимации:

self.image = my_animation.next() 
Смежные вопросы