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

如何在Pygame代码中添加可移动弹跳的圆形图形?

如何在Pygame中添加可移动反弹的圆形?

问题描述

我想在如下Pygame代码中添加一个圆形,使其像现有矩形一样移动并在窗口边缘反弹:

import pygame, sys, time
from pygame.locals import *

# Set up pygame.
pygame.init()

# Set up the window.
WINDOWWIDTH = 400
WINDOWHEIGHT = 400
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Animation')

# Set up direction variables.
DOWNLEFT = 'downleft'
DOWNRIGHT = 'downright'
UPLEFT = 'upleft'
UPRIGHT = 'upright'

MOVESPEED = 4

# Set up the colors.
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)

# Set up the box data structure.
b1 = {'rect':pygame.Rect(300, 80, 50, 100), 'color':RED, 'dir':UPRIGHT}
b2 = {'rect':pygame.Rect(200, 200, 20, 20), 'color':GREEN, 'dir':UPLEFT}
b3 = {'rect':pygame.Rect(100, 150, 60, 60), 'color':BLUE, 'dir':DOWNLEFT}
boxes = [b1, b2, b3]

# Run the game loop.
while True:
    #Check for the QUIT event.
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

     #Draw the white background onto the surface.
    windowSurface.fill(WHITE)

    for b in boxes:
        # Move the box data structure.
        if b['dir'] == DOWNLEFT:
            b['rect'].left -= MOVESPEED
            b['rect'].top += MOVESPEED
        if b['dir'] == DOWNRIGHT:
            b['rect'].left += MOVESPEED
            b['rect'].top += MOVESPEED
        if b['dir'] == UPLEFT:
            b['rect'].left -= MOVESPEED
            b['rect'].top -= MOVESPEED
        if b['dir'] == UPRIGHT:
            b['rect'].left += MOVESPEED
            b['rect'].top -= MOVESPEED

        # Check whether the box has moved out of the window.
        if b['rect'].top < 0:
            # The box has moved past the top.
            if b['dir'] == UPLEFT:
                b['dir'] = DOWNLEFT
            if b['dir'] == UPRIGHT:
                b['dir'] = DOWNRIGHT
        if b['rect'].bottom > WINDOWHEIGHT:
            # The box has moved past the bottom.
            if b['dir'] == DOWNLEFT:
                b['dir'] = UPLEFT
            if b['dir'] == DOWNRIGHT:
                b['dir'] = UPRIGHT
        if b['rect'].left < 0:
            # The box has moved past the left side.
            if b['dir'] == DOWNLEFT:
                b['dir'] = DOWNRIGHT
            if b['dir'] == UPLEFT:
                b['dir'] = UPRIGHT
        if b['rect'].right > WINDOWWIDTH:
            # The box has moved past the right side.
            if b['dir'] == DOWNRIGHT:
                b['dir'] = DOWNLEFT
            if b['dir'] == UPRIGHT:
                b['dir'] = UPLEFT

        # Draw the box onto the surface.
        pygame.draw.rect(windowSurface, b['color'], b['rect'])
    # Draw the window onto the screen.
    pygame.display.update()
    time.sleep(0.02)

我尝试在boxes列表中添加圆形项,调用pygame.draw.circle(windowSurface, b['color'], b['circle'])进行绘制,但一直出现"circle"无模块属性的错误,不知道该如何实现需求。

解决方案

问题出在你对圆形数据结构的定义和绘制调用上。pygame.draw.circle需要的参数是表面、颜色、圆心坐标、半径,而不是一个名为"circle"的属性。同时为了让圆形复用现有移动和边界反弹逻辑,我们可以给圆形绑定一个Rect对象(用于边界碰撞检测),同时存储圆心和半径信息。

修改后的完整代码

import pygame, sys, time
from pygame.locals import *

# Set up pygame.
pygame.init()

# Set up the window.
WINDOWWIDTH = 400
WINDOWHEIGHT = 400
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Animation')

# Set up direction variables.
DOWNLEFT = 'downleft'
DOWNRIGHT = 'downright'
UPLEFT = 'upleft'
UPRIGHT = 'upright'

MOVESPEED = 4

# Set up the colors.
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
PURPLE = (128, 0, 128) # 新增紫色用于圆形

# Set up the shape data structure: 区分矩形和圆形
b1 = {'type': 'rect', 'rect':pygame.Rect(300, 80, 50, 100), 'color':RED, 'dir':UPRIGHT}
b2 = {'type': 'rect', 'rect':pygame.Rect(200, 200, 20, 20), 'color':GREEN, 'dir':UPLEFT}
b3 = {'type': 'rect', 'rect':pygame.Rect(100, 150, 60, 60), 'color':BLUE, 'dir':DOWNLEFT}
# 新增圆形:type标记为circle,rect用于碰撞检测(圆心对应rect中心,宽高是直径),center存储圆心坐标,radius是半径
circle1 = {
    'type': 'circle',
    'rect': pygame.Rect(150, 100, 40, 40), # 宽高等于直径,方便用rect做边界检测
    'color': PURPLE,
    'dir': DOWNRIGHT,
    'radius': 20,
    'center': (150+20, 100+20) # 初始圆心是rect的中心
}
shapes = [b1, b2, b3, circle1] # 把所有图形放到统一列表

# Run the game loop.
while True:
    # Check for the QUIT event.
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

     # Draw the white background onto the surface.
    windowSurface.fill(WHITE)

    for shape in shapes:
        # Move the shape data structure
        if shape['dir'] == DOWNLEFT:
            shape['rect'].left -= MOVESPEED
            shape['rect'].top += MOVESPEED
        if shape['dir'] == DOWNRIGHT:
            shape['rect'].left += MOVESPEED
            shape['rect'].top += MOVESPEED
        if shape['dir'] == UPLEFT:
            shape['rect'].left -= MOVESPEED
            shape['rect'].top -= MOVESPEED
        if shape['dir'] == UPRIGHT:
            shape['rect'].left += MOVESPEED
            shape['rect'].top -= MOVESPEED

        # 更新圆形的圆心坐标(因为rect移动了)
        if shape['type'] == 'circle':
            shape['center'] = (shape['rect'].centerx, shape['rect'].centery)

        # Check whether the shape has moved out of the window.
        if shape['rect'].top < 0:
            # The shape has moved past the top.
            if shape['dir'] == UPLEFT:
                shape['dir'] = DOWNLEFT
            if shape['dir'] == UPRIGHT:
                shape['dir'] = DOWNRIGHT
        if shape['rect'].bottom > WINDOWHEIGHT:
            # The shape has moved past the bottom.
            if shape['dir'] == DOWNLEFT:
                shape['dir'] = UPLEFT
            if shape['dir'] == DOWNRIGHT:
                shape['dir'] = UPRIGHT
        if shape['rect'].left < 0:
            # The shape has moved past the left side.
            if shape['dir'] == DOWNLEFT:
                shape['dir'] = DOWNRIGHT
            if shape['dir'] == UPLEFT:
                shape['dir'] = UPRIGHT
        if shape['rect'].right > WINDOWWIDTH:
            # The shape has moved past the right side.
            if shape['dir'] == DOWNRIGHT:
                shape['dir'] = DOWNLEFT
            if shape['dir'] == UPRIGHT:
                shape['dir'] = UPLEFT

        # 根据图形类型绘制
        if shape['type'] == 'rect':
            pygame.draw.rect(windowSurface, shape['color'], shape['rect'])
        elif shape['type'] == 'circle':
            pygame.draw.circle(windowSurface, shape['color'], shape['center'], shape['radius'])

    # Draw the window onto the screen.
    pygame.display.update()
    time.sleep(0.02)

关键修改点说明

  1. 新增图形类型标记:给每个图形字典添加type字段,区分是矩形还是圆形,方便后续绘制逻辑判断。
  2. 圆形的数据结构:
    • 用rect对象做边界碰撞检测,宽高设置为圆形的直径,这样rect的边界正好对应圆形的外切矩形,和现有矩形的碰撞逻辑完全兼容。
    • 存储center(圆心坐标)和radius(半径),用于pygame.draw.circle调用。
  3. 移动时更新圆心:每次移动圆形的rect后,同步更新center为rect的中心坐标,保证圆形位置正确。
  4. 分类型绘制:在循环中根据type字段选择调用pygame.draw.rect或pygame.draw.circle。

这样修改后,圆形就能和矩形一样移动并在窗口边缘反弹了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:01:14