def __init__(self, use_function=None, uses=-99, item_type=ItemType.NONE, equip_effects=None, strength=0, defense=0, price=0, description="", **kwargs): self.use_function = use_function self.uses = uses self.function_kwargs = kwargs self.item_type = item_type self.equip_effects = equip_effects self.price = price self.description = description if strength != 0: ammo = kwargs['ammo'] if 'ammo' in kwargs else 0 self.weapon = Weapon(strength, ammo) else: self.weapon = None if defense != 0: self.armor = Armor(defense) else: self.armor = None
def create_component(component): """ Return the desired component. """ # Weapon components. if component == WeaponComponent.LASER: return Weapon(name='pulse laser', damage=5, min_targets=1, max_targets=5, color=libtcod.green, range=10, cost=2, rate_of_fire=10, projectile=ProjectileType.LASER_PROJECTILE) elif component == WeaponComponent.GUN: return Weapon(name='gattling gun', damage=5, min_targets=1, max_targets=3, color=libtcod.red, range=10, cost=1, rate_of_fire=4, projectile=ProjectileType.BASIC_PROJECTILE) # Chassis components. elif component == ChassisComponent.BASIC_CHASSIS: return Chassis(max_hp=30) elif component == ChassisComponent.WEAK_CHASSIS: return Chassis(max_hp=20) # Propulsion components. elif component == PropulsionComponent.BASIC_PROPULSION: return Propulsion(max_speed=12, max_impulse=2) elif component == PropulsionComponent.WEAK_PROPULSION: return Propulsion(max_speed=4, max_impulse=1) # AI components. elif component == AIComponent.DEBUG: return DoNothing() elif component == AIComponent.PROJECTILE: return ProjectileAI() return None
def __init__(self, *groups): SHEET = sprite_sheet((100,100), 'assets/ship-death.png') super().__init__(pygame.transform.scale(PLAYER, (125, 125)), (200, 800, 120), (WIDTH/2, HEIGHT-50), groups) self.hp = 6 self.mask = pygame.mask.from_surface(self.image, 200) self.image.fill((5, 5, 5, 10), special_flags=pygame.BLEND_RGB_ADD) self.sheet = SHEET self.rect = self.image.get_rect() self.weapon = Weapon(Bullet) self.direction = 'stop' self.death_animation_timer = Timer(60) self.destruction_sound = pygame.mixer.Sound('assets/sounds/enemy_hit.ogg') self.current_sprite_index = 0 self.dying = False self.post_death_timer = Timer(500) self.health_bar = PlayerHealthBar(self.hp) self.regen_cooldown_timer = Timer(50*100) self.regen_timer = Timer(500)
def __init__(self): super().__init__(PLAYER, (130, 200, 120)) self.mask = pygame.mask.from_surface(self.image) self.rect = self.image.get_rect() self.rect.x = 700 / 2 - 40 self.rect.y = 330 # self.rect.centerx = self.rect.width / 2 self.speed = 4 self.weapon = Weapon(Bullet) self.pos = (350, 350) self.direction = 'stop'
def build_long_sword(): _long_sword = Item( uid="long_sword", name="Longsword", description="A longsword.", display=Display(Colors.DARK_GRAY, Colors.BLACK_COLOR, "!"), ) _long_sword.register_component(data.python_templates.material.Iron.copy()) _long_sword.register_component(Stats(health=1, size=Size.Medium)) _long_sword.register_component( Weapon(weapon_category=item_enums.WeaponCategory.Martial, weapon_type=item_enums.WeaponType.Melee, size=Size.Medium, melee_damage_type=DamageType.Slash, damage_dice=DiceStack(1, Dice(8)))) return _long_sword
def main(): screen_width = 80 screen_height = 50 bar_width = 20 panel_height = 7 panel_y = screen_height - panel_height message_x = bar_width + 2 message_width = screen_width - bar_width - 2 message_height = panel_height - 1 map_width = 80 map_height = 43 fov_algorithm = 'BASIC' fov_light_walls = True fov_radius = 10 colors = { 'dark_wall': (0, 0, 100), 'dark_ground': (50, 50, 150), 'light_wall': (130, 110, 50), 'light_ground': (200, 180, 50), 'white': (255, 255, 255), 'black': (0, 0, 0), 'light red': (255, 100, 100), 'red': (255, 0, 0), 'yellow': (255, 255, 0), 'orange': (255, 127, 0), 'green': ( 0, 255, 0, ), 'light_red': (255, 114, 114), 'darker_red': (127, 0, 0), 'highlight': (199, 234, 70) } mech_component = Mech(hp=30, peak_momentum=6) weapon_component = Weapon(name="Laser", damage=5, min_targets=0, max_targets=5, color=colors.get('green'), range=10) player = Entity(int(screen_width / 2), int(screen_height / 2), '@', colors.get('white'), "player", mech=mech_component, weapon=weapon_component) npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), '@', colors.get('yellow'), "NPC") cursor_component = Cursor() cursor = Entity( -1, -1, ' ', colors.get('red'), "cursor", cursor=cursor_component ) # The ' ' isn't actually "nothing". To have nothing, I would have to mess with a render order. entities = [npc, player, cursor] tdl.set_font('arial10x10.png', greyscale=True, altLayout=True) root_console = tdl.init(screen_width, screen_height, title='MVP v0.0') con = tdl.Console(screen_width, screen_height) panel = tdl.Console(screen_width, panel_height) game_map = GameMap(map_width, map_height) make_map(game_map) message_log = MessageLog(message_x, message_width, message_height) mouse_coordinates = (0, 0) game_state = GameStates.PLAYER_TURN previous_game_state = game_state turn_state = TurnStates.UPKEEP_PHASE fov_recompute = True while not tdl.event.is_window_closed(): if fov_recompute: game_map.compute_fov(player.x, player.y, fov=fov_algorithm, radius=fov_radius, light_walls=fov_light_walls) render_all(con, panel, entities, game_map, fov_recompute, root_console, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse_coordinates, colors) tdl.flush() clear_all(con, entities) for event in tdl.event.get(): if event.type == 'KEYDOWN': user_input = event break elif event.type == 'MOUSEMOTION': mouse_coordinates = event.cell else: user_input = None fov_recompute = False action = handle_keys(user_input, game_state) impulse = None # This is to avoid logic problems. change_game_state = None # This is to avoid logic problems. move = action.get('move') # Attempt to move. impulse = action.get('impulse') # Adjust mech impulse. next_turn_phase = action.get( 'next turn phase') # Move to the next phase. change_game_state = action.get( 'change game state') # Go to different game_state select = action.get( 'select') # A target has been selected via keyboard. exit = action.get('exit') # Exit whatever screen is open. fullscreen = action.get('fullscreen') # Set game to full screen. if exit: if game_state == GameStates.TARGETING: # Turn off cursor cursor.char = ' ' cursor.x = -1 cursor.y = -1 fov_recompute = True game_state = previous_game_state else: return True if fullscreen: tdl.set_fullscreen(not tdl.get_fullscreen()) if game_state == GameStates.PLAYER_TURN: # See game_states.py for the turn structure. # Turns order is reversed so ensure that the loop runs once for each if turn_state == TurnStates.POST_ATTACK_PHASE: # Reset map flags and remove targets. reset_flags(game_map) for x, y in player.weapon.targets: erase_cell(con, x, y) turn_state = TurnStates.UPKEEP_PHASE game_state = GameStates.ENEMY_TURN if turn_state == TurnStates.ATTACK_PHASE: if change_game_state == GameStates.TARGETING: # Turn on cursor. cursor.char = 'X' # If there were no previous targets, start on the player. if len(player.weapon.targets) == 0: cursor.x = player.x cursor.y = player.y else: cursor.x, cursor.y = player.weapon.targets[-1] fov_recompute = True previous_game_state = game_state game_state = GameStates.TARGETING if next_turn_phase: turn_state = TurnStates.POST_ATTACK_PHASE if turn_state == TurnStates.PRE_ATTACK_PHASE: message_log.add_message( Message('Begin ATTACK PHASE.', colors.get('white'))) message_log.add_message( Message( 'Press f to target. Press ESC to stop targeting. Enter to change phase.', colors.get('orange'))) fov_recompute = True turn_state = TurnStates.ATTACK_PHASE if turn_state == TurnStates.POST_MOVEMENT_PHASE: reset_flags(game_map) player.reset( ) # Reset the mech for the next turn. ### Move this to the post-attack phase fov_recompute = True turn_state = TurnStates.PRE_ATTACK_PHASE if turn_state == TurnStates.MOVEMENT_PHASE: if move: dx, dy = move if game_map.walkable[player.x + dx, player.y + dy]: player.move(dx, dy) fov_recompute = True if next_turn_phase and player.mech.has_spent_minimum_momentum( ): turn_state = TurnStates.POST_MOVEMENT_PHASE elif next_turn_phase and not player.mech.has_spent_minimum_momentum( ): message_log.add_message( Message('Must spend more momentum.', colors.get('red'))) if turn_state == TurnStates.PRE_MOVEMENT_PHASE: if impulse is not None: player.mech.impulse = impulse turn_state = TurnStates.MOVEMENT_PHASE message_log.add_message( Message('Impulse set to {0}.'.format(impulse), colors.get('orange'))) fov_recompute = True highlight_legal_moves(player, game_map) if turn_state == TurnStates.UPKEEP_PHASE and game_state == GameStates.PLAYER_TURN: # This is added to avoid starting the Upkeep Phase when the turn just ended. message_log.add_message( Message('Begin PLAYER TURN.', colors.get('white'))) message_log.add_message( Message('Begin MOVEMENT PHASE.', colors.get('white'))) message_log.add_message( Message('Choose impulse. PAGEUP, PAGEDOWN or HOME.', colors.get('orange'))) turn_state = TurnStates.PRE_MOVEMENT_PHASE fov_recompute = True if game_state == GameStates.ENEMY_TURN: message_log.add_message( Message('Begin ENEMY TURN.', colors.get('white'))) fov_recompute = True game_state = GameStates.PLAYER_TURN if game_state == GameStates.TARGETING: if move: dx, dy = move # Ensure the first target is in firing range. if len(player.weapon.targets) == 0: if player.distance(cursor.x + dx, cursor.y + dy) <= player.weapon.range: cursor.fly(dx, dy) fov_recompute = True else: message_log.add_message( Message('Out of range.', colors.get('red'))) # Ensure that the next targets are adjacent to the previous target elif len(player.weapon.targets) > 0: tar_x, tar_y = player.weapon.targets[ -1] # Get the most recent target added. if abs(tar_x - (cursor.x + dx)) + abs(tar_y - (cursor.y + dy)) <= 1: cursor.fly(dx, dy) fov_recompute = True else: message_log.add_message( Message('Invalid target.', colors.get('red'))) if select: if len(player.weapon.targets) < player.weapon.max_targets: if set_targeted( game_map, cursor.x, cursor.y ): # At the moment, this always returns True. In the future, this may change. fov_recompute = True player.weapon.targets.append((cursor.x, cursor.y)) else: message_log.add_message( Message('Targeting failed.', colors.get('red')))
class Player(Entity): """ represents the Player. """ def __init__(self, *groups): SHEET = sprite_sheet((100,100), 'assets/ship-death.png') super().__init__(pygame.transform.scale(PLAYER, (125, 125)), (200, 800, 120), (WIDTH/2, HEIGHT-50), groups) self.hp = 6 self.mask = pygame.mask.from_surface(self.image, 200) self.image.fill((5, 5, 5, 10), special_flags=pygame.BLEND_RGB_ADD) self.sheet = SHEET self.rect = self.image.get_rect() self.weapon = Weapon(Bullet) self.direction = 'stop' self.death_animation_timer = Timer(60) self.destruction_sound = pygame.mixer.Sound('assets/sounds/enemy_hit.ogg') self.current_sprite_index = 0 self.dying = False self.post_death_timer = Timer(500) self.health_bar = PlayerHealthBar(self.hp) self.regen_cooldown_timer = Timer(50*100) self.regen_timer = Timer(500) def get_event(self, event, **state): if event.type == pygame.MOUSEBUTTONDOWN: can_fire = self.weapon.ammo > 0 and not self.dying if can_fire and event.button == 1: self.weapon.begin_fire(self.rect.center) state['shots_fired'] += 1 elif can_fire and event.button == 3: for i in range(3): bullet = Chain_Lightning(self.rect.center, self.weapon.bullets) bullet.find_next_target(state['enemy_list'].sprites() + state['boss_list'].sprites()) state['shots_fired'] += 1 self.weapon.ammo -= 1 elif event.button == 2: self.weapon.ammo += 30 elif not can_fire: print('you loose') pygame.mixer.music.fadeout(1000) # message_display('YOU LOOSE OUT OF AMMO!!!', WHITE, pygame.display.get_surface(), (700, 400)) signaly.emit('GAME_OVER') # self.done = True elif event.type == pygame.MOUSEBUTTONUP: if event.button == 1: self.weapon.cease_fire() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_a: self.move('left') if event.key == pygame.K_d: self.move('right') elif event.type == pygame.KEYUP: if event.key == pygame.K_a: self.move('stop') if event.key == pygame.K_d: self.move('stop') def collision_detected(self, hp_delta): self.hp -= hp_delta self.regen_timer.reset() self.regen_cooldown_timer.start() def handle_regen(self): if self.regen_cooldown_timer.is_finished(): self.regen_timer.start_repeating() signaly.emit('PLAYER_MSSG', 'REGEN!') if self.regen_timer.is_finished(): crit_roll = randint(1, 101) will_crit = crit_roll > 96 if will_crit: amt = 0.15*10 else: amt = 0.15 if self.hp < self.health_bar.starting_hp and not self.dying: self.hp += amt signaly.emit('PLAYER_MSSG', amt) if self.hp == self.health_bar.starting_hp: # self.hp = self.health_bar.starting_hp self.regen_timer.reset() def explode(self): if not self.dying: self.destruction_sound.play() self.dying = True self.max_speed = 45 self.death_animation_timer.start_repeating() self.weapon.cease_fire() self.image = pygame.transform.scale(self.sheet[self.current_sprite_index], (125, 125)) def sprite_animation(self): cap = 11 if (self.death_animation_timer.is_finished()): self.current_sprite_index+=1 if self.current_sprite_index == cap-1: self.post_death_timer.start() elif self.current_sprite_index >= cap: self.current_sprite_index = cap self.image = pygame.transform.scale(self.sheet[self.current_sprite_index], (125, 125)) def draw(self, screen): """ draw player specifically """ mouse_pos = pygame.mouse.get_pos() des = self.pos - vec(mouse_pos) angle = angle_from_vec(des) img, rect = self.rot_center(self.image, self.rect, angle) rect.center = self.rect.center screen.blit(img, rect) def move(self, direction): self.direction = direction def update(self, dt): """ update the player's position to the mouse x position """ self.handle_regen() self.sprite_animation() self.weapon.bullets.update(dt) self.health_bar.update(self.hp) if self.post_death_timer.is_finished(): self.kill() signaly.remove_subscriber('PLAYER_MSSG') signaly.emit('GAME_OVER') if self.direction == 'left': self.acc = vec(-1, 0).normalize() * self.max_speed elif self.direction == 'right': self.acc = vec(701, 0).normalize() * self.max_speed elif self.direction == 'stop': self.acc = vec(0 ,0) # give edges of screen a little bounce when hit if self.pos[0] >= (WIDTH -30): self.pos[0] = WIDTH -30 self.acc = vec(-1, 0).normalize() * 2000 elif self.pos[0] <= 30: self.pos[0] = 30 self.acc = vec(701, 0).normalize() * 2000 super().update(dt)