Pygame如何实现多个敌人实例生成与独立追踪逻辑
Pygame多敌人同屏实现方案
你现在的代码出不了多个敌人,根本原因是敌人的坐标、移动逻辑全绑在全局变量上,同一时间只能存1个敌人的状态。要实现多敌人独立运行,改3个核心位置就行,顺便可以修掉现有代码里几个隐性bug。
先修现有代码的小问题
- 你重复写了2次
Button类,删掉前面没有draw方法的空定义,只留带交互逻辑的版本就行 - 主循环里调了2次
pygame.display.flip(),一帧刷多次屏会闪,删掉多余的调用,所有内容画完之后只刷1次 FPS设成1000没用,普通显示器刷新率就60,锁60帧既能保证移动流畅,还能少占CPU
核心改动
1. 写个Enemy类封装敌人的所有属性和逻辑
跟你写Button类的思路一样,把每个敌人自己的坐标、移速、外观,还有追踪玩家、转方向、画到屏幕上的逻辑全封到类里,每个生成的敌人实例状态完全独立,不会互相串:
import random # 记得在代码顶部加这个导入,用来随机刷敌人初始位置 class Enemy: def __init__(self): # 每个敌人的初始坐标随机生成在屏幕四周边缘,不会一开始全叠在一个点 spawn_side = random.randint(0,3) if spawn_side == 0: # 上边 self.x = random.randint(0, SCREEN_WIDTH) self.y = 0 elif spawn_side == 1: # 右边 self.x = SCREEN_WIDTH self.y = random.randint(0, SCREEN_HEIGHT) elif spawn_side == 2: # 下边 self.x = random.randint(0, SCREEN_WIDTH) self.y = SCREEN_HEIGHT else: # 左边 self.x = 0 self.y = random.randint(0, SCREEN_HEIGHT) self.vel = Enemy_Vel self.image = Enemy # 直接复用你之前加载好的敌人图片 def update(self, player_x, player_y): # 每个敌人自己的追踪逻辑,只改自己的坐标 if self.x < player_x: self.x += self.vel if self.x > player_x: self.x -= self.vel if self.y < player_y: self.y += self.vel if self.y > player_y: self.y -= self.vel def draw(self, screen): # 每个敌人自己算旋转角度、画到屏幕上 enemy_rect = self.image.get_rect(center=(self.x, self.y)) dx, dy = player_x - enemy_rect.centerx, player_y - enemy_rect.centery angle = math.degrees(math.atan2(-dy, dx)) - correction_angle rot_image = pygame.transform.rotate(self.image, angle) rot_image_rect = rot_image.get_rect(center=enemy_rect.center) screen.blit(rot_image, rot_image_rect.topleft)
2. 用列表存所有敌人实例
把你之前写的全局变量Enemy_x = 100、Enemy_y = 100删掉,换成一个空列表存所有生成的敌人,自己改同屏敌人数量就行:
enemy_list = [] ENEMY_COUNT = 5 # 想要多少敌人改这个数
在你点开始按钮进游戏的逻辑里,循环生成对应数量的敌人存进列表:
if start_button.draw() == True and Start == False: print('START') Start = True player_x = 225 player_y = 400 # 清空上一局的敌人,重新生成 enemy_list.clear() for _ in range(ENEMY_COUNT): enemy_list.append(Enemy())
3. 主循环里遍历所有敌人统一更新、绘制
把原来写死的单个敌人移动、旋转、画的代码全删掉,换成遍历敌人列表,逐个调更新和绘制方法:
if Start == True: screen.fill((SCREEN_COLOR)) screen.blit(Background,(0, 0)) # 你原来写的玩家移动、旋转、绘制逻辑全保留,不用改 player_pos = player_x, player_y player_rect = player.get_rect(center = player_pos) mx, my = pygame.mouse.get_pos() dx, dy = mx - player_rect.centerx, my - player_rect.centery angle = math.degrees(math.atan2(-dy, dx)) - correction_angle rot_image = pygame.transform.rotate(player, angle) rot_image_rect = rot_image.get_rect(center = player_rect.center) screen.blit(rot_image, rot_image_rect.topleft) # 替换成遍历敌人的逻辑 for enemy in enemy_list: enemy.update(player_x, player_y) enemy.draw(screen)
后续可以扩展的功能
- 想要动态刷怪,就在主循环里加判断,只要当前列表里的敌人数量小于你设的上限,每隔几秒往列表里加新的
Enemy()实例就行 - 想要做击杀判定,只要判断子弹和敌人的碰撞,碰撞到就把对应敌人实例从
enemy_list里移除即可
内容的提问来源于stack exchange,提问作者LegoSuperBall
相关产品推荐
相关产品推荐

