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

求助:运行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

问题排查与修复要点

  1. GameObject图像属性错误
    GameObject类中把加载的图像存储在self.background,但所有绘制逻辑都使用.image属性调用,导致小球(及其他对象)无法找到图像资源。需将GameObject中的self.background改为self.image。

  2. 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)。

  3. 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。
  4. 方法调用与返回值错误

    • bounce方法调用时未传入所需参数(ball、dx、dy),且边界判断逻辑错误(比如800 - self.height实际为0,不符合屏幕边界),可将碰撞反弹逻辑整合到check_if_collided中简化代码。
    • detect_score方法没有返回值,需在每个条件分支添加return语句,否则永远不会触发重置逻辑。
  5. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 19:31:05