def load(self): from core import prepare self.dpad["surface"] = tools.load_and_scale("gfx/d-pad.png") self.dpad["position"] = (0, prepare.SCREEN_SIZE[1] - self.dpad["surface"].get_height()) # Create the collision rectangle objects for the dpad so we can see if we're pressing a button self.dpad["rect"] = {} self.dpad["rect"]["up"] = pygame.Rect( self.dpad["position"][0] + (self.dpad["surface"].get_width() / 3), self.dpad["position"][1], # Rectangle position_y self.dpad["surface"].get_width() / 3, # Rectangle size_x self.dpad["surface"].get_height() / 2) # Rectangle size_y self.dpad["rect"]["down"] = pygame.Rect( self.dpad["position"][0] + (self.dpad["surface"].get_width() / 3), self.dpad["position"][1] + (self.dpad["surface"].get_height() / 2), self.dpad["surface"].get_width() / 3, self.dpad["surface"].get_height() / 2) self.dpad["rect"]["left"] = pygame.Rect( self.dpad["position"][0], self.dpad["position"][1] + (self.dpad["surface"].get_height() / 3), self.dpad["surface"].get_width() / 2, self.dpad["surface"].get_height() / 3) self.dpad["rect"]["right"] = pygame.Rect( self.dpad["position"][0] + (self.dpad["surface"].get_width() / 2), self.dpad["position"][1] + (self.dpad["surface"].get_height() / 3), self.dpad["surface"].get_width() / 2, self.dpad["surface"].get_height() / 3) # Create the buttons self.a_button = {} self.a_button["surface"] = tools.load_and_scale("gfx/a-button.png") self.a_button["position"] = ( prepare.SCREEN_SIZE[0] - int(self.a_button["surface"].get_width() * 1.0), (self.dpad["position"][1] + (self.dpad["surface"].get_height() / 2) - (self.a_button["surface"].get_height() / 2))) self.a_button["rect"] = pygame.Rect( self.a_button["position"][0], self.a_button["position"][1], self.a_button["surface"].get_width(), self.a_button["surface"].get_height()) self.b_button = {} self.b_button["surface"] = tools.load_and_scale("gfx/b-button.png") self.b_button["position"] = ( prepare.SCREEN_SIZE[0] - int(self.b_button["surface"].get_width() * 2.1), (self.dpad["position"][1] + (self.dpad["surface"].get_height() / 2) - (self.b_button["surface"].get_height() / 2))) self.b_button["rect"] = pygame.Rect( self.b_button["position"][0], self.b_button["position"][1], self.b_button["surface"].get_width(), self.b_button["surface"].get_height())
def __init__(self, images, position, animation_speed=0.2, animation_loop=False): # Check to see what kind of image(s) are being loaded. images_type = type(images).__name__ # Handle loading a single image, multiple images, or surfaces if images_type == 'str' or images_type == 'unicode': surface = tools.load_and_scale(images) self.images = [(surface, animation_speed)] elif images_type == 'list' or images_type == 'tuple': self.images = [] for item in images: item_type = type(item).__name__ if item_type == 'str' or item_type == 'unicode': surface = tools.load_and_scale(images) else: surface = item self.images.append((surface, animation_speed)) else: surface = images self.images = [(surface, animation_speed)] # Create a pyganimation object using our loaded images. self.animation = pyganim.PygAnimation(self.images, loop=animation_loop) self.animation.play() self.animation.pause() self.rect = self.images[0][0].get_rect(topleft=position) self.visible = True self.state = "" self.moving = False self.move_destination = (0, 0) self.move_delta = [0, 0] self.move_duration = 0. self.move_time = 0. self.fading = False self.fade_duration = 0. self.shaking = False
def draw_monster_info(self, surface, monster, rect): # position and draw hp bar hp_rect = rect.copy() left = rect.width * .6 right = rect.right - tools.scale(4) hp_rect.width = right - left hp_rect.left = left hp_rect.height = tools.scale(8) hp_rect.centery = rect.centery # draw the hp bar self.hp_bar.value = monster.current_hp / monster.hp self.hp_bar.draw(surface, hp_rect) # draw the name text_rect = rect.inflate(-tools.scale(6), -tools.scale(6)) draw_text(surface, monster.name, text_rect, font=self.font) # draw the level info text_rect.top = rect.bottom - tools.scale(7) draw_text(surface, " Lv " + str(monster.level), text_rect, font=self.font) # draw any status icons # TODO: caching or something, idk # TODO: not hardcode icon sizes for index, status in enumerate(monster.status): if status.icon: image = tools.load_and_scale(status.icon) pos = (rect.width * .4) + (index * tools.scale(32)), rect.y + tools.scale(5) surface.blit(image, pos)
def startup(self, **kwargs): super(MonsterMenuState, self).startup(**kwargs) # make a text area to show messages self.text_area = TextArea(self.font, self.font_color, (96, 96, 96)) self.text_area.rect = pygame.Rect( tools.scale_sequence([20, 80, 80, 100])) self.sprites.add(self.text_area, layer=100) # Set up the border images used for the monster slots self.monster_slot_border = {} self.monster_portrait = pygame.sprite.Sprite() self.hp_bar = HpBar() # load and scale the monster slot borders root = "gfx/ui/monster/" border_types = ["empty", "filled", "active"] for border_type in border_types: filename = root + border_type + "_monster_slot_border.png" border = tools.load_and_scale(filename) filename = root + border_type + "_monster_slot_bg.png" background = tools.load_image(filename) window = GraphicBox(border, background, None) self.monster_slot_border[border_type] = window # TODO: something better than this global, load_sprites stuff for monster in self.game.player1.monsters: monster.load_sprites()
def startup(self, **kwargs): super(MonsterMenuState, self).startup(**kwargs) # make a text area to show messages self.text_area = TextArea(self.font, self.font_color, (96, 96, 96)) self.text_area.rect = pygame.Rect(tools.scale_sequence([20, 80, 80, 100])) self.sprites.add(self.text_area, layer=100) # Set up the border images used for the monster slots self.monster_slot_border = {} self.monster_portrait = pygame.sprite.Sprite() self.hp_bar = HpBar() # load and scale the monster slot borders root = "gfx/ui/monster/" border_types = ["empty", "filled", "active"] for border_type in border_types: filename = root + border_type + "_monster_slot_border.png" border = tools.load_and_scale(filename) filename = root + border_type + "_monster_slot_bg.png" background = tools.load_image(filename) window = GraphicBox(border, background, None) self.monster_slot_border[border_type] = window # TODO: something better than this global, load_sprites stuff for monster in self.game.player1.monsters: monster.load_sprites()
def animate_capture_monster(self, is_captured, num_shakes, monster): """ Animation for capturing monsters. :param is_captured: boolean representing success of capture :param num_shakes: number of shakes before animation ends :param monster: the monster :return: """ monster_sprite = self._monster_sprite_map.get(monster, None) capdev = self.load_sprite('gfx/items/capture_device.png') animate = partial(self.animate, capdev.rect, transition='in_quad', duration=1.0) scale_sprite(capdev, .4) capdev.rect.center = scale(0), scale(0) animate(x=monster_sprite.rect.centerx) animate(y=monster_sprite.rect.centery) self.task(partial(toggle_visible, monster_sprite), 1.0) # make the monster go away temporarily def kill(): self._monster_sprite_map[monster].kill() self.hud[monster].kill() del self._monster_sprite_map[monster] del self.hud[monster] # TODO: cache this sprite from the first time it's used. # also, should loading animated sprites be more convenient? images = list() for fn in ["capture%02d.png" % i for i in range(1, 10)]: fn = 'animations/technique/' + fn image = tools.load_and_scale(fn) images.append((image, .07)) tech = PygAnimation(images, False) sprite = Sprite() sprite.image = tech sprite.rect = tech.get_rect() self.task(tech.play, 1.0) self.task(partial(self.sprites.add, sprite), 1.0) sprite.rect.midbottom = monster_sprite.rect.midbottom def shake_ball(initial_delay): animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay) animate(capdev.rect, y=scale(3), relative=True) animate = partial(self.animate, duration=0.2, transition='linear', delay=initial_delay + 0.1) animate(capdev.rect, y=-scale(6), relative=True) animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay + 0.3) animate(capdev.rect, y=scale(3), relative=True) for i in range(0, num_shakes): shake_ball(1.8 + i * 1.0) # leave a 0.6s wait between each shake if is_captured: self.task(kill, 2 + num_shakes) else: self.task(partial(toggle_visible, monster_sprite), 1.8 + num_shakes * 1.0) # make the monster appear again! self.task(tech.play, 1.8 + num_shakes * 1.0) self.task(capdev.kill, 1.8 + num_shakes * 1.0)
def animate_monster_release_bottom(self, feet, monster): """ :type feet: sequence :type monster: core.components.monster.Monster :return: """ capdev = self.load_sprite('gfx/items/capture_device.png') scale_sprite(capdev, .4) capdev.rect.center = feet[0], feet[1] - scale(60) # animate the capdev falling fall_time = .7 animate = partial(self.animate, duration=fall_time, transition='out_quad') animate(capdev.rect, bottom=feet[1], transition='in_back') animate(capdev, rotation=720, initial=0) # animate the capdev fading away delay = fall_time + .6 fade_duration = .9 h = capdev.rect.height animate = partial(self.animate, duration=fade_duration, delay=delay) animate(capdev, width=1, height=h * 1.5) animate(capdev.rect, y=-scale(14), relative=True) # convert the capdev sprite so we can fade it easily def func(): capdev.image = tools.convert_alpha_to_colorkey(capdev.image) self.animate(capdev.image, set_alpha=0, initial=255, duration=fade_duration) self.task(func, delay) self.task(capdev.kill, fall_time + delay + fade_duration) # load monster and set in final position monster_sprite = self.load_sprite(monster.back_battle_sprite, midbottom=feet) self._monster_sprite_map[monster] = monster_sprite # position monster_sprite off screen and set animation to move it back to final spot monster_sprite.rect.top = self.game.screen.get_height() self.animate(monster_sprite.rect, bottom=feet[1], transition='out_back', duration=.9, delay=fall_time + .5) # capdev opening animation images = list() for fn in ["capture%02d.png" % i for i in range(1, 10)]: fn = 'animations/technique/' + fn image = tools.load_and_scale(fn) images.append((image, .07)) delay = 1.3 tech = PygAnimation(images, False) sprite = Sprite() sprite.image = tech sprite.rect = tech.get_rect() sprite.rect.midbottom = feet self.task(tech.play, delay) self.task(partial(self.sprites.add, sprite), delay)
def load(self): from core import prepare self.dpad["surface"] = tools.load_and_scale("gfx/d-pad.png") self.dpad["position"] = (0, prepare.SCREEN_SIZE[1] - self.dpad["surface"].get_height() ) # Create the collision rectangle objects for the dpad so we can see if we're pressing a button self.dpad["rect"] = {} self.dpad["rect"]["up"] = pygame.Rect(self.dpad["position"][0] + (self.dpad["surface"].get_width() /3), self.dpad["position"][1], # Rectangle position_y self.dpad["surface"].get_width() /3, # Rectangle size_x self.dpad["surface"].get_height() /2) # Rectangle size_y self.dpad["rect"]["down"] = pygame.Rect(self.dpad["position"][0] + (self.dpad["surface"].get_width() /3), self.dpad["position"][1] + (self.dpad["surface"].get_height() /2), self.dpad["surface"].get_width() /3, self.dpad["surface"].get_height() /2) self.dpad["rect"]["left"] = pygame.Rect(self.dpad["position"][0], self.dpad["position"][1] + (self.dpad["surface"].get_height() /3), self.dpad["surface"].get_width() /2, self.dpad["surface"].get_height() /3) self.dpad["rect"]["right"] = pygame.Rect(self.dpad["position"][0] + (self.dpad["surface"].get_width() /2), self.dpad["position"][1] + (self.dpad["surface"].get_height() /3), self.dpad["surface"].get_width() /2, self.dpad["surface"].get_height() /3) # Create the buttons self.a_button = {} self.a_button["surface"] = tools.load_and_scale("gfx/a-button.png") self.a_button["position"] = (prepare.SCREEN_SIZE[0] - int( self.a_button["surface"].get_width() * 1.0 ), (self.dpad["position"][1] + (self.dpad["surface"].get_height() / 2) - (self.a_button["surface"].get_height() / 2))) self.a_button["rect"] = pygame.Rect( self.a_button["position"][0], self.a_button["position"][1], self.a_button["surface"].get_width(), self.a_button["surface"].get_height()) self.b_button = {} self.b_button["surface"] = tools.load_and_scale("gfx/b-button.png") self.b_button["position"] = (prepare.SCREEN_SIZE[0] - int( self.b_button["surface"].get_width() * 2.1 ), (self.dpad["position"][1] + (self.dpad["surface"].get_height() / 2) - (self.b_button["surface"].get_height() / 2))) self.b_button["rect"] = pygame.Rect( self.b_button["position"][0], self.b_button["position"][1], self.b_button["surface"].get_width(), self.b_button["surface"].get_height())
def startup(self, *args, **kwargs): super(CombatTargetMenuState, self).startup(*args, **kwargs) # used to determine how player can target techniques self.user = kwargs.get("user") self.action = kwargs.get("action") self.player = kwargs.get("player") # load and scale the menu borders border = tools.load_and_scale(self.borders_filename) self.border = GraphicBox(border, None, None)
def load_graphics(self): """ Loads all the graphical elements of the menu Will load some elements from disk, so needs to be called at least once. """ # load and scale the _background background = None if self.background_filename: background = tools.load_image(self.background_filename) # load and scale the menu borders border = None if self.draw_borders: border = tools.load_and_scale(self.borders_filename) # set the helper to draw the _background self.window = GraphicBox(border, background, self.background_color) # handle the arrow cursor image = tools.load_and_scale(self.cursor_filename) self.arrow = MenuCursor(image)
def load_sprites(self): """Loads the monster's sprite images as Pygame surfaces. :rtype: Boolean :returns: True if the sprites are already loaded. **Examples:** >>> bulbatux.load_sprites() >>> bulbatux.sprites """ if len(self.sprites): return True self.sprites["front"] = tools.load_and_scale(self.front_battle_sprite) self.sprites["back"] = tools.load_and_scale(self.back_battle_sprite) self.sprites["menu"] = tools.load_and_scale(self.menu_sprite) return False
def load_sprites(self): """Loads the monster's sprite images as Pygame surfaces. :param scale: Amount to scale the sprite when loading the image. :type scale: Integer :rtype: Boolean :returns: True if the sprites are already loaded. **Examples:** >>> bulbatux.load_sprites() >>> bulbatux.sprites """ if len(self.sprites): return True self.sprites["front"] = tools.load_and_scale(self.front_battle_sprite) self.sprites["back"] = tools.load_and_scale(self.back_battle_sprite) self.sprites["menu"] = tools.load_and_scale(self.menu_sprite) return False
def show_combat_dialog(self): """ Create and show the area where battle messages are displayed """ # make the border and area at the bottom of the screen for messages x, y, w, h = self.game.screen.get_rect() rect = pygame.Rect(0, 0, w, h // 4) rect.bottomright = w, h border = tools.load_and_scale(self.borders_filename) self.dialog_box = GraphicBox(border, None, self.background_color) self.dialog_box.rect = rect self.sprites.add(self.dialog_box, layer=100) # make a text area to show messages self.text_area = TextArea(self.font, self.font_color) self.text_area.rect = self.dialog_box.calc_inner_rect(self.dialog_box.rect) self.sprites.add(self.text_area, layer=100)
def load(self, slug): """Loads and sets this items's attributes from the item.db database. The item is looked up in the database by slug. :param slug: The item slug to look up in the monster.item database. :type slug: String :rtype: None :returns: None **Examples:** >>> potion_item = Item() >>> potion_item.load("item_potion") # Load an item by slug. >>> pprint.pprint(potion_item.__dict__) {'description': u'Heals a monster by 50 HP.', 'effect': [u'heal'], 'slug': 'item_potion', 'name': u'Potion', 'power': 50, 'type': u'Consumable'} """ results = items.lookup(slug, table="item") self.slug = results["slug"] # short English identifier self.name = trans(results["name_trans"]) # will be locale string self.description = trans( results["description_trans"]) # will be locale string # must be translated before displaying self.execute_trans = results['execute_trans'] self.success_trans = results['success_trans'] self.failure_trans = results['failure_trans'] self.sort = results['sort'] self.type = results["type"] self.power = results["power"] self.sprite = results["sprite"] self.usable_in = results["usable_in"] self.target = db.process_targets(results["target"]) self.effect = results["effects"] self.surface = tools.load_and_scale(self.sprite) self.surface_size_original = self.surface.get_size()
def load(self, name, id): """Loads and sets this items's attributes from the item.db database. The item is looked up in the database by name or id. :param name: The name of the item to look up in the monster.item database. :param id: The id of the item to look up in the item.db database. :type name: String :type id: Integer :rtype: None :returns: None **Examples:** >>> potion_item = Item() >>> potion_item.load("Potion", None) # Load an item by name. >>> potion_item.load(None, 1) # Load an item by id. >>> pprint.pprint(potion_item.__dict__) {'description': u'Heals a monster by 50 HP.', 'effect': [u'heal'], 'id': 1, 'name': u'Potion', 'power': 50, 'type': u'Consumable'} """ if name: results = items.lookup(name, table="item") elif id: results = items.lookup_by_id(id, table="item") self.name = results["name"] self.description = results["description"] self.id = results["id"] self.type = results["type"] self.power = results["power"] self.sprite = results["sprite"] self.target = results["target"] self.usable_in = results["usable_in"] self.surface = tools.load_and_scale(self.sprite) self.surface_size_original = self.surface.get_size() self.effect = results["effects"]
def load(self, slug): """Loads and sets this items's attributes from the item.db database. The item is looked up in the database by slug. :param slug: The item slug to look up in the monster.item database. :type slug: String :rtype: None :returns: None **Examples:** >>> potion_item = Item() >>> potion_item.load("item_potion") # Load an item by slug. >>> pprint.pprint(potion_item.__dict__) {'description': u'Heals a monster by 50 HP.', 'effect': [u'heal'], 'slug': 'item_potion', 'name': u'Potion', 'power': 50, 'type': u'Consumable'} """ results = items.lookup(slug, table="item") self.slug = results["slug"] # short English identifier self.name = trans(results["name_trans"]) # will be locale string self.description = trans(results["description_trans"]) # will be locale string # must be translated before displaying self.execute_trans = results['execute_trans'] self.success_trans = results['success_trans'] self.failure_trans = results['failure_trans'] self.sort = results['sort'] self.type = results["type"] self.power = results["power"] self.sprite = results["sprite"] self.usable_in = results["usable_in"] self.target = db.process_targets(results["target"]) self.effect = results["effects"] self.surface = tools.load_and_scale(self.sprite) self.surface_size_original = self.surface.get_size()
def load_technique_animation(technique): """ TODO: move to some generic animation loading thingy :param technique: :rtype: core.components.sprite.Sprite """ frame_time = .09 images = list() for fn in technique.images: image = tools.load_and_scale(fn) images.append((image, frame_time)) tech = PygAnimation(images, False) sprite = Sprite() sprite.image = tech sprite.rect = tech.get_rect() return sprite
def load_technique_animation(technique): """ TODO: move to some generic animation loading thingy :param technique: :rtype: core.components.sprite.Sprite """ frame_time = 0.09 images = list() for fn in technique.images: image = tools.load_and_scale(fn) images.append((image, frame_time)) tech = PygAnimation(images, False) sprite = Sprite() sprite.image = tech sprite.rect = tech.get_rect() return sprite
def load(slot): """Loads game state data from a shelved save file. :param slot: The save slot to load game data from. :type slot: Integer :rtype: Dictionary :returns: Dictionary containing game data to load. **Examples:** >>> core.components.load.load(1) """ # this check is required since opening a shelve will # create the pickle is it doesn't already exist. # this check prevents a bug where saves are not recorded # properly. save_path = prepare.SAVE_PATH + str(slot) + ".save" if not os.path.exists(save_path): return saveFile = shelve.open(save_path) saveData = dict() saveData["game_variables"] = saveFile["game_variables"] saveData["tile_pos"] = saveFile["tile_pos"] tempinv = dict(saveFile["inventory"]) for keys, values in tempinv.items(): # TODO: unify loading and game instancing for keys2, values2 in values.items(): if keys2 == "item": values2.surface = tools.load_and_scale(values2.sprite) saveData["inventory"] = tempinv tempmon = list(saveFile["monsters"]) for mon in tempmon: mon.load_sprites() saveData["monsters"] = tempmon # TODO: unify loading and game instancing # Loop through the storage item keys and re-add the surface. tempstorage = dict(saveFile["storage"]) for keys, values in tempstorage.items(): if keys == "items": for keys2, values2 in values.items(): for keys3, values3 in values2.items(): if keys3 == "item": values3.surface = tools.load_and_scale(values3.sprite) if keys == "monsters": for storemon1 in values: storemon1.load_sprites() saveData["storage"] = tempstorage saveData["current_map"] = saveFile["current_map"] saveData["player_name"] = saveFile["player_name"] saveData["time"] = saveFile["time"] return saveData
def load(slot): """Loads game state data from a shelved save file. :param slot: The save slot to load game data from. :type slot: Integer :rtype: Dictionary :returns: Dictionary containing game data to load. **Examples:** >>> core.components.load.load(1) """ # this check is required since opening a shelve will # create the pickle is it doesn't already exist. # this check prevents a bug where saves are not recorded # properly. save_path = prepare.SAVE_PATH + str(slot) + '.save' if not os.path.exists(save_path): return saveFile = shelve.open(save_path) saveData = dict() saveData['game_variables'] = saveFile['game_variables'] saveData['tile_pos'] = saveFile['tile_pos'] tempinv = dict(saveFile['inventory']) for keys, values in tempinv.items(): # TODO: unify loading and game instancing for keys2, values2 in values.items(): if keys2 == 'item': values2.surface = tools.load_and_scale(values2.sprite) saveData['inventory'] = tempinv tempmon = list(saveFile['monsters']) for mon in tempmon: mon.load_sprites() saveData['monsters'] = tempmon # TODO: unify loading and game instancing # Loop through the storage item keys and re-add the surface. tempstorage = dict(saveFile['storage']) for keys, values in tempstorage.items(): if keys == 'items': for keys2, values2 in values.items(): for keys3, values3 in values2.items(): if keys3 == 'item': values3.surface = tools.load_and_scale(values3.sprite) if keys == 'monsters': for storemon1 in values: storemon1.load_sprites() saveData['storage'] = tempstorage saveData['current_map'] = saveFile['current_map'] saveData['player_name'] = saveFile['player_name'] saveData['time'] = saveFile['time'] return saveData
def load_graphics(self): """ Image become class attribute, so is shared. Eventually, implement some game-wide image caching """ image = tools.load_and_scale(self.border_filename) HpBar.border = GraphicBox(image)