class Game: def __init__(self): # initialize imported components pygame.init() # number of frames rendered per second # (equal to number of loop turns) self.FPS = 60 # clock to synchronize ticks with desired FPS self.clock = pygame.time.Clock() # main loop condition self.running = True # initialize subsystems self.drawer = Drawer() self.handler = EventHandler(self) self.game_state = GameState() self.manager = Manager() self.ticker = Ticker(self) def initialize(self): # create game objects from scaffold # and add them to proper subsystems scaffold = Scaffold() for obj in scaffold.objects: self.manager.add_object(obj) for obs in scaffold.observers: self.game_state.add_observer(obs) for e in scaffold.recurring_events: self.ticker.add_event(e) def shutdown(self): # this will break main loop self.running = False def exit(self): # close all imported components pygame.quit() # force exit program exit(1) def loop(self): self.initialize() # main loop while self.running: # synchronize self.clock.tick(self.FPS) # notify ticker self.ticker.tick() # render game objects self.drawer.draw(self.manager) # respond to events self.handler.handle() self.exit()
def take_damage(self, val): if self.dmg_reduction > 0: val -= self.dmg_reduction if val > 0: self.hp -= val if self.hp <= 0: f = self.death_function if f is not None: EventHandler.add_death_event('death', (f, self.owner))
def picked_up(self, entity_picker, objects): assert entity_picker.inventory is not None, 'cannot pick up items without an inventory' if len(entity_picker.inventory) >= 26: EventHandler.add_inventory_event(ActionType.PICK_UP_FAIL, (self.owner, entity_picker)) return ActionType.PICK_UP_FAIL else: entity_picker.inventory.items.append(self.owner) objects.remove(self.owner) EventHandler.add_inventory_event(ActionType.PICK_UP_GAIN, (self.owner, entity_picker)) return ActionType.PICK_UP_GAIN
def __init__(self): # initialize imported components pygame.init() # number of frames rendered per second # (equal to number of loop turns) self.FPS = 60 # clock to synchronize ticks with desired FPS self.clock = pygame.time.Clock() # main loop condition self.running = True # initialize subsystems self.drawer = Drawer() self.handler = EventHandler(self) self.game_state = GameState() self.manager = Manager() self.ticker = Ticker(self)
def move_or_attack(dx, dy, objects, player, tilemap): x = player.x + dx y = player.y + dy target = None for o in objects: if o.fighter and o.x == x and o.y == y: target = o break if target is not None: results = Combat.melee_attack(player, target) EventHandler.add_combat_event(ActionType.MELEE_COMBAT, (player, target, results)) return ActionType.MELEE_COMBAT else: player.move(dx, dy, tilemap, objects) RenderFunctions.fov_recompute = True EventHandler.add_move_event(ActionType.MOVE, None) return ActionType.MOVE
def update(self, action): if action in (ActionType.MELEE_COMBAT, ActionType.RANGED_COMBAT): self.game_state = GameState.ENEMY_TURN elif action == ActionType.PICK_UP_GAIN: self.game_state = GameState.ENEMY_TURN elif action == ActionType.MOVE: self.game_state = GameState.ENEMY_TURN RenderFunctions.compute_fov(self) # event updates and messages EventHandler.update() # enemy turn if self.game_state == GameState.ENEMY_TURN: for o in self.objects: if o.fighter and o.ai and o.timeobj: o.timeobj.tick() self.__game_time += 1 self.game_state = GameState.PLAYING
def attack_closest(objects, player, fov_map, max_range=10): closest = None closest_dist = max_range + 1 for o in objects: if o.fighter and o != player and libtcod.map_is_in_fov( fov_map, o.x, o.y): dist = player.distance_to_entity(o) if dist < closest_dist: closest = o closest_dist = dist if closest is not None and libtcod.map_is_in_fov( fov_map, closest.x, closest.y): if player.distance_to_entity(closest) >= 2: if player.inventory.get_equipped_in_slot(Slot.RANGED) is None: player.move_astar(closest) RenderFunctions.fov_recompute = True EventHandler.add_move_event(ActionType.MOVE, None) return ActionType.MOVE else: if player.distance_to_entity( closest) <= player.fighter.firing_range: result = Combat.ranged_attack(player, closest) RenderFunctions.fov_recompute = True EventHandler.add_combat_event( ActionType.RANGED_COMBAT, (player, closest, result)) return ActionType.RANGED_COMBAT else: player.move_astar(closest) RenderFunctions.fov_recompute = True EventHandler.add_move_event(ActionType.MOVE, None) return ActionType.MOVE elif closest.fighter.hp > 0: result = Combat.melee_attack(player, closest) EventHandler.add_combat_event(ActionType.MELEE_COMBAT, (player, closest, result)) return ActionType.MELEE_COMBAT
def melee_attack(self, target): result = Combat.melee_attack(self.owner, target) EventHandler.add_combat_event(ActionType.MELEE_COMBAT, (self.owner, target, result))
def take_turn(self): entity = self.owner player = self.world.player cost = 0 if self.state == EntityState.SLEEPING: if libtcod.map_is_in_fov(self.world.fov_map, entity.x, entity.y) or \ entity.distance_to_entity(player) + player.fighter.stealthiness <= 10: if Rolls.wake_up_roll(entity, player): self.state = EntityState.IDLE if libtcod.map_is_in_fov(self.world.fov_map, entity.x, entity.y): EventHandler.add_entity_event('wake_up', entity) cost = 100 elif self.state == EntityState.IDLE: if libtcod.map_is_in_fov(self.world.fov_map, entity.x, entity.y): self.target = player self.timer = 10 self.state = EntityState.CHASING self.target_coord = player.x, player.y EventHandler.add_entity_event('spotted', entity) cost = 50 else: wander_chance = libtcod.random_get_int(0, 0, 100) if wander_chance <= 10: self.state = EntityState.WANDERING elif wander_chance <= 20 and self.sleep_timer == 0: self.state = EntityState.SLEEPING self.sleep_timer += self.sleep_cooldown else: cost = 100 elif self.state == EntityState.CHASING: if libtcod.map_is_in_fov(self.world.fov_map, entity.x, entity.y): if entity.distance_to_entity(player) >= 2: entity.move_astar(player, self.world.tilemap, self.world.objects) self.target_coord = player.x, player.y cost = 100 elif self.target.fighter.hp > 0: entity.fighter.melee_attack(self.target) cost = 100 elif self.target_coord != (None, None) and self.timer > 0: if entity.x == self.target_coord[ 0] and entity.y == self.target_coord[1]: self.target_coord = (None, None) self.state = EntityState.IDLE else: entity.move_towards(self.target_coord[0], self.target_coord[1], self.world.tilemap, self.world.objects) self.timer -= 1 cost = 100 elif self.timer <= 0: self.timer = 0 self.target_coord = (None, None) self.state = EntityState.IDLE elif self.state == EntityState.WANDERING: if libtcod.map_is_in_fov(self.world.fov_map, entity.x, entity.y): self.target = player self.timer = 10 self.state = EntityState.CHASING self.target_coord = player.x, player.y EventHandler.add_entity_event('spotted', entity) cost = 50 else: if self.target_coord != (None, None): if entity.x == self.target_coord[ 0] and entity.y == self.target_coord[1]: self.target_coord = (None, None) self.state = EntityState.IDLE else: old_x, old_y = entity.x, entity.y entity.move_towards(self.target_coord[0], self.target_coord[1], self.world.tilemap, self.world.objects) if entity.x == old_x and entity.y == old_y: self.target_coord = (None, None) self.state = EntityState.IDLE cost = 100 else: dx = libtcod.random_get_int(0, -8, 8) dy = libtcod.random_get_int(0, -8, 8) if 0 <= entity.x + dx < Constants.consts['MAP_WIDTH'] and \ 0 <= entity.y + dy < Constants.consts['MAP_HEIGHT']: if not self.world.tilemap[entity.x + dx][entity.y + dy].blocked: self.target_coord = entity.x + dx, entity.y + dy if self.state != EntityState.SLEEPING and self.sleep_timer > 0: self.sleep_timer -= 1 return cost