def __init__(self, father): CascadeElement.__init__(self) self.inventory_display = StatusDisplay(self) self.mob_list = [] self.current_question_key = '' self.previous_question = '' self.current_question = None self.bg = SimpleSprite('menu.png') self.inventory = [] self.cursor = SimpleSprite('icons/magnifyingglass.png') self.pc_position = GameTile(0, 0) self.pc_sprite = SimpleSprite('tiles/Fighter.png') self.map = WorldMap(0) self.subsprites = [ self.bg, self.inventory_display, self.map, self.pc_sprite, self.cursor ] self.formation = [ (-2, 4), (-1, 4.5), (0, 4), (1, 4.5), (2, 4), ] Interface.__init__(self, father, keys=[ ('(up|down)(left|right)?', self.move), (K_ESCAPE, self.quit), ])
def test_raycast(self): ray = list(self.t1.raycast(self.t2)) assert GameTile(2, 3) in ray assert GameTile(3, 3.5) in ray assert GameTile(3, 4.5) in ray assert len(ray) == 3
def test_tile_dist(self): # +1 +0.5 is a hex move t1 = GameTile(5, 2.5) t2 = GameTile(3, 1.5) d = t1.dist(t2) assert round(d, ndigits=10) == 2
def test_range(self): c1 = Creature('Archer', is_pc=True) g = Combat([(c1, (0, 0))], []) hint = g.get_range_hint(c1, c1.abilities[0]) assert GameTile(4, 4) not in hint assert GameTile(0, -2) in hint assert GameTile(1, -1.5) in hint
def test_move(self): c = Creature('Barbarian') c.set_in_combat(FakeCombat(), GameTile(0, 0), 0) c.move_or_attack(GameTile(0, 1)) assert c.tile == GameTile(0, 1) assert c.free_moves == 0 assert c.next_action == 0
def test_attack(self): f = FakeCombat() c1 = Creature('Archer', is_pc=True) c2 = Creature('Archer', is_pc=False) c1.set_in_combat(f, GameTile(0, 0), 0) c2.set_in_combat(f, GameTile(0, 1), 0) c1.move_or_attack(GameTile(0, 1)) assert c1.tile == GameTile(0, 0) assert c1.next_action == 100 assert c2.health == c2.maxhealth - c1.damage
def test_cleave(self): f = FakeCombat() c1 = Creature('Barbarian', is_pc=True) c2 = Creature('Archer', is_pc=False) c1.set_in_combat(f, GameTile(0, 0), 0) c2.set_in_combat(f, GameTile(0, 1), 0) c1.use_ability(c1.abilities[0], c1.tile) assert c1.next_action == 100 assert c1.abilities[0].current_cooldown == 200 assert c2.health == c2.maxhealth - c1.damage assert c1.health == c1.maxhealth
def test_fireball(self): f = FakeCombat() c1 = Creature('Wizard', is_pc=True) c2 = Creature('Archer', is_pc=False) c3 = Creature('Archer', is_pc=False) c1.set_in_combat(f, GameTile(0, 0), 0) c2.set_in_combat(f, GameTile(0, 1), 0) c3.set_in_combat(f, GameTile(1, 0.5), 0) c1.use_ability(c1.abilities[0], c2.tile) assert c1.abilities[0].current_cooldown == 200 assert c2.health == c2.maxhealth - 15 assert c3.health == c3.maxhealth - 11 assert c1.health == c1.maxhealth
def update(self, mouse_pos): self.updates += 1 self.father.combat_ui.update(self.father.combat, mouse_pos) range_hint = self.father.combat.get_range_hint( self.father.combat.to_act, self.ability) for target in range_hint: self.father.combat_ui.arena.board[target].animate( 'tiles/GreyTile2.png') splash_hint = self.father.combat.get_splash_hint( self.father.combat.to_act, self.ability, self.target) for target in splash_hint: self.father.combat_ui.arena.board[target].animate( 'tiles/Yellow2.png') targets_hint = [] backgrounds = [] for i, target in enumerate(self.valid_targets): key = i + 1 if i < 9 else 0 x, y = target.display_location() t = TextSprite('[%d]' % key, '#ffff00', x=x + 4, y=y + 6) background = Gauge(32, 32, '#000000') background.move_to(x, y) background.image.set_alpha(50) backgrounds.append(background) targets_hint.append(t) tile = GameTile.get_tile_for_mouse(mouse_pos) if tile and tile in self.valid_targets: self.target = tile self.father.combat_ui.display() for t in backgrounds: t.display() for t in targets_hint: t.display() self.father.combat_ui.cursor.display()
def spawn_creatures(self, pcs, mobs): i = 0 for pc, gt in pcs: if pc.health > 0: pc.set_in_combat(self, GameTile(*gt), i) i += 2 i = 1 mob_zone = [ gt for gt in GameTile.all_tiles(self.MAP_RADIUS) if gt.y < -3.25 ] for mobdef in mobs: gt = random.choice(mob_zone) mob_zone.remove(gt) c = Creature(mobdef) c.set_in_combat(self, gt, i) i += 2
def gen_random(self): self.board = {} self.gen_room(GameTile(0, 0)) extremums = [] for neighb in GameTile(0, 0).neighbours(): self.board[neighb + neighb] = rand_tile(neighb + neighb, self.level) self.gen_room(neighb + neighb + neighb + neighb) extremums.append(neighb + neighb + neighb + neighb + neighb + neighb) random_stair = random.choice(extremums) extremums.remove(random_stair) self.board[random_stair] = StairTile(random_stair) pc_tile = random.choice(extremums) pc_tile = GameTile(pc_tile.x * 5 / 6, pc_tile.y * 5 / 6) self.board[pc_tile] = MapTile(pc_tile) return pc_tile
def __init__(self, radius): super().__init__() self.radius = radius self.board = {} for tile in GameTile.all_tiles(radius): self.board[tile] = SimpleSprite('tiles/GreyTile.png') self.board[tile].rect.move_ip(*tile.display_location()) self.subsprites = list(self.board.values())
class TestGametile: def setup(self): self.t1 = GameTile(2, 2) self.t2 = GameTile(3, 4.5) def test_tile_add(self): t = self.t1 + self.t2 assert t.x == 5 assert t.y == 6.5 def test_tile_sub(self): t = self.t2 - self.t1 assert t.x == 1 assert t.y == 2.5 def test_tile_dist(self): # +1 +0.5 is a hex move t1 = GameTile(5, 2.5) t2 = GameTile(3, 1.5) d = t1.dist(t2) assert round(d, ndigits=10) == 2 def test_tile_compare(self): t1_bis = GameTile(2.0, 2) assert self.t1 == t1_bis assert self.t2 != t1_bis def test_mouse_location(self): xt1, yt1 = self.t1.display_location() assert GameTile.get_tile_for_mouse((xt1, yt1)) == self.t1 assert GameTile.get_tile_for_mouse((xt1 + 20, yt1 + 20)) == self.t1 def test_raycast(self): ray = list(self.t1.raycast(self.t2)) assert GameTile(2, 3) in ray assert GameTile(3, 3.5) in ray assert GameTile(3, 4.5) in ray assert len(ray) == 3
def make_tiles(self): size = settings.square_size for i in range(0, 3): for j in range(0, 3): self.tiles[i][j] = GameTile( int(settings.screen_width / 2) - int(size / 2) - size + (size * i), int(settings.screen_height / 2) - int(size / 2) - size + (size * j), self)
def update(self, combat, mouse_pos): self.game_frame += 1 self.cursor.rect.x, self.cursor.rect.y = mouse_pos[0] - 10, mouse_pos[ 1] - 10 tile = GameTile.get_tile_for_mouse(mouse_pos) self.hover_xair.update(tile) self.selected_xair.update(combat.selected) for creature in combat.creatures.values(): if creature not in self.subsprites: self.subsprites.insert(3, creature) creature = combat.creatures.get( tile, combat.creatures.get(combat.selected, combat.to_act)) if creature: self.hover_display.update(creature, mouse_pos) self.hover_display.must_show = True else: self.hover_display.must_show = False self.arena.update(combat.to_act)
def load_game(self, slot): self.slot = slot with open('save%d.json' % slot) as f: d = json.loads(f.read()) self.party_gold = d['gold'] self.pc_position = GameTile.from_string(d['pc_position']) self.level = d['level'] self.party_food = d['food'] self.map.level = self.level for key in d['inventory_dump']: item_class = items.ITEMS[key][0] item_args = items.ITEMS[key][1] self.inventory.append(item_class(*item_args)) self.pc_list = [ Creature.dict_load(pc, self.inventory) for pc in d['pcs'] ] self.map.load_dict(d['map']) self.map.board[self.pc_position].on_step(self)
def __init__(self, combat): super().__init__() self.arena = Arena(combat.MAP_RADIUS) self.cursor = SimpleSprite('icons/magnifyingglass.png') self.hover_display = InfoDisplay(18, 90) self.log_display = LogDisplay() self.bg = SimpleSprite('bg.png') self.dmg_log_display = DamageLogDisplay() self.to_act_display = NextToActDisplay() self.hover_xair = HoverXair('icons/target.png') self.hover_xair.rect.x, self.hover_xair.rect.y = GameTile( 0, 0).display_location() self.selected_xair = HoverXair('icons/select.png') self.subsprites = [ self.bg, self.arena, self.log_display, self.dmg_log_display, self.to_act_display, self.hover_display, self.hover_xair, self.selected_xair, self.cursor ] for c in combat.creatures.values(): self.subsprites.insert(3, c) self.log_display.push_text('Press [?] for help and keybindings') self.game_frame = 0
def get_splash_hint(self, creature, ability, selected): valid_range = [ tile for tile in GameTile.all_tiles(self.MAP_RADIUS) if ability.splash_hint(creature, selected, tile) ] return valid_range
def get_range_hint(self, creature, ability): valid_range = [ tile for tile in GameTile.all_tiles(self.MAP_RADIUS) if ability.range_hint(creature, tile) ] return valid_range
def get_valid_targets(self, creature, ability): valid_targets = [ tile for tile in GameTile.all_tiles(self.MAP_RADIUS) if ability.is_valid_target(creature, tile) ] return valid_targets
class WorldInterface(Interface, CascadeElement): def __init__(self, father): CascadeElement.__init__(self) self.inventory_display = StatusDisplay(self) self.mob_list = [] self.current_question_key = '' self.previous_question = '' self.current_question = None self.bg = SimpleSprite('menu.png') self.inventory = [] self.cursor = SimpleSprite('icons/magnifyingglass.png') self.pc_position = GameTile(0, 0) self.pc_sprite = SimpleSprite('tiles/Fighter.png') self.map = WorldMap(0) self.subsprites = [ self.bg, self.inventory_display, self.map, self.pc_sprite, self.cursor ] self.formation = [ (-2, 4), (-1, 4.5), (0, 4), (1, 4.5), (2, 4), ] Interface.__init__(self, father, keys=[ ('(up|down)(left|right)?', self.move), (K_ESCAPE, self.quit), ]) def on_return(self, defunct=None): self.pc_list = [pc for pc in self.pc_list if pc.health > 0] if not self.pc_list: self.erase_save() game_over = GameOverModal(self) self.desactivate() game_over.activate() def on_click(self, mouse_pos): self.inventory_display.on_click(mouse_pos) def new_game(self, slot): self.slot = slot self.party_gold = 0 self.party_food = 400 self.level = 1 self.map.level = 1 self.pc_list = [ Creature('Fighter', is_pc=True), Creature('Barbarian', is_pc=True), Creature('Archer', is_pc=True), Creature('Wizard', is_pc=True), Creature('Enchantress', is_pc=True), ] self.pc_position = self.map.gen_random() def display_choices(self): pass def move(self, key): moves = { 'down': 1, 'downleft': 0, 'downright': 2, 'up': 4, 'upright': 5, 'upleft': 3 } index = moves[key] new_position = self.pc_position.neighbours()[index] if self.map.board[new_position].is_wall: return self.party_food -= len(self.pc_list) if self.party_food < 0: self.erase_save() game_over = GameOverModal(self) self.desactivate() game_over.activate() self.pc_position = new_position self.map.board[self.pc_position].on_step(self) def update(self, mouse_pos): self.inventory_display.update(mouse_pos) self.pc_sprite.rect.x, self.pc_sprite.rect.y = self.pc_position.display_location( ) self.map.update(self.pc_position) self.cursor.rect.x, self.cursor.rect.y = mouse_pos self.map.update(self.pc_position) self.display() def start_combat(self, mobs): self.save_game() gi = CombatInterface(self, mobs) gi.activate() self.desactivate() def save_game(self): pc_dump = [pc.dict_dump() for pc in self.pc_list] inventory_dump = [item.name for item in self.inventory] save = { 'pcs': pc_dump, 'gold': self.party_gold, 'food': self.party_food, 'level': self.level, 'map': self.map.dict_dump(), 'inventory_dump': inventory_dump, 'pc_position': self.pc_position.dict_dump() } with open('save%d.json' % self.slot, 'w') as f: f.write(json.dumps(save)) def quit(self, mouse_pos): self.save_game() self.done() def erase_save(self): try: os.unlink('save%d.json' % self.slot) except FileNotFoundError: pass def load_game(self, slot): self.slot = slot with open('save%d.json' % slot) as f: d = json.loads(f.read()) self.party_gold = d['gold'] self.pc_position = GameTile.from_string(d['pc_position']) self.level = d['level'] self.party_food = d['food'] self.map.level = self.level for key in d['inventory_dump']: item_class = items.ITEMS[key][0] item_args = items.ITEMS[key][1] self.inventory.append(item_class(*item_args)) self.pc_list = [ Creature.dict_load(pc, self.inventory) for pc in d['pcs'] ] self.map.load_dict(d['map']) self.map.board[self.pc_position].on_step(self) def pay(self, amount): self.party_gold -= amount
def on_click(self, mouse_pos): tile = GameTile.get_tile_for_mouse(mouse_pos) if self.combat.selected and self.combat.selected == tile: self.combat.selected = None else: self.combat.selected = tile
def on_click(self, mouse_pos): self.target = GameTile.get_tile_for_mouse(mouse_pos) if self.target and self.target in self.valid_targets: self.father.combat.selected = None self.done()
def setup(self): self.t1 = GameTile(2, 2) self.t2 = GameTile(3, 4.5)
def load_dict(self, d): for k, v in d.items(): tile = GameTile.from_string(k) self.board[tile] = MapTile.from_list(v, tile)
def test_mouse_location(self): xt1, yt1 = self.t1.display_location() assert GameTile.get_tile_for_mouse((xt1, yt1)) == self.t1 assert GameTile.get_tile_for_mouse((xt1 + 20, yt1 + 20)) == self.t1
def test_tile_compare(self): t1_bis = GameTile(2.0, 2) assert self.t1 == t1_bis assert self.t2 != t1_bis