如何让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
相关产品推荐
相关产品推荐

