我正在Pygame写一个小海盗游戏。如果你在帝国全面战争中玩过海战,你就会知道我想要实现的目标:
船的精灵位于(x1|y1)
位置。播放器现在点击屏幕上的(x2|y2)
位置。精灵现在应该以{{1}}作为新的位置 - 一步一步走到那里,而不是立即在那里发光。
我发现它与矩形(x2|y2)
,(x1|y1)
,(x1|y2)
,(x2|y2)
的对角线有关,但我无法弄明白,尤其是考虑到任何一个(船舶或点击)的(x2|y1)
和x
值可能比相应的另一个更大或更小,而不是保持速度相同,无论对角线具有什么角度。
这个小片段是我最后一次编写工作函数的尝试:
y
这里的“船只”只是一个粉红色的像素。我点击屏幕时显示的反应是大致向我的点击方向移动,但是停在我点击的点看似随机的距离。
变量是:
def update(self, new_x, new_y, speed, screen, clicked):
if clicked:
self.xshift = (self.x - new_x)
self.yshift = ((self.y - new_y) / (self.x - new_x))
if self.x > (new_x + 10):
self.x -= 1
self.y -= self.yshift
elif self.x > new_x and self.x < (new_x + 10):
self.x -= 1
self.y -= self.yshift
elif self.x < (new_x - 10):
self.x += 1
self.y += self.yshift
elif self.x < new_x and self.x < (new_x - 10):
self.x += 1
self.y += self.yshift
else:
self.x += 0
self.y += 0
screen.set_at((self.x, self.y), (255, 0, 255))
,new_x
=鼠标点击的位置
new_y
=恒定速度取决于船型
speed
= clicked
事件设置true
,以确保仅在玩家点击时定义自身的xshift和yshift,而不是每个帧再次定义。
如何使船舶从当前位置平稳移动到玩家点击的位置?
答案 0 :(得分:0)
说当前位置为pos
,玩家点击的点为target_pos
,然后在pos
和target_pos
之间取向。
现在您知道如何从pos
到target_pos
,但要以恒定速度(而不是一次整个距离)移动,您必须对矢量进行标准化,并应用速度常数通过标量乘法。
就是这样。
完整示例: (相关代码位于Ship.update
方法中)
import pygame
class Ship(pygame.sprite.Sprite):
def __init__(self, speed, color):
super().__init__()
self.image = pygame.Surface((10, 10))
self.image.set_colorkey((12,34,56))
self.image.fill((12,34,56))
pygame.draw.circle(self.image, color, (5, 5), 3)
self.rect = self.image.get_rect()
self.pos = pygame.Vector2(0, 0)
self.set_target((0, 0))
self.speed = speed
def set_target(self, pos):
self.target = pygame.Vector2(pos)
def update(self):
move = self.target - self.pos
move_length = move.length()
if move_length < self.speed:
self.pos = self.target
elif move_length != 0:
move.normalize_ip()
move = move * self.speed
self.pos += move
self.rect.topleft = list(int(v) for v in self.pos)
def main():
pygame.init()
quit = False
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
group = pygame.sprite.Group(
Ship(1.5, pygame.Color('white')),
Ship(3.0, pygame.Color('orange')),
Ship(4.5, pygame.Color('dodgerblue')))
while not quit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.MOUSEBUTTONDOWN:
for ship in group.sprites():
ship.set_target(pygame.mouse.get_pos())
group.update()
screen.fill((20, 20, 20))
group.draw(screen)
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()