Ejemplo n.º 1
0
def create_dungeon_game_state(player_state: PlayerState,
                              camera_size: Tuple[int, int],
                              difficulty_level: int) -> GameState:
    dungeon = _generate_dungeon(difficulty_level)
    player_entity = create_hero_world_entity(player_state.hero_id,
                                             dungeon.player_position)
    game_world = GameWorldState(
        player_entity=player_entity,
        non_player_characters=dungeon.npcs,
        consumables_on_ground=[],
        items_on_ground=[],
        money_piles_on_ground=[],
        walls=dungeon.walls,
        entire_world_area=dungeon.world_area,
        decoration_entities=dungeon.decorations,
        portals=[],
        chests=[],
        shrines=[],
        dungeon_entrances=[],
    )
    return GameState(game_world=game_world,
                     camera_size=camera_size,
                     player_state=player_state,
                     is_dungeon=True,
                     player_spawn_position=dungeon.player_position)
Ejemplo n.º 2
0
 def deserialize(data, player_state: PlayerState,
                 camera_size: Tuple[int, int]) -> GameState:
     return GameState(
         player_entity=PlayerJson.deserialize(player_state.hero_id,
                                              data["player"]),
         consumables_on_ground=[
             ConsumableJson.deserialize(p)
             for p in data.get("consumables_on_ground", [])
         ],
         items_on_ground=[
             ItemJson.deserialize(i)
             for i in data.get("items_on_ground", [])
         ],
         money_piles_on_ground=[
             MoneyJson.deserialize(p)
             for p in data.get("money_piles_on_ground", [])
         ],
         non_player_characters=[
             NpcJson.deserialize(e)
             for e in data.get("non_player_characters", [])
         ],
         walls=[WallJson.deserialize(w) for w in data.get("walls", [])],
         camera_size=camera_size,
         entire_world_area=WorldAreaJson.deserialize(
             data["entire_world_area"]),
         player_state=player_state,
         decoration_entities=[
             DecorationJson.deserialize(d)
             for d in data.get("decorations", [])
         ],
         portals=[
             PortalJson.deserialize(p) for p in data.get("portals", [])
         ],
         chests=[ChestJson.deserialize(c) for c in data.get("chests", [])])
Ejemplo n.º 3
0
 def _set_game_world(self, game_world: GameWorldState,
                     player_spawn_position: Tuple[int, int]):
     enabled_portals = {
         portal.portal_id: portal.world_entity.sprite
         for portal in game_world.portals if portal.is_enabled
     }
     player_state = create_player_state_as_initial(HERO_ID, enabled_portals)
     self.game_state = GameState(game_world, CAMERA_SIZE, player_state,
                                 False, player_spawn_position)
     self.game_state.game_world.player_entity = create_hero_world_entity(
         HERO_ID, player_spawn_position)
     self.game_state.center_camera_on_position(player_spawn_position)
     self.game_state.snap_camera_to_grid(self.grid_cell_size)
     if self.ui_view:  # UI view may not have been created yet at this time
         self._notify_ui_of_new_wall_positions()
Ejemplo n.º 4
0
    def deserialize(data, player_state: PlayerState,
                    camera_size: Tuple[int, int]) -> MapData:
        game_state = GameState(
            player_entity=PlayerJson.deserialize(player_state.hero_id,
                                                 data["player"]),
            consumables_on_ground=[
                ConsumableJson.deserialize(p)
                for p in data.get("consumables_on_ground", [])
            ],
            items_on_ground=[
                ItemJson.deserialize(i)
                for i in data.get("items_on_ground", [])
            ],
            money_piles_on_ground=[
                MoneyJson.deserialize(p)
                for p in data.get("money_piles_on_ground", [])
            ],
            non_player_characters=[
                NpcJson.deserialize(e)
                for e in data.get("non_player_characters", [])
            ],
            walls=[WallJson.deserialize(w) for w in data.get("walls", [])],
            camera_size=camera_size,
            entire_world_area=WorldAreaJson.deserialize(
                data["entire_world_area"]),
            player_state=player_state,
            decoration_entities=[
                DecorationJson.deserialize(d)
                for d in data.get("decorations", [])
            ],
            portals=[
                PortalJson.deserialize(p) for p in data.get("portals", [])
            ],
            chests=[ChestJson.deserialize(c) for c in data.get("chests", [])],
            shrines=[
                ShrineJson.deserialize(s) for s in data.get("shrines", [])
            ])

        map_editor_config = MapEditorConfig(
            disable_smart_grid=data.get("disable_smart_grid", False))
        grid_string = data.get("grid", None)

        return MapData(game_state, map_editor_config, grid_string)
Ejemplo n.º 5
0
def main(map_file_name: Optional[str]):
    map_file_path = MAP_DIR + (map_file_name or "map1.json")

    if Path(map_file_path).exists():
        game_state = create_game_state_from_json_file(CAMERA_SIZE,
                                                      map_file_path, HERO_ID)
    else:
        player_entity = create_hero_world_entity(HERO_ID, (0, 0))
        player_state = create_player_state(HERO_ID)
        game_state = GameState(player_entity, [], [], [], [], [], CAMERA_SIZE,
                               Rect(-250, -250, 500, 500), player_state, [],
                               [], [])

    pygame.init()

    pygame_screen = pygame.display.set_mode(SCREEN_SIZE)
    images_by_sprite = load_images_by_sprite(ENTITY_SPRITE_INITIALIZERS)
    images_by_ui_sprite = load_images_by_ui_sprite(UI_ICON_SPRITE_PATHS,
                                                   MAP_EDITOR_UI_ICON_SIZE)
    images_by_portrait_sprite = load_images_by_portrait_sprite(
        PORTRAIT_ICON_SPRITE_PATHS, PORTRAIT_ICON_SIZE)
    world_view = GameWorldView(pygame_screen, CAMERA_SIZE, SCREEN_SIZE,
                               images_by_sprite)
    ui_view = MapEditorView(pygame_screen, CAMERA_SIZE, SCREEN_SIZE,
                            images_by_sprite, images_by_ui_sprite,
                            images_by_portrait_sprite)

    user_state = UserState.deleting_entities()

    is_mouse_button_down = False

    possible_grid_cell_sizes = [25, 50]
    grid_cell_size_index = 0
    grid_cell_size = possible_grid_cell_sizes[grid_cell_size_index]

    camera_move_distance = 75  # must be a multiple of the grid size
    snapped_mouse_screen_position = (0, 0)
    snapped_mouse_world_position = (0, 0)
    exact_mouse_screen_position = (0, 0)
    is_snapped_mouse_within_world = True
    is_snapped_mouse_over_ui = False

    game_state.center_camera_on_player()
    game_state.camera_world_area.topleft = (
        (game_state.camera_world_area.x // grid_cell_size) * grid_cell_size,
        (game_state.camera_world_area.y // grid_cell_size) * grid_cell_size)

    held_down_arrow_keys = set([])
    clock = pygame.time.Clock()
    camera_pan_timer = PeriodicTimer(Millis(50))

    shown_tab = EntityTab.ITEMS

    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN
                                             and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()

            if event.type == pygame.MOUSEMOTION:
                exact_mouse_screen_position: Tuple[int, int] = event.pos
                ui_view.handle_mouse_movement(exact_mouse_screen_position)
                snapped_mouse_screen_position = (
                    (exact_mouse_screen_position[0] // grid_cell_size) *
                    grid_cell_size,
                    (exact_mouse_screen_position[1] // grid_cell_size) *
                    grid_cell_size)
                snapped_mouse_world_position = sum_of_vectors(
                    snapped_mouse_screen_position,
                    game_state.camera_world_area.topleft)
                is_snapped_mouse_within_world = game_state.is_position_within_game_world(
                    snapped_mouse_world_position)
                is_snapped_mouse_over_ui = ui_view.is_screen_position_within_ui(
                    snapped_mouse_screen_position)
                if is_mouse_button_down and is_snapped_mouse_within_world and not is_snapped_mouse_over_ui:
                    if user_state.placing_entity:
                        if user_state.placing_entity.wall_type:
                            _add_wall(game_state, snapped_mouse_world_position,
                                      user_state.placing_entity.wall_type)
                        elif user_state.placing_entity.decoration_sprite:
                            _add_decoration(
                                user_state.placing_entity.decoration_sprite,
                                game_state, snapped_mouse_world_position)
                    elif user_state.deleting_entities:
                        _delete_map_entities_from_position(
                            game_state, snapped_mouse_world_position)
                    else:
                        _delete_map_decorations_from_position(
                            game_state, snapped_mouse_world_position)

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_s:
                    save_file = map_file_path
                    save_game_state_to_json_file(game_state, save_file)
                    print("Saved state to " + save_file)
                elif event.key in [
                        pygame.K_RIGHT, pygame.K_DOWN, pygame.K_LEFT,
                        pygame.K_UP
                ]:
                    held_down_arrow_keys.add(event.key)
                elif event.key == pygame.K_q:
                    user_state = UserState.deleting_entities()
                elif event.key == pygame.K_z:
                    user_state = UserState.deleting_decorations()
                elif event.key == pygame.K_PLUS:
                    grid_cell_size_index = (grid_cell_size_index +
                                            1) % len(possible_grid_cell_sizes)
                    grid_cell_size = possible_grid_cell_sizes[
                        grid_cell_size_index]
                elif event.key == pygame.K_v:
                    shown_tab = EntityTab.ITEMS
                elif event.key == pygame.K_b:
                    shown_tab = EntityTab.NPCS
                elif event.key == pygame.K_n:
                    shown_tab = EntityTab.WALLS
                elif event.key == pygame.K_m:
                    shown_tab = EntityTab.MISC

            if event.type == pygame.KEYUP:
                if event.key in held_down_arrow_keys:
                    held_down_arrow_keys.remove(event.key)

            if event.type == pygame.MOUSEBUTTONDOWN:
                ui_view.handle_mouse_click()
                is_mouse_button_down = True
                if user_state.placing_entity:
                    entity_being_placed = user_state.placing_entity
                    if is_snapped_mouse_within_world and not is_snapped_mouse_over_ui:
                        if entity_being_placed.is_player:
                            game_state.player_entity.set_position(
                                snapped_mouse_world_position)
                        elif entity_being_placed.npc_type:
                            _add_npc(entity_being_placed.npc_type, game_state,
                                     snapped_mouse_world_position)
                        elif entity_being_placed.wall_type:
                            _add_wall(game_state, snapped_mouse_world_position,
                                      entity_being_placed.wall_type)
                        elif entity_being_placed.consumable_type:
                            _add_consumable(
                                entity_being_placed.consumable_type,
                                game_state, snapped_mouse_world_position)
                        elif entity_being_placed.item_type:
                            _add_item(entity_being_placed.item_type,
                                      game_state, snapped_mouse_world_position)
                        elif entity_being_placed.decoration_sprite:
                            _add_decoration(
                                entity_being_placed.decoration_sprite,
                                game_state, snapped_mouse_world_position)
                        elif entity_being_placed.money_amount:
                            _add_money(entity_being_placed.money_amount,
                                       game_state,
                                       snapped_mouse_world_position)
                        elif entity_being_placed.portal_id:
                            _add_portal(entity_being_placed.portal_id,
                                        game_state,
                                        snapped_mouse_world_position)
                        elif entity_being_placed.is_chest:
                            _add_chest(game_state,
                                       snapped_mouse_world_position)
                        else:
                            raise Exception("Unknown entity: " +
                                            str(entity_being_placed))
                elif user_state.deleting_entities:
                    _delete_map_entities_from_position(
                        game_state, snapped_mouse_world_position)
                else:
                    _delete_map_decorations_from_position(
                        game_state, snapped_mouse_world_position)

            if event.type == pygame.MOUSEBUTTONUP:
                is_mouse_button_down = False

        clock.tick()
        time_passed = clock.get_time()

        if camera_pan_timer.update_and_check_if_ready(time_passed):
            if pygame.K_RIGHT in held_down_arrow_keys:
                game_state.translate_camera_position((camera_move_distance, 0))
            if pygame.K_LEFT in held_down_arrow_keys:
                game_state.translate_camera_position(
                    (-camera_move_distance, 0))
            if pygame.K_DOWN in held_down_arrow_keys:
                game_state.translate_camera_position((0, camera_move_distance))
            if pygame.K_UP in held_down_arrow_keys:
                game_state.translate_camera_position(
                    (0, -camera_move_distance))

        entities_to_render = game_state.get_all_entities_to_render()
        decorations_to_render = game_state.get_decorations_to_render()
        world_view.render_world(
            all_entities_to_render=entities_to_render,
            decorations_to_render=decorations_to_render,
            player_entity=game_state.player_entity,
            is_player_invisible=game_state.player_state.is_invisible,
            player_active_buffs=game_state.player_state.active_buffs,
            camera_world_area=game_state.camera_world_area,
            non_player_characters=game_state.non_player_characters,
            visual_effects=game_state.visual_effects,
            render_hit_and_collision_boxes=ui_view.
            checkbox_show_entity_outlines.checked,
            player_health=game_state.player_state.health_resource.value,
            player_max_health=game_state.player_state.health_resource.
            max_value,
            entire_world_area=game_state.entire_world_area,
            entity_action_text=None)

        camera_world_area = game_state.camera_world_area
        world_area = game_state.entire_world_area
        camera_rect_ratio = ((camera_world_area.x - world_area.x) /
                             world_area.w,
                             (camera_world_area.y - world_area.y) /
                             world_area.h, camera_world_area.w / world_area.w,
                             camera_world_area.h / world_area.h)

        npc_positions_ratio = [
            ((npc.world_entity.x - world_area.x) / world_area.w,
             (npc.world_entity.y - world_area.y) / world_area.h)
            for npc in game_state.non_player_characters
        ]
        wall_positions_ratio = [
            ((wall.world_entity.x - world_area.x) / world_area.w,
             (wall.world_entity.y - world_area.y) / world_area.h)
            for wall in game_state.walls_state.walls
        ]

        if shown_tab == EntityTab.ITEMS:
            shown_entities = ITEM_ENTITIES
        elif shown_tab == EntityTab.NPCS:
            shown_entities = NPC_ENTITIES
        elif shown_tab == EntityTab.WALLS:
            shown_entities = WALL_ENTITIES
        elif shown_tab == EntityTab.MISC:
            shown_entities = MISC_ENTITIES
        else:
            raise Exception("Unknown entity tab: " + str(shown_tab))

        ui_view.set_shown_tab(shown_tab)

        entity_icon_hovered_by_mouse = ui_view.render(
            entities=shown_entities,
            placing_entity=user_state.placing_entity,
            deleting_entities=user_state.deleting_entities,
            deleting_decorations=user_state.deleting_decorations,
            num_enemies=len(game_state.non_player_characters),
            num_walls=len(game_state.walls_state.walls),
            num_decorations=len(
                game_state.decorations_state.decoration_entities),
            grid_cell_size=grid_cell_size,
            mouse_screen_position=exact_mouse_screen_position,
            camera_rect_ratio=camera_rect_ratio,
            npc_positions_ratio=npc_positions_ratio,
            wall_positions_ratio=wall_positions_ratio)

        if is_mouse_button_down and entity_icon_hovered_by_mouse:
            user_state = UserState.placing_entity(entity_icon_hovered_by_mouse)

        if is_snapped_mouse_over_ui:
            pass
            # render nothing over UI
        elif not is_snapped_mouse_within_world:
            snapped_mouse_rect = Rect(snapped_mouse_screen_position[0],
                                      snapped_mouse_screen_position[1],
                                      grid_cell_size, grid_cell_size)
            ui_view.render_map_editor_mouse_rect((250, 50, 0),
                                                 snapped_mouse_rect)
        elif user_state.placing_entity:
            entity_being_placed = user_state.placing_entity
            ui_view.render_map_editor_world_entity_at_position(
                entity_being_placed.sprite, entity_being_placed.entity_size,
                snapped_mouse_screen_position)
        elif user_state.deleting_entities:
            snapped_mouse_rect = Rect(snapped_mouse_screen_position[0],
                                      snapped_mouse_screen_position[1],
                                      grid_cell_size, grid_cell_size)
            ui_view.render_map_editor_mouse_rect((250, 250, 0),
                                                 snapped_mouse_rect)
        elif user_state.deleting_decorations:
            snapped_mouse_rect = Rect(snapped_mouse_screen_position[0],
                                      snapped_mouse_screen_position[1],
                                      grid_cell_size, grid_cell_size)
            ui_view.render_map_editor_mouse_rect((0, 250, 250),
                                                 snapped_mouse_rect)
        else:
            raise Exception("Unhandled user_state: " + str(user_state))

        pygame.display.update()