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

如何实现所有Sprite持续移动,避免新Sprite生成时旧Sprite停止?

问题描述

我原本计划实现圆形Sprite按固定间隔生成,并以指定速度向鼠标位置移动,目前生成功能已正常运行,但每当新Sprite生成时,之前的Sprite便会停止移动,仿佛不再被更新。我希望所有Sprite能够同时向鼠标位置移动,而非仅新Sprite移动。我是开发新手,若您发现代码中的其他问题也请不吝指出。

相关代码
# Enemy
class Enemy (pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.x = 0
        self.y = 0
        self.speed = 2
        self.change_x = 0
        self.change_y = 0
        self.update()

    def update(self):
        dx, dy = (pygame.mouse.get_pos()[0]+8) - self.x, (pygame.mouse.get_pos()[1]+8) - self.y
        dist = math.hypot(dx, dy)
        dx, dy = dx / dist, dy / dist
        self.change_x += dx * self.speed
        self.change_y += dy * self.speed


def make_enemies():
    enemy = Enemy()
    enemy.change_x = random.randrange(0, 800)
    enemy.change_y = random.randrange(0, 600)
    enemy.speed = 2

    return enemy


enemy_list = []
spawn = make_enemies()
enemy_list.append(spawn)
add_enemy = pygame.USEREVENT + 1
pygame.time.set_timer(add_enemy, 1000)

# Game loop
done = False
while not done:

    # RGB - RED, GREEN, BLUE (0-255)
    screen.fill(BACKGROUND)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == add_enemy:
            spawn = make_enemies()
            enemy_list.append(spawn)
    for enemy in enemy_list:
        enemy.x = enemy.change_x
        enemy.y = enemy.change_y
        pygame.draw.circle (screen, WHITE, [enemy.change_x, enemy.change_y], BALL_SIZE)


    enemy.update()
    clock.tick(100)
    pygame.display.update()
问题修复与优化建议

核心问题:仅更新单个敌人

游戏循环里的enemy.update()只调用了最后一个生成的敌人的更新方法,之前的敌人完全没被处理。必须遍历所有敌人逐个调用update:

# 替换原循环里的enemy.update()
for enemy in enemy_list:
    enemy.update()

变量逻辑错误修正

  1. 初始位置赋值错误
    make_enemies里把初始位置赋值给了change_x/change_y,但Enemy类中x/y才是记录当前位置的变量,应该修正为:

    def make_enemies():
        enemy = Enemy()
        enemy.x = random.randrange(0, 800)
        enemy.y = random.randrange(0, 600)
        enemy.speed = 2
        return enemy
    
  2. 移动逻辑错误
    原update方法里累加change_x/change_y会导致速度越来越快,且没有正确更新x/y位置。应该让change_x/change_y作为每帧的位移量,直接更新位置:

    def update(self):
        dx, dy = (pygame.mouse.get_pos()[0]+8) - self.x, (pygame.mouse.get_pos()[1]+8) - self.y
        dist = math.hypot(dx, dy)
        # 避免敌人与鼠标重合时除以0的错误
        if dist != 0:
            dx, dy = dx / dist, dy / dist
            self.change_x = dx * self.speed
            self.change_y = dy * self.speed
        else:
            self.change_x = 0
            self.change_y = 0
        # 更新当前位置
        self.x += self.change_x
        self.y += self.change_y
    
  3. 绘制位置错误
    绘制时应该使用x/y作为位置,而非change_x/change_y,同时要转成整数(pygame绘制坐标需要整数):

    for enemy in enemy_list:
        pygame.draw.circle(screen, WHITE, [int(enemy.x), int(enemy.y)], BALL_SIZE)
    

    原代码里把x/y赋值为change_x/change_y的逻辑完全颠倒,也是移动异常的关键原因。

其他细节优化

  • Enemy类继承自pygame.sprite.Sprite,但缺少必需的image和rect属性,后续如果用精灵组做碰撞检测会出错,建议补上:
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.x = 0
        self.y = 0
        self.speed = 2
        self.change_x = 0
        self.change_y = 0
        # 添加Sprite必需的属性
        self.image = pygame.Surface((BALL_SIZE*2, BALL_SIZE*2), pygame.SRCALPHA)
        pygame.draw.circle(self.image, WHITE, (BALL_SIZE, BALL_SIZE), BALL_SIZE)
        self.rect = self.image.get_rect()
    
  • 确保代码开头导入了必要模块:import pygame、import math、import random,并且完成pygame初始化(pygame.init())、屏幕设置、颜色和常量定义,否则代码无法运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 14:15:34