class Scene_Level(Scene):
    def __init__(self, game):
        Scene.__init__(self, game)

    def init(self):
        self.scrollablePosition = [0, 0]
        self.scrollableSize = [480, 240]
        self.map = Map(self.game, 'map.tmx')
        self.game.map = self.map
        self.scrollableLayer = ScrollableLayer(self.game,
                                               self.scrollablePosition,
                                               self.scrollableSize, [0, 0],
                                               self.map.size)
        self.game.scrollableLayer = self.scrollableLayer
        self.units = []
        self.units.append(Unit(self.game, [96, 64]))
        self.units.append(Unit(self.game, [96, 96]))
        self.units.append(Unit(self.game, [96, 128]))
        self.units.append(Unit(self.game, [96, 160]))
        self.ui = UI(self.game)

    def endTurn(self):
        for unit in self.units:
            unit.endTurn()

    def update(self, deltaTime, events):
        scrollSpeed = 32 * deltaTime
        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP] or self.game.cursor.bounds['top']:
            self.scrollableLayer.changeOffsetBy([0, 1 * scrollSpeed])
        if keys[pygame.K_DOWN] or self.game.cursor.bounds['bottom']:
            self.scrollableLayer.changeOffsetBy([0, -1 * scrollSpeed])
        if keys[pygame.K_LEFT] or self.game.cursor.bounds['left']:
            self.scrollableLayer.changeOffsetBy([1 * scrollSpeed, 0])
        if keys[pygame.K_RIGHT] or self.game.cursor.bounds['right']:
            self.scrollableLayer.changeOffsetBy([-1 * scrollSpeed, 0])

        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.endTurn()

        self.map.update(deltaTime, events)
        for unit in self.units:
            unit.update(deltaTime, events)
        self.scrollableLayer.update(deltaTime, events)
        self.ui.update(deltaTime, events)

    def draw(self, screen):
        self.map.draw(self.scrollableLayer.virtualSurface)
        for unit in self.units:
            unit.draw(self.scrollableLayer.virtualSurface)
        self.scrollableLayer.draw(screen)
        self.ui.draw(screen)
Ejemplo n.º 2
0
class Game:
    def __init__(self):
        pygame.init()
        self.w, self.h = 1000, 800
        self.win = pygame.display.set_mode((self.w, self.h))
        self.board = Board(5, 5, 790, 790, self)
        self.ui = UI(800, 5, 195, 790)
        self.ui.create_panel(self)
        self.mouse_position = (0, 0)
        self.mouse_button_down = False

    def run(self):
        clock = pygame.time.Clock()
        while True:
            dt = clock.tick(30)
            self.board.elapsedTime += dt / 1000
            self.mouse_position = pygame.mouse.get_pos()
            self.mouse_button_down = False

            self.win.fill((150, 150, 150))
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    quit()

                if event.type == MOUSEBUTTONDOWN:

                    self.mouse_button_down = True

                    if self.board.HasPieceMouse(self.mouse_position[0],
                                                self.mouse_position[1]):
                        self.board.GetPieceMouse(self.mouse_position[0],
                                                 self.mouse_position[1])
                    else:
                        self.board.UnselectCase()

            self.board.draw()
            self.ui.draw(self)
            pygame.display.update()
Ejemplo n.º 3
0
class SnakeGame:
    """
    Main game class
    """
    def __init__(self, s_width, s_height, setup):
        """
        Initialize the game starting in main menu
        Args:
            s_width (int): screen_width
            s_width (int): screen_height
            setup (Setup[]): list of setup options:
                Desktop: default option. in this mode everything is controlled by keyboard
                Arcade: prevents user from quiting the game from ui and changing key bindings
                        in this mode both the game and ui are controlled by joysticks
                Windowed: default option. Uses s_width and s_height to determine screen dimensions
                Fullscreen: ignores s_width and s_height args and enables fullscreen (duh)
        """
        pygame.init()
        pygame.font.init()

        self.arcade = False
        fullscreen = False
        for opt in setup:
            if opt == Setup.Arcade:
                self.arcade = True
            elif opt == Setup.Fullscreen:
                fullscreen = True

        self.joysticks = [
            pygame.joystick.Joystick(x)
            for x in range(pygame.joystick.get_count())
        ]
        for j in self.joysticks:
            j.init()

        self.display = Display((s_width, s_height), fullscreen)
        self.clock = pygame.time.Clock()
        self.FPS = 60

        self.ui = UI(self.display)
        if self.arcade:
            if len(self.joysticks) == 0:
                print(
                    "=================== plug in the controller ==================="
                )
                exit(1)
            self.ui.enable_arcade_mode()

        self.selected_speed = "speed Medium"
        self.game_manager = GameManager(self.display, self.ui,
                                        GameMode.EatToGrow, GameState.Menu)

    def start_new_game(self, mode):
        """
        Start a new game
        Args:
            Mode (GameMode): selected game mode
                InfiniteSnake: snakes dont shrink and there are no pickups
                EatToGrow: snakes shrink to preserve constant length. players
                            can eat pickups to grow in length and speed up
                EatToSurvive = snakes shrink and their length decrease in time.
                            players have to eat pickups to stay alive
        """
        self.display.clear()
        #self.ui.hide()
        if self.selected_speed == "speed Slow":
            self.game_manager.set_players_speed(1.9)
        elif self.selected_speed == "speed Medium":
            self.game_manager.set_players_speed(3)
        elif self.selected_speed == "speed Fast":
            self.game_manager.set_players_speed(5)
        self.game_manager = GameManager(self.display, self.ui, mode,
                                        GameState.Running,
                                        self.game_manager.player1,
                                        self.game_manager.player2)

    def handle_events(self):
        """
        Invoke handlers for desired events during game
        """
        keys = pygame.key.get_pressed()
        if self.game_manager.game_state == GameState.Running:
            if self.arcade:
                self.game_manager.control_players_arcade(self.joysticks)
            else:
                self.game_manager.control_players(keys)
        elif self.arcade:
            self.ui.arcade_control(self.joysticks[1])

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.game_manager.game_state = GameState.Quit
            if self.game_manager.game_state == GameState.Finished or\
            self.game_manager.game_state == GameState.Menu :
                if event.type == pygame.KEYDOWN and not self.arcade:
                    self.ui.control(event.key)
                    #self.start_new_game(GameMode.EatToSurvive)

    def handle_ui_response(self):
        """
        Handle user actions performed in the interface
        """
        option = self.ui.get_selected_option()

        #main menu
        if option == "Play":
            #self.game_manager.game_state = GameState.Menu
            pass
        elif option == "Quit":
            self.ui.hide()
            self.game_manager.game_state = GameState.Quit

        #settings menu
        elif option == "p1 Absolute":
            self.game_manager.player1.steering_mode = "absolute"
        elif option == "p1 Relative":
            self.game_manager.player1.steering_mode = "relative"
        elif option == "p2 Absolute":
            self.game_manager.player2.steering_mode = "absolute"
        elif option == "p2 Relative":
            self.game_manager.player2.steering_mode = "relative"
        elif option == "P1 Key Bindings":
            self.ui.load_controls(self.game_manager.player1.controls)
        elif option == "P2 Key Bindings":
            self.ui.load_controls(self.game_manager.player2.controls)

        #key bindings menu
        elif option == "Apply":
            if self.ui.currently_changed_player == "p1":
                self.game_manager.player1.controls = self.ui.loaded_player_controls
            elif self.ui.currently_changed_player == "p2":
                self.game_manager.player2.controls = self.ui.loaded_player_controls

        #speed menu
        elif option == "speed Slow" or option == "speed Medium" or option == "speed Fast":
            self.selected_speed = option

        #play menu
        elif option == "Standard":
            self.start_new_game(GameMode.EatToGrow)
        elif option == "Infinite":
            self.start_new_game(GameMode.InfiniteSnake)
        elif option == "Starve":
            self.start_new_game(GameMode.EatToSurvive)

        #endgame menu
        elif option == "Play Again":
            self.start_new_game(self.game_manager.game_mode)
        elif option == "Return to main menu":
            self.game_manager.game_state = GameState.Menu

    def render_scene(self):
        """
        Draw objects onto the screen. 
        All the rendering is done here
        """
        if self.game_manager.game_state == GameState.Running or\
        self.game_manager.game_state == GameState.Finished:
            self.display.erase_points()
            self.game_manager.draw_players()

        self.ui.draw()
        pygame.display.flip()
        # if self.game_manager.game_state == GameState.Finished:
        #     time.sleep(0.5)

    def cleanup(self):
        """
        Cleanup after the game has ended
        """
        pygame.quit()

    def main_loop(self):
        """
        Main loop of the game. 
        """
        while self.game_manager.game_state != GameState.Quit:

            self.handle_events()
            self.handle_ui_response()
            #in menu
            if self.game_manager.game_state == GameState.Menu:
                self.display.clear()

            #in game
            elif self.game_manager.game_state == GameState.Running:
                self.game_manager.move_players()

            #after game
            elif self.game_manager.game_state == GameState.Finished:
                if self.game_manager.winner == None:
                    self.game_manager.player1.decay()
                    self.game_manager.player2.decay()
                else:
                    self.game_manager.loser.decay()
                    self.game_manager.loser.draw()

            #perform game manager actions
            self.game_manager.act()
            #do all the rendering stuff
            self.render_scene()
            #control FPS
            self.clock.tick(self.FPS)
Ejemplo n.º 4
0
class Game:
    def __init__(self):
        # fps stuff
        self.print_fps = True
        self.fps_max = 0
        self.fps_min = 100000
        self.avg_fps = []
        self._draw_map_grid = False

        # system stuff
        self.screen = None
        self.clock = None
        self.pygame_init()
        self.running = True
        self.game_tic = 0
        self.move_tic = 0
        pygame.event.set_blocked(None)
        pygame.event.set_allowed([
            pygame.KEYUP, pygame.KEYDOWN, pygame.MOUSEBUTTONDOWN,
            pygame.MOUSEBUTTONUP, pygame.QUIT, pygame.MOUSEMOTION
        ])
        self.image_loader = Image()
        self.paused = False
        self.paused_movement_buffer = []

        # map stuff
        self.get_current_map()

        # player stuff
        player_spawn = self.current_map.get_player_spawn_pos()
        self.can_move = False
        self.player = Player(player_spawn, ZERO_VECTOR)
        self.player.set_walls(
            self.current_map.get_walls())  # TODO don't like this
        self.smooth_move_list = self.player.get_smooth_movement(
        )  # TODO change to be hooked to viewable object
        self.directions = {LEFT: False, RIGHT: False, UP: False, DOWN: False}
        self.player_inventory = PlayerInventory()

        # viewable stuff
        self.bounds = {
            LEFT: WIDTH // 4,
            RIGHT: WIDTH // 2,
            UP: HEIGHT // 4,
            DOWN: HEIGHT // 2
        }
        self.bounding_rect = pygame.Rect(self.bounds[LEFT], self.bounds[UP],
                                         self.bounds[RIGHT], self.bounds[DOWN])
        self.camera_object = self.create_view_object()
        self.offset_value = (0, 0)
        self.need_to_redraw = True

        # UI stuff
        self.fade = Fade()
        self.ui = UI()
        self.menu_screen = MenuScreen()
        self.menu_is_open = False
        self.need_mouse_movement = False
        self.mouse_held = False
        self.inv_pickup = None
        self.inv_drop = None

    def update(self):
        self.get_events()
        self.update_player()
        self.check_bounds()  # todo move to other method with smooth scrolling
        self.smooth_scrolling()  # TODO
        self.get_fps()
        self.ui.update()
        if self.menu_is_open:
            self.menu_screen.update()

    def draw(self):
        self.check_redraw()
        self.get_offset()
        if not self.menu_is_open:
            self.draw_map()
            self.draw_ui()
            if self._draw_map_grid:  # TODO remove after testing
                self.draw_map_grid()
            # self.fade.draw()
            self.player.draw()
        if self.menu_is_open:
            self.menu_screen.draw()

        pygame.display.update()
        self.clock.tick(TIC_RATE)
        self.game_tic += 1
        self.player.get_game_tic(
            self.game_tic)  # TODO do a better way of giving player game tic
        self.need_to_redraw = True  # TODO change to false after testing

    def draw_ui(self):
        self.ui.draw()
        _ = self.player_inventory.get_images_for_ui()
        if _ is not None:
            self.ui.set_inventory_images(_)

    def open_menu(self):
        self.paused_movement_buffer = self.player.movement_input
        self.paused = True
        self.menu_is_open = True

    def close_menu(self):
        self.player.movement_input = self.paused_movement_buffer
        self.paused = False
        self.menu_is_open = False

    def get_events(self):
        _movement = None
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.stop_running()
            if event.type == pygame.KEYDOWN:
                _movement = self.key_down_event(_movement, event)

            elif event.type == pygame.KEYUP:
                _movement = self.key_up_event(_movement, event)

            elif event.type == pygame.MOUSEBUTTONDOWN:
                self.mouse_button_down_event(event)

            elif event.type == pygame.MOUSEBUTTONUP:

                self.mouse_button_up_event(event)

            if self.need_mouse_movement:
                if event.type == pygame.MOUSEMOTION:
                    self.mouse_motion_event(event)

    def key_down_event(self, _movement, event):
        if event.key == pygame.K_d:
            _movement = Directions.RIGHT.value
        elif event.key == pygame.K_a:
            _movement = Directions.LEFT.value
        elif event.key == pygame.K_w:
            _movement = Directions.UP.value
        elif event.key == pygame.K_s:
            _movement = Directions.DOWN.value
        if event.key == pygame.K_ESCAPE:
            if not self.menu_is_open:
                self.open_menu()
            else:
                self.close_menu()
        if event.key == pygame.K_i:
            self.ui.inventory_visible = not self.ui.inventory_visible
            self.need_mouse_movement = not self.need_mouse_movement  # TODO do this differently.
        if self.paused:
            if _movement:  # todo refactor this. it's messy and has repeating code
                if _movement not in self.paused_movement_buffer:
                    self.paused_movement_buffer.append(_movement)
            _movement = None
            self.player.movement_input = ["still"]
        if _movement:
            if _movement not in self.player.movement_input:
                self.player.add_movement_input(_movement)
        return _movement

    def key_up_event(self, _movement, event):
        if event.key == pygame.K_d:
            _movement = Directions.RIGHT.value
        elif event.key == pygame.K_a:
            _movement = Directions.LEFT.value
        elif event.key == pygame.K_w:
            _movement = Directions.UP.value
        elif event.key == pygame.K_s:
            _movement = Directions.DOWN.value
        if self.paused:
            if _movement:
                if _movement in self.paused_movement_buffer:
                    self.paused_movement_buffer.remove(_movement)
            _movement = None
        if _movement:
            if _movement in self.player.movement_input:
                self.player.remove_movement_input(_movement)
        return _movement

    def mouse_button_down_event(self, event):
        self.inv_pickup = (event.pos[0] - STEP // 2) // 32, (
            event.pos[1] - STEP // 2 - STEP) // 32
        inv_clicked = self.ui.ui_clicked(event.pos)
        if inv_clicked and self.inv_pickup in self.player_inventory.inventory.filled_cells:
            self.mouse_held = True
        else:
            self.inv_pickup = None

    def mouse_button_up_event(self, event):
        self.inv_drop = (event.pos[0] - STEP // 2) // 32, (
            event.pos[1] - STEP // 2 - STEP) // 32
        if self.inv_pickup and self.inv_drop:
            self.player_inventory.move_item(self.inv_pickup, self.inv_drop)
        self.mouse_held = False
        self.inv_pickup = None
        self.inv_drop = None

    def mouse_motion_event(self, event):
        if self.mouse_held:
            self.ui.inventory.add_image_offset(
                self.inv_pickup,
                (event.pos[0] - 16 - 16 - (self.inv_pickup[0] * 32),
                 event.pos[1] - 32 - 16 - 16 - (self.inv_pickup[1] * 32)))
        ui_hovering = self.ui.ui_hovering(event.pos)
        if ui_hovering is not None:
            if ui_hovering[1] == "inventory":  # TODO make constant
                item = self.player_inventory.get_item(ui_hovering[0])
                if item:
                    self.ui.inventory.make_info_box(item, event.pos)
                else:
                    self.ui.inventory.reset_info_box()
        else:
            self.ui.inventory.reset_info_box()

    def pygame_init(self):
        self.screen = pygame.display.get_surface()
        self.clock = pygame.time.Clock()

    def update_player(self):
        self.player.set_offset(self.offset_value)
        self.player.update()

    def draw_moving_tiles(self):
        self.current_map.draw_single_tile(self.player.get_stood_tile(),
                                          self.offset_value)
        self.current_map.draw_single_tile(self.player.get_facing_tile(),
                                          self.offset_value)
        self.current_map.draw_single_tile(self.player.get_behind_tile(),
                                          self.offset_value)

    def draw_map(self):
        if self.need_to_redraw:
            self.current_map.draw(self.offset_value)
        else:
            self.draw_moving_tiles()

    def get_offset(self):
        self.offset_value = self.camera_object.get_offset()

    def check_bounds(self):
        if self.player.pos[0] + self.offset_value[0] < self.bounding_rect.left:
            self.directions[LEFT] = True
        elif self.player.pos[0] + self.offset_value[
                0] > self.bounding_rect.right:
            self.directions[RIGHT] = True
        if self.player.pos[1] + self.offset_value[1] < self.bounding_rect.top:
            self.directions[UP] = True
        elif self.player.pos[1] + self.offset_value[
                1] > self.bounding_rect.bottom:
            self.directions[DOWN] = True

    def check_redraw(self):
        if self.camera_object.check_if_offset_changed(self.offset_value):
            self.need_to_redraw = True

    def smooth_map_scrolling(self):
        if self.player.is_moving():
            if self.directions[RIGHT]:
                self.move_cycle(-self.smooth_move_list[self.move_tic], 0)
            elif self.directions[LEFT]:
                self.move_cycle(self.smooth_move_list[self.move_tic], 0)
            if self.directions[DOWN]:
                self.move_cycle(0, -self.smooth_move_list[self.move_tic])
            elif self.directions[UP]:
                self.move_cycle(0, self.smooth_move_list[self.move_tic])
            self.tic_cycle()

    def smooth_scrolling(self):
        if any(list(self.directions.values())):
            self.smooth_map_scrolling()
        else:
            self.smooth_player_scrolling()
        self.reset_directions()

    def smooth_player_scrolling(self):
        if self.player.is_moving():
            self.tic_cycle()

    def reset_directions(self):
        for key in self.directions.keys():
            self.directions[key] = False

    def tic_cycle(self):
        self.move_tic += 1

        if self.move_tic == self.player.get_speed():
            self.move_tic = 0

        self.player.update_move_tic(self.move_tic)

    def move_cycle(self, x=0, y=0):
        self.camera_object.shift(x, y)

    def get_current_map(self):
        self.current_map = Map01()  # TODO get from file

    def is_running(self):
        return self.running

    def stop_running(self):
        self.running = False

    def start_running(self):
        self.running = True

    def create_view_object(self):
        return View(self.current_map, self.player,
                    *self.current_map.camera_pos)

    def get_fps(self):
        fps = self.clock.get_fps()
        self.avg_fps.append(fps)
        if len(self.avg_fps) > 1000:
            del (self.avg_fps[0])
        avg = sum(self.avg_fps) // (len(self.avg_fps))
        self.fps_max = max(self.fps_max, fps)
        _min = min(self.fps_min, fps)
        if _min:
            self.fps_min = _min
        if self.print_fps:
            pygame.display.set_caption(
                f'fps: avg={avg:.0f} current={fps:.0f} min={self.fps_min:.0f},'
                f' max={self.fps_max:.0f}  TIC={self.game_tic}')

    def draw_map_grid(self):
        # for testing only. delete after testing
        for i in range(WIDTH // STEP):
            pygame.draw.line(self.screen, (0, 0, 0), (i * STEP, 0),
                             (i * STEP, HEIGHT), 1)
        for i in range(HEIGHT // STEP):
            pygame.draw.line(self.screen, (0, 0, 0), (0, i * STEP),
                             (WIDTH, i * STEP), 1)