You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Pygame中发射球朝向最后一个瞄准球方向运动?

修复发射球方向与显示问题

你的代码有三个核心问题导致发射球无法正确朝向瞄准球运动(或无法显示):

1. 鼠标点击事件未正确捕获

鼠标点击判断代码写在了事件循环外部,event变量只在for event in pygame.event.get()循环内有效,外部调用会导致错误或无法触发发射。

修改:
将鼠标点击判断移到事件循环内部:

while run:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      run = False
    # 移到这里
    if event.type == pygame.MOUSEBUTTONDOWN:
      shooting_balls.append(Shooting_Ball(*pos))

2. 绘制顺序颠倒

你先绘制了飞行中的发射球,再执行window.fill(black)清空窗口,导致发射球被覆盖,根本看不到。正确的绘制顺序应该是:清空窗口 → 绘制静态元素 → 绘制动态元素 → 更新显示。

修改:
调整主循环内的绘制逻辑顺序,把window.fill(black)放在最前面,然后依次绘制所有元素,最后更新显示:

while run:
  # ... 事件处理、按键逻辑 ...

  # 1. 清空窗口
  window.fill(black)

  # 2. 绘制静态元素
  pygame.draw.rect(window, blue, pygame.Rect(posx, posy, 50, 50))
  pygame.draw.circle(window, white, [400, 600], 8, 0)

  # 3. 绘制瞄准球
  pygame.draw.circle(window, gray, [circle_positions_x[0], circle_positions_y[0]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[1], circle_positions_y[1]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[2], circle_positions_y[2]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[3], circle_positions_y[3]], 8, 0)

  # 4. 绘制发射原点
  pygame.draw.circle(window, white, pos, 8, 0)
  window.blit(text, textRect)

  # 5. 更新并绘制飞行中的发射球
  for shooting_ball in shooting_balls[:]:
    shooting_ball.update()
    if not window.get_rect().collidepoint(shooting_ball.pos):
      shooting_balls.remove(shooting_ball)
    
  for shooting_ball in shooting_balls:
    shooting_ball.draw(window)

  # 6. 其他逻辑
  if move_ticker > 0:
    move_ticker -= 1

  # 7. 更新显示
  pygame.display.update()

3. 冗余的按键获取

主循环内重复调用了keys = pygame.key.get_pressed(),删掉后面那一次即可,避免不必要的性能消耗。

完整修正代码

import pygame
import random
import math
pygame.init()

posx = random.randint(50, 600)
posy = 50

move_ticker = 0

black = pygame.Color('black')
blue = pygame.Color('blue')
red = pygame.Color('red')
green = pygame.Color('green')
white = pygame.Color('white')
gray = pygame.Color('gray')

num_in_box = random.randint(1, 30)

font = pygame.font.Font("freesansbold.ttf", 16)
text = font.render(str(num_in_box), True, white, blue)
textRect = text.get_rect()
textRect.center = (posx + 25, posy + 25)

circle_positions_x = [350, 300, 250, 200]
circle_positions_y = [550, 500, 450, 400]

class Shooting_Ball:
    def __init__(self, x, y):
        self.pos = (x, y)
        rx, ry = circle_positions_x[3], circle_positions_y[3]
        self.dir = (rx - x, ry - y)
        length = math.hypot(*self.dir)
        if length == 0.0:
            self.dir = (0, -1)
        else:
            self.dir = (self.dir[0]/length, self.dir[1]/length)
        angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))

        self.shooting_ball = pygame.Surface((7, 2)).convert_alpha()
        self.shooting_ball.fill((255, 255, 255))
        self.shooting_ball = pygame.transform.rotate(self.shooting_ball, angle)
        self.speed = 2

    def update(self):  
        self.pos = (self.pos[0]+self.dir[0]*self.speed, 
                    self.pos[1]+self.dir[1]*self.speed)

    def draw(self, surf):
        shooting_ball_rect = self.shooting_ball.get_rect(center = self.pos)
        surf.blit(self.shooting_ball, shooting_ball_rect)  


shooting_ball_pos = pygame.math.Vector2(400, 600)

(width, height) = 1280, 780
window = pygame.display.set_mode((width, height))

pygame.display.set_caption("GAME")

shooting_balls = []
pos = (400, 600)

run = True

while run:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      run = False
    # 移到事件循环内的鼠标点击判断
    if event.type == pygame.MOUSEBUTTONDOWN:
      shooting_balls.append(Shooting_Ball(*pos))

  keys = pygame.key.get_pressed()

  offset_y = (6, 12, 18, 24)
  offset_x = (3, 6, 9, 12)

  # Go Left if x of first circle is less than 350    
  if keys[pygame.K_LEFT] and circle_positions_x[0] <= 350:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] += offset_y[i]
    for i in range (len(circle_positions_x)):
      circle_positions_x[i] -= offset_x[i]         
  
  # Go Left if x of first circle is between 350 and 450
  if keys[pygame.K_LEFT] and circle_positions_x[0] >= 350 and circle_positions_x[0] <= 449:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] += 0
    for i in range(len(circle_positions_x)):
      circle_positions_x[i] -= offset_y[i]
  
  # Go Left if x of the first circle is greater than 450
  if keys[pygame.K_LEFT] and circle_positions_x[0] >= 400:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] -= offset_y[i]
    for i in range(len(circle_positions_x)):
      circle_positions_x[i] -= offset_x[i]

  # Go Right if x of the first circle is less than 349 
  if keys[pygame.K_RIGHT] and circle_positions_x[0] <= 350:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] -= offset_y[i]
    for i in range(len(circle_positions_x)):
      circle_positions_x[i] += offset_x[i]

  # Go Right if x of the first circle is between 350 and 450 
  if keys[pygame.K_RIGHT] and circle_positions_x[0] >= 350 and circle_positions_x[0] <= 450:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] -= 0
    for i in range(len(circle_positions_x)):
      circle_positions_x[i] += offset_y[i]
  
  # Go Right if x of the first circle is greater than 450
  if keys[pygame.K_RIGHT] and circle_positions_x[0] >= 450:
    for i in range(len(circle_positions_y)):
      circle_positions_y[i] += offset_y[i]
    for i in range(len(circle_positions_x)):
      if circle_positions_x[3] < 659:
        circle_positions_x[i] += offset_x[i]
      else:
        circle_positions_x[i] -= offset_x[i]
  
  # --- 调整后的绘制顺序 ---
  window.fill(black)

  pygame.draw.rect(window, blue, pygame.Rect(posx, posy, 50, 50))
  pygame.draw.circle(window, white, [400, 600], 8, 0)

  # 绘制瞄准球
  pygame.draw.circle(window, gray, [circle_positions_x[0], circle_positions_y[0]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[1], circle_positions_y[1]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[2], circle_positions_y[2]], 8, 0)
  pygame.draw.circle(window, gray, [circle_positions_x[3], circle_positions_y[3]], 8, 0)

  # 绘制发射原点
  pygame.draw.circle(window, white, pos, 8, 0)
  window.blit(text, textRect)

  # 更新并绘制飞行中的发射球
  for shooting_ball in shooting_balls[:]:
    shooting_ball.update()
    if not window.get_rect().collidepoint(shooting_ball.pos):
      shooting_balls.remove(shooting_ball)
    
  for shooting_ball in shooting_balls:
    shooting_ball.draw(window)

  if move_ticker > 0:
    move_ticker -= 1

  pygame.display.update()

内容的提问来源于stack exchange,提问作者user19656752

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 04:24:18