示例#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 update(self):
        # Draw direction lines if requested
        if DoFlag.show_directions:
            self.draw_movement_line()

        # Check if a goal was scored
        for goal in Sprites.goals:
            enough_dur = (Frames.time() - goal.last_touch) > 0.1
            if self.rect.colliderect(goal) and enough_dur:
                goal.last_touch = Frames.time()
                self.score_time = Frames.time() - Gen.last_goal_time
                if goal.side == Conf.LEFT:
                    self.side = Conf.RIGHT
                else:
                    self.side = Conf.LEFT
                self.master.score_goal(self.score_time, self.side)

        # Check if ball was kicked and move accordingly
        if self.do_move:
            dur = Frames.time() - self.kick_time
            if dur < self.max_time:
                distance = 0.5 * self.move_dist * (self.max_time - dur)
                if distance < 2:
                    return
                self.move(self.move_angle, distance)
            else:
                self.do_move = False
示例#3
0
    def __init__(self,
                 size=Conf.BALL_SIZE,
                 pos=None,
                 color=Conf.COLOR2,
                 master=None):
        if pos is None:
            pos = (Conf.WIDTH // 2, Conf.HEIGHT // 2)
        super().__init__(size, pos=pos, color=color, text="B")
        self.master = master
        Gen.last_goal_time = Frames.time()
        self.move_dist = 0  # Move distance
        self.move_angle = 0  # Degrees from positive x-axis
        self.do_move = False
        self.friction = Physics.FRICTION

        self.kick_time = 0
        self.max_time = 0
        self.mass = Physics.BALL_MASS
        self.f_normal = self.mass * Physics.G
        self.f_friction = self.f_normal * Physics.MU  # Force due to friction
        self.a_friction = self.f_friction / self.mass  # Acceleration  ||
        self.side = None  # The side the ball scored on

        self.score_time = None
        Sprites.balls.add(self)
示例#4
0
 def move(self, move_dir, distance=None):
     if move_dir == Conf.FORWARD:
         # Move in current direction
         super().move(self.move_angle)
     elif move_dir == Conf.BACKWARD:
         # Rotate direction by 180 amd move forward
         super().move(self.move_angle + 180)
     elif move_dir == Conf.LEFT:
         # Prevent excessive updates to angle change for a single press
         dur = Frames.time() - self.cool_down_l
         if dur > Conf.CD_TIME:
             self.move_angle -= Conf.DIR_OFFSET
             self.cool_down_l = Frames.time()
             self.place_dir_arrow()
             self.limit_angle()
     elif move_dir == Conf.RIGHT:
         dur = Frames.time() - self.cool_down_r
         if dur > Conf.CD_TIME:
             self.move_angle += Conf.DIR_OFFSET
             self.cool_down_r = Frames.time()
             self.place_dir_arrow()
             self.limit_angle()
示例#5
0
 def update_score(self, side):
     if side == Conf.LEFT:
         self.left += 1
     elif side == Conf.RIGHT:
         self.right += 1
     self.total = self.left + self.right
     self.image.fill(Conf.ALPHA_COLOR)  # Clear score box
     self.text = f"LEFT {self.left} : RIGHT {self.right}"  # Update text
     self.text_render = self.font.render(self.text, True, Conf.BLACK)
     self.text_rect = self.text_render.get_rect()
     self.text_rect.center = (self.rect.width // 2, self.rect.height // 2)
     Gen.last_goal_time = Frames.time()
     # Place text
     self.image.blit(self.text_render, self.text_rect)
示例#6
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)
示例#7
0
 def get_kicked(self, speed, angle):
     self.move_dist = speed
     self.move_angle = angle
     self.kick_time = Frames.time()
     self.max_time = speed / self.a_friction
     self.do_move = True