在Pygame中创建带圆周传感器的可移动旋转圆形
Got it, let's build this obstacle-avoiding, rotating circle step by step in Pygame! I'll make sure the direction stays clear even when spinning, and the front/left/right sensors work as intended (even if the original diagram had reversed L/R labels—we'll stick to your core needs).
We'll create a circle with:
- A position, radius, and current facing angle (to track direction reliably)
- Three sensors on its circumference: front (aligned with facing direction), left, and right
- Controls to rotate the circle and move it forward/backward
- Obstacle detection using the sensors to avoid square barriers
1. Initialize Pygame & Basic Setup
First, we'll set up the window, define core variables for the circle, and create some test obstacles:
import pygame import math # Initialize Pygame pygame.init() # Screen settings SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Sensor-Controlled Circle") # Colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # Circle properties circle_pos = pygame.math.Vector2(100, SCREEN_HEIGHT // 2) circle_radius = 30 circle_speed = 3 current_angle = 0 # 0 degrees = facing right (adjust to start facing other directions) # Obstacles (list of pygame.Rect objects) obstacles = [ pygame.Rect(300, 200, 100, 100), pygame.Rect(500, 400, 80, 80), pygame.Rect(200, 500, 120, 60) ] clock = pygame.time.Clock()
2. Calculate Sensor Positions
The sensors sit on the circle's edge, so we'll use polar coordinates to compute their positions relative to the circle's center. Pygame's Vector2.from_polar() simplifies this:
def get_sensor_positions(center, radius, angle): # Front sensor: aligned with current facing angle front = center + pygame.math.Vector2.from_polar((radius, angle)) # Left sensor: 90 degrees counterclockwise from facing direction # (Swap +90 and -90 here if you need to match reversed L/R labels from your diagram) left = center + pygame.math.Vector2.from_polar((radius, angle + 90)) # Right sensor: 90 degrees clockwise from facing direction right = center + pygame.math.Vector2.from_polar((radius, angle - 90)) return front, left, right
Note: If you need to reverse the left/right sensors to match your diagram's reversed labels, just swap the +90 and -90 values in the left/right calculations.
3. Obstacle Detection Logic
We'll check if any sensor is inside an obstacle using Rect.collidepoint(), which returns a boolean for each sensor:
def check_obstacles(sensors, obstacles): front_hit, left_hit, right_hit = False, False, False for obs in obstacles: if obs.collidepoint(sensors[0]): front_hit = True if obs.collidepoint(sensors[1]): left_hit = True if obs.collidepoint(sensors[2]): right_hit = True return front_hit, left_hit, right_hit
4. Movement & Rotation Controls
We'll use keyboard inputs to rotate the circle and move it. The movement direction is always aligned with the current facing angle to avoid direction confusion:
def handle_movement(pos, angle, speed, front_hit): keys = pygame.key.get_pressed() # Rotate left/right if keys[pygame.K_LEFT]: angle += 2 # Counterclockwise rotation if keys[pygame.K_RIGHT]: angle -= 2 # Clockwise rotation # Move forward/backward (optional: block forward movement if front is blocked) if keys[pygame.K_UP] and not front_hit: direction = pygame.math.Vector2.from_polar((speed, angle)) pos += direction if keys[pygame.K_DOWN]: direction = pygame.math.Vector2.from_polar((speed, angle + 180)) pos += direction # Keep circle within screen bounds pos.x = max(circle_radius, min(pos.x, SCREEN_WIDTH - circle_radius)) pos.y = max(circle_radius, min(pos.y, SCREEN_HEIGHT - circle_radius)) return pos, angle
Optional: I added a check to prevent moving forward if the front sensor hits an obstacle—remove the and not front_hit part if you want full manual control regardless of obstacles.
5. Main Game Loop
Put it all together to handle events, update positions, detect obstacles, and draw everything:
running = True while running: screen.fill(WHITE) # Handle quit event for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Get current sensor positions sensors = get_sensor_positions(circle_pos, circle_radius, current_angle) # Check for obstacle collisions front_hit, left_hit, right_hit = check_obstacles(sensors, obstacles) # Update circle position and rotation circle_pos, current_angle = handle_movement(circle_pos, current_angle, circle_speed, front_hit) # Draw obstacles for obs in obstacles: pygame.draw.rect(screen, BLACK, obs) # Draw the main circle pygame.draw.circle(screen, BLUE, (int(circle_pos.x), int(circle_pos.y)), circle_radius) # Optional: Draw sensors (comment out if you don't want them visible) pygame.draw.circle(screen, RED, (int(sensors[0].x), int(sensors[0].y)), 3) # Front pygame.draw.circle(screen, GREEN, (int(sensors[1].x), int(sensors[1].y)), 3) # Left pygame.draw.circle(screen, GREEN, (int(sensors[2].x), int(sensors[2].y)), 3) # Right # Refresh display pygame.display.flip() clock.tick(60) pygame.quit()
- The
current_anglevariable always tracks the circle's facing direction—no matter how much you rotate, moving forward uses this angle, so you'll never mix up front/back. - If you need the circle to start facing a different direction (e.g., up), set
current_angle = 90(Pygame's polar coordinates use 0° as right, 90° as up). - Sensors rotate automatically with the circle since their positions are calculated relative to
current_angle.
内容的提问来源于stack exchange,提问作者MandyLB

