泛舟湖上清波郎朗
为此你需要一些矢量数学,所以我建议重构你的代码并学习如何使用Sprites;你可以在这里找到一个例子。要找到问题的答案(“预测路径”),您可以在 google 上搜索intercept vectoror pursuit vector。那应该会产生一些结果,例如如何计算截距的向量?或计算拦截矢量。例如,我翻译了第二个问题的最后一个答案并将其复制/粘贴到我的一个答案中,因为 a) 我懒得再写一遍 b) 有一个代码点我必须更改才能实现拦截逻辑(EnemyController类)。import pygameimport randomimport mathfrom pygame import Vector2SPRITE_SHEET = NoneGREEN_SHIP = pygame.Rect(0, 292, 32, 32)RED_SHIP = pygame.Rect(0, 324, 32, 32)BLUE_SHIP = pygame.Rect(0, 356, 32, 32)YELLOW_SHIP = pygame.Rect(0, 388, 32, 32)class EnemyController: def __init__(self, target): self.direction = Vector2(1, 0) self.target = target def update(self, sprite, events, dt): k = self.target.vel.magnitude() / sprite.speed; distance_to_target = (sprite.pos - self.target.pos).magnitude() b_hat = self.target.vel c_hat = sprite.pos - self.target.pos CAB = b_hat.angle_to(c_hat) ABC = math.asin(math.sin(CAB) * k) ACB = math.pi - (CAB + ABC) j = distance_to_target / math.sin(ACB) a = j * math.sin(CAB) b = j * math.sin(ABC) time_to_collision = b / self.target.vel.magnitude() if self.target.vel.magnitude() > 0 else 1 collision_pos = self.target.pos + (self.target.vel * time_to_collision) v = sprite.pos - collision_pos if v.length() > 0: sprite.direction = -v.normalize() if v.length() <= 10: sprite.pos = pygame.Vector2(400, 100)class PlayerController: movement = { pygame.K_UP: Vector2( 0, -1), pygame.K_DOWN: Vector2( 0, 1), pygame.K_LEFT: Vector2(-1, 0), pygame.K_RIGHT: Vector2( 1, 0) } def update(self, sprite, events, dt): pressed = pygame.key.get_pressed() v = Vector2(0, 0) for key in PlayerController.movement: if pressed[key]: v += PlayerController.movement[key] sprite.direction = v for e in events: if e.type == pygame.KEYDOWN: if e.key == pygame.K_SPACE: sprite.groups()[0].add(Explosion(sprite.pos))class Animation: def __init__(self, frames, speed, sprite): self.sprite = sprite self.speed = speed self.ticks = 0 self.frames = frames self.running = 0 self.start() def cycle_func(self, iterable): saved = [] for element in iterable: yield element saved.append(element) if hasattr(self.sprite, 'on_animation_end'): self.sprite.on_animation_end() while saved: for element in saved: yield element if hasattr(self.sprite, 'on_animation_end'): self.sprite.on_animation_end() def stop(self): self.running = 0 if self.idle_image: self.sprite.image = self.idle_image def start(self): if not self.running: self.running = 1 self.cycle = self.cycle_func(self.frames) self.sprite.image = next(self.cycle) def update(self, dt): self.ticks += dt if self.ticks >= self.speed: self.ticks = self.ticks % self.speed if self.running: self.sprite.image = next(self.cycle)class AnimatedSprite(pygame.sprite.Sprite): def __init__(self, pos, frames, speed): super().__init__() self.animation = Animation(frames, speed, self) self.rect = self.image.get_rect(center=pos) self.pos = Vector2(pos) self.animation.start() def update(self, events, dt): self.animation.update(dt)class Explosion(AnimatedSprite): frames = None def __init__(self, pos): if not Explosion.frames: Explosion.frames = parse_sprite_sheet(SPRITE_SHEET, pygame.Rect(0, 890, 64, 64), 6, 4) super().__init__(pos, Explosion.frames, 50) def on_animation_end(self): self.kill()class DirectionalImageSprite(pygame.sprite.Sprite): directions = [(1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1),(0,0)] def __init__(self, pos, directional_images_rect): super().__init__() images = parse_sprite_sheet(SPRITE_SHEET, directional_images_rect, 9, 1) self.images = { x: img for (x, img) in zip(DirectionalImageSprite.directions, images) } self.direction = Vector2(0, 0) self.image = self.images[(self.direction.x, self.direction.y)] self.rect = self.image.get_rect(center=pos) self.pos = pygame.Vector2(pos)class SpaceShip(DirectionalImageSprite): def __init__(self, pos, controller, directional_images_rect): super().__init__(pos, directional_images_rect) self.controller = controller self.speed = 2 self.vel = pygame.Vector2(0, 0) def update(self, events, dt): super().update(events, dt) if self.controller: self.controller.update(self, events, dt) self.vel = Vector2(0, 0) if (self.direction.x, self.direction.y) in self.images: self.image = self.images[(self.direction.x, self.direction.y)] if self.direction.length(): self.vel = self.direction.normalize() * self.speed self.pos += self.vel self.rect.center = int(self.pos[0]), int(self.pos[1])def parse_sprite_sheet(sheet, start_rect, frames_in_row, lines): frames = [] rect = start_rect.copy() for _ in range(lines): for _ in range(frames_in_row): frame = sheet.subsurface(rect) frames.append(frame) rect.move_ip(rect.width, 0) rect.move_ip(0, rect.height) rect.x = start_rect.x return framesdef main(): screen = pygame.display.set_mode((800, 600)) global SPRITE_SHEET SPRITE_SHEET = pygame.image.load("ipLRR.png").convert_alpha() clock = pygame.time.Clock() dt = 0 player = SpaceShip((400, 300), PlayerController(), YELLOW_SHIP) enemy = SpaceShip((400, 100), EnemyController(player), GREEN_SHIP) enemy.speed = 4 all_sprites = pygame.sprite.Group( player, enemy ) while True: events = pygame.event.get() for e in events: if e.type == pygame.QUIT: return all_sprites.update(events, dt) screen.fill((0, 0, 0)) all_sprites.draw(screen) pygame.display.flip() dt = clock.tick(120)main()https://i.stack.imgur.com/lapWw.gif