求助:运行Pygame代码时球未在屏幕显示的问题排查
Pygame小球不显示问题修复
问题描述
运行以下Pygame程序时,除球之外的所有元素都能正常显示并工作。在编写球的移动逻辑之前,球是可以正常显示的,因此确定问题出在移动逻辑相关的代码中,但无法找到具体原因。
原代码
主程序代码
import pygame from gameObject import GameObject pygame.font.init() myfont = pygame.font.SysFont('FNT', 80) pygame.init() class Player(GameObject): def __init__(self, x, y, width, height, image_path, speed): super().__init__(x, y, width, height, image_path) self.speed = speed def move(self, direction, max_height): if (self.y >= max_height - self.height and direction > 0) or (self.y <= 0 and direction < 0): return self.y += (direction * self.speed) class Ball(GameObject): def __init__(self, x, y, width, height, image_path, speed): super().__init__(x, y, width, height, image_path) self.speed = speed def move(self, max_height, dx, dy): if self.y <= 0: self.speed = abs(self.speed) elif (self.y >= max_height - self.height and dy > 0) or (self.y <= 0 and dy < 0): self.y = -self.y self.y += (dx * self.speed) self.x += (dy * self.speed) class Game: def __init__(self): self.width = 800 self.height = 800 self.white_color = (255, 255, 255) self.game_window = pygame.display.set_mode((self.width, self.height)) self.clock = pygame.time.Clock() self.background = GameObject(0, 0, self.width, self.height, 'assets/background.png') self.level = 1.0 self.reset_map() def reset_map(self): self.player1 = Player(-200, 300, 500, 175, 'assets/player.png', 10) self.player2 = Player(500, 300, 500, 175, 'assets/player.png', 10 ) self.ball = Ball(400, 400, 40, 40, 'assets/ball.png', 3) # self.ball.speed = 3 # if self.level >= 9: # self.ball.speed = 15 # elif self.level >= 7: # self.ball.speed = 10 # elif self.level >= 3: # self.ball.speed = 5 def draw_objects(self): self.game_window.fill(self.white_color) self.game_window.blit(self.background.image, (self.background.x, self.background.y)) self.game_window.blit(self.player1.image, (self.player1.x, self.player1.y)) self.game_window.blit(self.player2.image, (self.player2.x, self.player2.y)) self.game_window.blit(self.ball.image, (self.ball.x, self.ball.y)) pygame.display.update() def move_objects(self, player1_direction, player2_direction, dx, dy): self.player1.move(player1_direction, self.height) self.player2.move(player2_direction, self.height) self.ball.move(dx, dy, self.height) def check_if_collided(self): if self.detect_collision(self.player1, self.ball): return True if self.detect_collision(self.player2, self.ball): return True def detect_score(self, ball): if ball.x >= 800 - self.width: True elif ball.x <= 0 - self.width: True else: False def bounce(self, ball, dy, dx): if ball.y >= 800 - self.height: dy *= -1 self.level += 1 elif ball.y <= 0 - self.height: dx *= -1 self.level += 1 def detect_collision(self, object_1, object_2): if object_1.y < (object_2.y + object_2.height) and (object_1.y + object_1.height) > object_2.y and object_1.x < (object_2.x + object_2.width) and (object_1.x + object_1.width) > object_2.x: return True return False def run_game_loop(self): player1_direction = 0 player2_direction = 0 dx = .1 dy = -.1 gameRunning = True while gameRunning: for event in pygame.event.get(): if event.type == pygame.QUIT: gameRunning = False if gameRunning == False: pygame.quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: player2_direction = -1 elif event.key == pygame.K_DOWN: player2_direction = 1 elif event.key == pygame.K_w: player1_direction = -1 elif event.key == pygame.K_s: player1_direction = 1 elif event.type == pygame.KEYUP: if event.key == pygame.K_UP or event.key == pygame.K_DOWN: player2_direction = 0 if event.key == pygame.K_w or event.key == pygame.K_s: player1_direction = 0 self.draw_objects() self.move_objects(player1_direction, player2_direction, dx, dy) if self.check_if_collided(): self.bounce() if self.detect_score(self.ball): self.reset_map() self.clock.tick(60) game = Game() game.run_game_loop() quit()
GameObject类代码
import pygame class GameObject: def __init__(self, x, y, width, height, image_path): background = pygame.image.load(image_path) self.background = pygame.transform.scale(background, (width, height)) self.x = x self.y = y self.width = width self.height = height
问题排查与修复要点
GameObject图像属性错误
GameObject类中把加载的图像存储在self.background,但所有绘制逻辑都使用.image属性调用,导致小球(及其他对象)无法找到图像资源。需将GameObject中的self.background改为self.image。Ball.move方法参数顺序错误
Game类的move_objects中调用self.ball.move(dx, dy, self.height),但Ball类的move方法定义为def move(self, max_height, dx, dy),参数顺序完全颠倒,导致边界判断和位置计算全部错误,小球直接跑出屏幕。需调整调用顺序为self.ball.move(self.height, dx, dy)。Ball.move逻辑混乱
- 反弹逻辑错误:
self.y = -self.y会将小球瞬移到屏幕外,应改为反转y方向的速度(单独维护x、y方向的速度分量更合理)。 - 位置更新参数搞反:
self.y += (dx * self.speed)、self.x += (dy * self.speed),正确应为self.x += dx * self.speed,self.y += dy * self.speed。
- 反弹逻辑错误:
方法调用与返回值错误
bounce方法调用时未传入所需参数(ball、dx、dy),且边界判断逻辑错误(比如800 - self.height实际为0,不符合屏幕边界),可将碰撞反弹逻辑整合到check_if_collided中简化代码。detect_score方法没有返回值,需在每个条件分支添加return语句,否则永远不会触发重置逻辑。
Player初始位置优化
player1的x=-200、宽度500,导致大部分在屏幕外,可调整为x=50,使其正常显示在屏幕左侧。
修复后的代码
修复后的GameObject类
import pygame class GameObject: def __init__(self, x, y, width, height, image_path): img = pygame.image.load(image_path) self.image = pygame.transform.scale(img, (width, height)) self.x = x self.y = y self.width = width self.height = height
修复后的主程序代码
import pygame from gameObject import GameObject pygame.font.init() myfont = pygame.font.SysFont('FNT', 80) pygame.init() class Player(GameObject): def __init__(self, x, y, width, height, image_path, speed): super().__init__(x, y, width, height, image_path) self.speed = speed def move(self, direction, max_height): if (self.y >= max_height - self.height and direction > 0) or (self.y <= 0 and direction < 0): return self.y += direction * self.speed class Ball(GameObject): def __init__(self, x, y, width, height, image_path, speed): super().__init__(x, y, width, height, image_path) self.speed = speed # 单独维护x、y方向的速度分量 self.dx = speed self.dy = -speed def move(self, max_height): # 上下边界反弹 if self.y <= 0: self.dy = abs(self.dy) elif self.y >= max_height - self.height: self.dy = -abs(self.dy) self.x += self.dx self.y += self.dy class Game: def __init__(self): self.width = 800 self.height = 800 self.white_color = (255, 255, 255) self.game_window = pygame.display.set_mode((self.width, self.height)) self.clock = pygame.time.Clock() self.background = GameObject(0, 0, self.width, self.height, 'assets/background.png') self.level = 1.0 self.reset_map() def reset_map(self): # 调整player1位置使其显示在屏幕内 self.player1 = Player(50, 300, 100, 175, 'assets/player.png', 10) self.player2 = Player(650, 300, 100, 175, 'assets/player.png', 10 ) self.ball = Ball(400, 400, 40, 40, 'assets/ball.png', 3) # 根据等级调整速度 if self.level >= 9: self.ball.speed = 15 elif self.level >= 7: self.ball.speed = 10 elif self.level >= 3: self.ball.speed = 5 # 更新速度分量 self.ball.dx = self.ball.speed self.ball.dy = -self.ball.speed def draw_objects(self): self.game_window.fill(self.white_color) self.game_window.blit(self.background.image, (self.background.x, self.background.y)) self.game_window.blit(self.player1.image, (self.player1.x, self.player1.y)) self.game_window.blit(self.player2.image, (self.player2.x, self.player2.y)) self.game_window.blit(self.ball.image, (self.ball.x, self.ball.y)) pygame.display.update() def move_objects(self, player1_direction, player2_direction): self.player1.move(player1_direction, self.height) self.player2.move(player2_direction, self.height) self.ball.move(self.height) def check_if_collided(self): if self.detect_collision(self.player1, self.ball): self.ball.dx = abs(self.ball.dx) self.level += 1 return True if self.detect_collision(self.player2, self.ball): self.ball.dx = -abs(self.ball.dx) self.level += 1 return True return False def detect_score(self, ball): if ball.x >= self.width: # player2得分,重置 self.reset_map() return True elif ball.x <= -ball.width: # player1得分,重置 self.reset_map() return True return False def detect_collision(self, object_1, object_2): return (object_1.y < object_2.y + object_2.height and object_1.y + object_1.height > object_2.y and object_1.x < object_2.x + object_2.width and object_1.x + object_1.width > object_2.x) def run_game_loop(self): player1_direction = 0 player2_direction = 0 gameRunning = True while gameRunning: for event in pygame.event.get(): if event.type == pygame.QUIT: gameRunning = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: player2_direction = -1 elif event.key == pygame.K_DOWN: player2_direction = 1 elif event.key == pygame.K_w: player1_direction = -1 elif event.key == pygame.K_s: player1_direction = 1 elif event.type == pygame.KEYUP: if event.key == pygame.K_UP or event.key == pygame.K_DOWN: player2_direction = 0 if event.key == pygame.K_w or event.key == pygame.K_s: player1_direction = 0 self.draw_objects() self.move_objects(player1_direction, player2_direction) self.check_if_collided() self.detect_score(self.ball) self.clock.tick(60) pygame.quit() game = Game() game.run_game_loop() quit()
内容的提问来源于stack exchange,提问作者Blitz
相关产品推荐
相关产品推荐

