我怎样才能让敌人向玩家移动并在pygame中预测它的路径

我正在制作一个 pygame 游戏,我希望我的敌人跟随玩家并预测它的路径。我不只是想缩短玩家和敌人之间的距离。敌人的数量会根据等级而定,每升3级就会增加一个新的敌人。我附上了我的整个代码和一张截图,显示我的敌人目前正在直线移动。


http://img3.mukewang.com/63a175270001976b19111076.jpg

翻翻过去那场雪
浏览 98回答 1
1回答

泛舟湖上清波郎朗

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

相关分类

Python