Beispiel #1
0
        def __init__(self, game_engine: 'GameEngine'):
            self._game_map = game_engine._game_map
            self._keys_pressed = game_engine._keys_pressed
            self._collisions_processor = CollisionsProcessor(
                game_engine._game_map)

            self._player_is_on_the_ground = False
            self._vertical_velocity = 0

            self._PMS_gb_multiplier = 1
            self._IJV_gb_multiplier = 1

            self._get_game_loop_iterations_count = (
                game_engine.get_map_updates_count)
    def test_unknown_moving_object_exception(self):
        with self.assertRaises(CollisionsProcessorException) as occurred_exc:
            CollisionsProcessor(test_map_1).get_collisions(
                MovableObject(Vector2D(0, 0)), Vector2D(0, 0))

        assert len(occurred_exc.exception.args) == 1
        assert occurred_exc.exception.args[0] == (
            'While processing [get_collisions] method, got [moving_object] '
            'with unknown type: MovableObject')
    def test_player_buff_collision(self):
        collisions: List[Collision] = (
            CollisionsProcessor(test_map_2).get_collisions(
                test_map_2.movable_objects[0], Vector2D(30, 30)))

        self.assertEqual(1, len(collisions))
        self.assertEqual(GameEvent.PLAYER_BUFF, collisions[0].game_event)
        self.assertEqual(test_map_2.immovable_objects[0],
                         collisions[0].collided_object)
        self.assertEqual(test_map_2.movable_objects[0],
                         collisions[0].moving_object)
    def test_bottom_border_collision(self):
        bottom_border_collision: List[Collision] = (
            CollisionsProcessor(test_map_1).get_collisions(
                test_map_1.movable_objects[0], Vector2D(0, 200)))

        self.assertEqual(1, len(bottom_border_collision))

        assert (bottom_border_collision[0].game_event is
                GameEvent.PLAYER_BORDERS_BOTTOM)
        assert (bottom_border_collision[0].moving_object is
                test_map_1.movable_objects[0])
        assert bottom_border_collision[0].collided_object is None
    def test_left_border_collision(self):
        left_border_collision: List[Collision] = (
            CollisionsProcessor(test_map_1).get_collisions(
                test_map_1.movable_objects[0], Vector2D(-200, 0)))

        self.assertEqual(1, len(left_border_collision))

        assert (left_border_collision[0].game_event is
                GameEvent.PLAYER_BORDERS_LEFT)
        assert (left_border_collision[0].moving_object is
                test_map_1.movable_objects[0])
        assert left_border_collision[0].collided_object is None
    def test_player_basic_platform_collision(self):
        collisions: List[Collision] = (
            CollisionsProcessor(test_map_3).get_collisions(
                test_map_3.movable_objects[0], Vector2D(20, 20)))

        self.assertEqual(1, len(collisions))
        self.assertEqual(GameEvent.PLAYER_TOP_BASIC_PLATFORM,
                         collisions[0].game_event)
        self.assertEqual(test_map_3.movable_objects[0],
                         collisions[0].moving_object)
        self.assertEqual(test_map_3.immovable_objects[0],
                         collisions[0].collided_object)
    def test_no_borders_collisions(self):
        no_border_collision: List[Collision] = (
            CollisionsProcessor(test_map_1).get_collisions(
                test_map_1.movable_objects[0], Vector2D(0, 10)))

        self.assertEqual(0, len(no_border_collision))
Beispiel #8
0
    class _StateUpdater(EventListener):
        # Improvement: Relocate some global vars from here to game
        #  objects' classes. E.g., [_PLAYER_MOVE_SPEED] -> [Player]

        # Improvement: Realize 'space' pressing with [EventListener]
        #  implementation when pressing switches 'space_was_pressed' flag?

        _KEY_CODE_A: int = 65
        _KEY_CODE_D: int = 68
        _KEY_CODE_SPACE: int = 32

        # Improvement: Add lock because 'set' operation below is NOT
        #  atomic! Note that it is NOT needed to pass lock into gui,
        #  because gui already invokes methods here. Right here,
        #  in [EventListener] implementation, lock should be used
        _keys_pressed: Set[int]

        # Constant move speed with global multiplier
        _PLAYER_MOVE_SPEED: int = 6
        _PMS_gb_multiplier: float

        _GRAVITY_ACCELERATION: Vector2D = Vector2D(0, 2.5)
        _MAX_VERTICAL_VELOCITY: float = 12

        # Constant initial jump velocity with global multiplier
        _INITIAL_JUMP_VELOCITY: float = -25
        _IJV_gb_multiplier: float

        _collisions_processor: CollisionsProcessor

        _game_map: GameMap

        # If so then main [Player] can jump
        #
        # Optimization: When [Player] is on the ground then no
        #  collisions with the ground should be initiated
        _player_is_on_the_ground: bool

        _vertical_velocity: float

        _get_game_loop_iterations_count: Callable[[], int]

        def __init__(self, game_engine: 'GameEngine'):
            self._game_map = game_engine._game_map
            self._keys_pressed = game_engine._keys_pressed
            self._collisions_processor = CollisionsProcessor(
                game_engine._game_map)

            self._player_is_on_the_ground = False
            self._vertical_velocity = 0

            self._PMS_gb_multiplier = 1
            self._IJV_gb_multiplier = 1

            self._get_game_loop_iterations_count = (
                game_engine.get_map_updates_count)

        def update_movable_objects_states(self):
            self._refresh_global_movement_multipliers()

            for movable_object in self._game_map.movable_objects:
                if isinstance(movable_object, Player):
                    self._update_player_state(movable_object)

                elif isinstance(movable_object, ProjectileObject):
                    self._update_projectile_state(movable_object)

                else:
                    GameEngineException(
                        "While processing [update_movable_objects_states] "
                        "method, got [movable_object] with unknown type: " +
                        movable_object.__class__.__name__)

        def _update_projectile_state(
                self, projectile: ProjectileObject):  # pragma: no cover
            collisions: List[Collision] = (
                self._collisions_processor.get_collisions(
                    projectile, projectile.moving_vector))

            for collision in collisions:
                self._process_projectile_collision(projectile, collision)

            if not projectile.should_be_despawned:
                projectile.location += projectile.moving_vector

        @staticmethod
        def _process_projectile_collision(
                projectile: ProjectileObject,
                collision: Collision):  # pragma: no cover
            if collision.collided_object is None:
                if collision.game_event is GameEvent.PROJECTILE_IS_OUT:
                    projectile.should_be_despawned = True
                else:
                    raise GameEngineException(
                        '[_process_projectile_collision] switch got '
                        'wrong [collision]', '[collided_object] -> [None]',
                        '(UNKNOWN) [game_event] -> ' + '[' +
                        collision.game_event.name + ']')

            else:
                raise GameEngineException(
                    '[_process_projectile_collision] switch got '
                    'wrong [collision]', '(UNKNOWN) [collided_object] -> ' +
                    '[' + collision.collided_object.__class__.__name__ + ']')

        def _refresh_global_movement_multipliers(self):
            self._PMS_gb_multiplier = self._IJV_gb_multiplier = 1

        def _update_player_state(self, player: Player):  # pragma: no cover
            self._check_player_buffs(player)

            # Copy in case if '_keys_pressed' will be modified during check
            keys_pressed_copy: Set[int] = set(self._keys_pressed)
            player_move_vector: Vector2D = Vector2D(0, 0)

            player_move_vector.x += self._get_horizontal_velocity(
                keys_pressed_copy)
            player_move_vector.y += self._get_vertical_velocity(
                keys_pressed_copy)

            if player_move_vector.x != 0 or player_move_vector.y != 0:
                player_collisions: List[Collision] = (
                    self._collisions_processor.get_collisions(
                        player, player_move_vector))

                for collision in player_collisions:
                    self._process_player_collision(player, collision,
                                                   player_move_vector)

                if player_move_vector.y != 0:
                    self._player_is_on_the_ground = False

                player.location += player_move_vector

        def _process_player_collision(
                self, player: Player, collision: Collision,
                player_move_vector: Vector2D):  # pragma: no cover
            if collision.collided_object is None:
                if (collision.game_event is GameEvent.PLAYER_BORDERS_RIGHT):
                    player_move_vector.x = 0
                    player.location.x = (
                        self._game_map.game_field_size.x
                        # '+ 1' for closest to border drawing
                        - Player.SIDE_LENGTH + 1)

                elif (collision.game_event is GameEvent.PLAYER_BORDERS_LEFT):
                    player_move_vector.x = 0
                    player.location.x = 0

                elif (collision.game_event is GameEvent.PLAYER_BORDERS_BOTTOM):
                    player_move_vector.y = 0

                    # Teleport Player close to game borders
                    player.location.y = (self._game_map.game_field_size.y -
                                         Player.SIDE_LENGTH + 1)

                    self._player_is_on_the_ground = True

                elif (collision.game_event is GameEvent.PLAYER_BORDERS_TOP):
                    player_move_vector.y = 0
                    player.location.y = 0

                else:
                    raise PlayerCollisionsSwitchError(
                        '[collided_object] is [None], [game_event] is '
                        'unknown', collision.game_event.name)

            elif isinstance(collision.collided_object, AbstractBuff):
                if collision.game_event is GameEvent.PLAYER_BUFF:
                    collision.collided_object.capture_this_buff(
                        self._get_game_loop_iterations_count(), player)
                else:
                    raise PlayerCollisionsSwitchError(
                        '[collided_object] is instance of [AbstractBuff], '
                        '[game_event] is unknown', collision.game_event.name)

            elif isinstance(collision.collided_object, BasicPlatform):
                if (collision.game_event is
                        GameEvent.PLAYER_TOP_BASIC_PLATFORM):
                    player_move_vector.y = 0

                    player.location.y = (collision.collided_object.location.y +
                                         collision.collided_object.height + 1)

                elif (collision.game_event is
                      GameEvent.PLAYER_BOTTOM_BASIC_PLATFORM):
                    player_move_vector.y = 0

                    player.location.y = (collision.collided_object.location.y -
                                         Player.SIDE_LENGTH - 1)

                    self._player_is_on_the_ground = True

                elif (collision.game_event is
                      GameEvent.PLAYER_RIGHT_BASIC_PLATFORM):
                    player_move_vector.x = 0

                    player.location.x = (collision.collided_object.location.x -
                                         Player.SIDE_LENGTH - 1)

                elif (collision.game_event is
                      GameEvent.PLAYER_LEFT_BASIC_PLATFORM):
                    player_move_vector.x = 0

                    player.location.x = (collision.collided_object.location.x +
                                         collision.collided_object.width + 1)

                else:
                    raise PlayerCollisionsSwitchError(
                        '[collided_object] is instance of [BasicPlatform],'
                        '[game_event] is unknown', collision.game_event.name)

            else:
                raise PlayerCollisionsSwitchError(
                    "[collided_object] is unknown",
                    collision.collided_object.__class__.__name__)

        def _check_player_buffs(self, player: Player):
            for buff in player.current_buffs:
                if isinstance(buff, SpeedUpBuff):
                    self._PMS_gb_multiplier = 2

                elif isinstance(buff, JumpHeightUpBuff):
                    self._IJV_gb_multiplier = 1.5

                else:
                    raise GameEngineException(
                        "[_check_player_buffs] method got [buff] with "
                        "unknown type: " + buff.__class__.__name__)

        def _get_horizontal_velocity(self, keys_pressed: Set[int]) -> float:
            """Method gets player's current horizontal velocity"""
            input_move_vector: Vector2D = Vector2D(0, 0)

            if self._KEY_CODE_A in keys_pressed:
                input_move_vector.x += (-self._PLAYER_MOVE_SPEED *
                                        self._PMS_gb_multiplier)

            if self._KEY_CODE_D in keys_pressed:
                input_move_vector.x += (self._PLAYER_MOVE_SPEED *
                                        self._PMS_gb_multiplier)

            return input_move_vector.x

        def _get_vertical_velocity(self, keys_pressed: Set[int]) -> float:
            """Method calculates current player's vertical velocity"""
            if (self._KEY_CODE_SPACE not in keys_pressed
                    and self._player_is_on_the_ground):
                self._vertical_velocity = self._GRAVITY_ACCELERATION.y
            elif (self._KEY_CODE_SPACE in keys_pressed
                  and self._player_is_on_the_ground):
                self._vertical_velocity = (self._INITIAL_JUMP_VELOCITY *
                                           self._IJV_gb_multiplier)
                self._player_is_on_the_ground = False

            elif (self._vertical_velocity + self._GRAVITY_ACCELERATION.y <
                  self._MAX_VERTICAL_VELOCITY):
                self._vertical_velocity += self._GRAVITY_ACCELERATION.y

            else:
                self._vertical_velocity = self._MAX_VERTICAL_VELOCITY

            return self._vertical_velocity

        def update_immovable_objects_states(self):  # pragma: no cover
            for immovable_object in self._game_map.immovable_objects:
                if isinstance(immovable_object, AbstractBuff):
                    self._update_buff_state(immovable_object)

                else:
                    GameEngineException(
                        "[update_immovable_objects_states] method got "
                        "[immovable_object] with unknown type: " +
                        immovable_object.__class__.__name__)

        def _update_buff_state(self, buff: AbstractBuff):
            buff.check_buff_expiration(self._get_game_loop_iterations_count())