예제 #1
0
    def start_man_calc(self):  # manual and calculated
        self._init()
        while ExitCtr.gen:
            if DoFlag.update_frame:
                Gen.screen.fill(Conf.WHITE)  # Reset screen for fresh drawings
            # Control robot
            self.controller.manual_control()
            if DoFlag.auto_calc:
                self.controller.calculated_control()

            # Update game state
            Sprites.every.update()
            Frames.update()

            if DoFlag.update_frame:
                # Update drawing if required
                # Control loop intervals
                self.clock.tick(Conf.FPS)  # Comment out to remove fps limit

                # Draw field borders
                pygame.draw.rect(Gen.screen, Conf.BLACK, self.rect, 1)

                # Draw everything and update the display
                Sprites.every.draw(Gen.screen)
                pygame.display.update()

        self.exit()
예제 #2
0
    def frame_step(self, action):
        """
        param:
        action --> tuple(
            direction --> 0 (left), 1 (right)
            angle --> 1 - 12 (0 to 180/angle_increment )
            distance --> 0 to 60 (0 to 300/move_dist)
            kick --> 0 (don't kick) or 1 (kick)
            continue --> 0 (don't continue) or 1 (continue)
        )

        return:
        x --> 0 to 600 (x coordinate)
        y --> 0 to 400 (y coordinate)

        # Ball relative conditions
        ball_flag --> 0 (not seen) or 1 (seen)
        ball_theta --> 0 to 360/angle_increment
        ball_dist --> 0 to 600/move_dist

        # Own goal relative conditions
        own_goal_theta --> 0 to 360/angle_increment
        own_goal_dist --> 0 to 600/move_dist

        # Opponent goal conditions
        opp_goal_theta --> 0 to 360/angle_increment
        opp_goal_dist --> 0 to 600/move_dist

        # Kick results given 0 or 1 for only one frame
        is_kick_success --> 0 (null) or 2 (miss) or 1 (hit)
        is_kick_accurate --> 0 (null) or 2 (bad miss) or 1 (near miss)

        # State flags
        is_kicking --> 0 (not kicking) or 1 (is kicking)
        is_moving --> 0 (not moving) or 1 (is moving)
        is_ball_moved -- > 0 (not moved recently) or 1 (moved recently)
        is_goal_scored --> 2 (own goal scored) 0 (not scored) or 1 (scored)

        time --> time since start (calculated based on frames)
        """
        #         print(type(action),action)
        # #         return
        # Attempt to instantiate which will only be done if not done already
        self._init()
        if DoFlag.update_frame:
            Gen.screen.fill(Conf.WHITE)  # Reset screen for fresh drawings

        NULL = 0
        STATE1 = 1
        STATE2 = 2

        # Reset goal to not scored
        self._goal_scored(reset=True)

        # Get action commands
        #         print(type(action),action)
        direction, theta, dist, kick, cont = list(action)
        theta *= Conf.DIR_OFFSET
        dist *= Conf.MOVE_DIST
        if direction == 1:
            direction = Conf.RIGHT
        elif direction == 0:
            direction = Conf.LEFT
        else:
            raise ValueError(
                f"{direction} is not a valid option. Must be 0 or 1")

        # Create return away
        ret_val = np.zeros(fsr.NUM_VAL)
        ret_val[fsr.ACT_DIR] = action[0]
        ret_val[fsr.ACT_THETA] = action[1]
        ret_val[fsr.ACT_DIST] = action[2]
        ret_val[fsr.ACT_KICK] = action[3]
        ret_val[fsr.ACT_CONT] = action[4]

        # Get vector positions (relative positions)
        to_ball_s, _, _ = self.controller.get_vec()
        ball_dist, ball_theta = to_ball_s.as_polar()

        if not cont:
            # Validate data
            if ret_val[fsr.ACT_THETA] > 360 / Conf.DIR_OFFSET:
                print(f"Warning {ret_val[fsr.ACT_THETA]} out of range "
                      f"{360/Conf.DIR_OFFSET}")
            if ret_val[fsr.ACT_DIST] > Conf.WIDTH / Conf.MOVE_DIST:
                print(f"Warning {ret_val[fsr.ACT_DIST]} out of range "
                      f"{Conf.WIDTH/Conf.MOVE_DIST}")
            self.net[Conf.DIRECTION] = direction
            self.net[Conf.THETA] = theta * Conf.DIR_OFFSET
            self.net[Conf.DIST] = dist * Conf.MOVE_DIST
            self.net[Conf.KICK] = kick

        # In case no kick was performed set to null value
        ret_val[fsr.IS_KICK_ACCURATE] = ret_val[fsr.IS_KICK_SUCCESS] = NULL
        if Frames.time() - Gen.last_kick_time < Conf.KICK_COOLDOWN:
            ret_val[fsr.IS_KICKING] = 1
        elif self.net[Conf.KICK] == 1:
            is_kicked = self.robot.kick()
            self.net[Conf.KICK] = False
            Gen.last_kick_time = Frames.time()

            # If within kick range
            if is_kicked:
                ret_val[fsr.IS_KICK_SUCCESS] = STATE1
            else:
                ret_val[fsr.IS_KICK_SUCCESS] = STATE2

        elif self.net[Conf.THETA] > 0:
            self.robot.move(self.net[Conf.DIRECTION])
            self.net[Conf.THETA] -= Conf.DIR_OFFSET
        elif self.net[Conf.DIST] > 0:
            self.robot.move(Conf.FORWARD)
            self.net[Conf.DIST] -= Conf.MOVE_DIST

        # Update game state
        Sprites.every.update()
        Frames.update()

        # Update drawing if required
        if DoFlag.update_frame:
            self.clock.tick(Conf.FPS)  # Regulate FPS if desired

            # Draw field borders
            pygame.draw.rect(Gen.screen, Conf.BLACK, self.rect, 1)

            # Draw everything and update the display
            Sprites.every.draw(Gen.screen)
            pygame.display.update()

        # Update return Values
        to_ball, to_goal, to_own_goal = self.controller.get_vec()
        ret_val[fsr.BALL_DIST], ret_val[fsr.BALL_THETA] = to_ball.as_polar()
        ret_val[fsr.OPP_GOAL_DIST], ret_val[fsr.OPP_GOAL_THETA] = (
            to_goal.as_polar())
        ret_val[fsr.OWN_GOAL_DIST], ret_val[fsr.OWN_GOAL_THETA] = (
            to_own_goal.as_polar())
        if self.robot.move_angle < -90 and ball_theta > 90:  # Edge case
            if self.robot.move_angle + 360 - ball_theta <= Conf.HALF_VIS_THETA:
                ret_val[fsr.BALL_FLAG] = STATE1
        elif self.robot.move_angle > 90 and ball_theta < -90:  # Edge case
            if ball_theta + 360 - self.robot.move_angle <= Conf.HALF_VIS_THETA:
                ret_val[fsr.BALL_FLAG] = STATE1
        elif abs(self.robot.move_angle - ball_theta) <= Conf.HALF_VIS_THETA:
            # If within field of view
            ret_val[fsr.BALL_FLAG] = STATE1

        # If ball_start_pos != current_ball_pos then ball moving
        if to_ball != to_ball_s:
            ret_val[fsr.IS_BALL_MOVED] = STATE1

        # If still has angle change or distance change then moving
        if self.net[Conf.THETA] > 0 or self.net[Conf.DIST] > 0:
            ret_val[fsr.IS_MOVING] = STATE1

        # Check if goal scored this frame
        if self.is_goal_scored:
            if (  # If close to opponent goal then scored and accurate
                    self.ball.side == self.robot.side):
                ret_val[fsr.IS_GOAL_SCORED] = STATE1
                ret_val[fsr.IS_KICK_ACCURATE] = STATE1
            else:  # If not close to target then own goal
                ret_val[fsr.IS_GOAL_SCORED] = STATE2
                ret_val[fsr.IS_KICK_ACCURATE] = NULL
        elif (  # if ball in wall bounce x location  check next condition
                # If ball is within range of y value
                self.controller.goal_cen.y -
                1 * self.controller.goal.rect.height <
                self.balls[0].rect.centery < self.controller.goal_cen.y +
                1 * self.controller.goal.rect.height):
            if (  # If hit the wall close to the goal
                    self.ball.rect.centerx > self.ball_bounce_x
                    and self.robot.side == Conf.LEFT):
                if not self.is_accurate_sent:
                    ret_val[fsr.IS_KICK_ACCURATE] = STATE1
                    self.is_accurate_sent = True
            elif (self.ball.rect.centerx < self.ball_bounce_x
                  and self.robot.side == Conf.RIGHT):
                if not self.is_accurate_sent:
                    ret_val[fsr.IS_KICK_ACCURATE] = STATE1
                    self.is_accurate_sent = True
            else:  # If not against respective wall accuracy was not sent
                self.is_accurate_sent = False
        else:
            if (self.ball.rect.centerx > self.ball_bounce_x
                    and self.robot.side == Conf.LEFT):
                if not self.is_accurate_sent:
                    ret_val[fsr.IS_KICK_ACCURATE] = STATE2
                    self.is_accurate_sent = True
            elif (self.ball.rect.centerx < self.ball_bounce_x
                  and self.robot.side == Conf.RIGHT):
                if not self.is_accurate_sent:
                    ret_val[fsr.IS_KICK_ACCURATE] = STATE2
                    self.is_accurate_sent = True
            else:
                self.is_accurate_sent = False

        ret_val[fsr.X] = self.robot.rect.centerx
        ret_val[fsr.Y] = self.robot.rect.centery
        ret_val[fsr.TIME] = int(Frames.time())
        return np.array(ret_val)