使精灵一步步移动到鼠标点击位置 [英] Make a sprite move to the mouse click position step by step
问题描述
我正在 Pygame 中编写一个小海盗游戏.如果你在《帝国全面战争》中玩过海战,你就会知道我想要实现的目标:
I'm writing a little pirate game in Pygame. If you played sea battles in Empires Total War, you have an idea of what I would like to achieve:
飞船的精灵位于 (x1|y1)
位置.玩家现在点击屏幕上的 (x2|y2)
位置.精灵现在应该将 (x2|y2)
作为它的新位置 - 通过一步一步地到达那里,而不是立即发出光芒.
The ship's sprite is at position (x1|y1)
. The player now clicks at position (x2|y2)
on the screen. The sprite is now supposed to take (x2|y2)
as its new position - by going there step by step, not by beaming there instantly.
我发现它与矩形的对角线有关 (x1|y1)
,(x1|y2)
,(x2|y2)
,(x2|y1)
但我就是想不通,尤其是不管对角线有什么角度都保持速度不变,并且考虑到 x
和 y
值(发货或点击)可能比各自更大或更小.
I figured out that it has something to do with the diagonal of the rectangle (x1|y1)
,(x1|y2)
,(x2|y2)
,(x2|y1)
but I just can't figure it out, especially not with keeping the speed the same no matter what angle that diagonal has and considering that the x
and y
values of either (ship or click) might be bigger or smaller than the respective other.
这个小片段是我最后一次尝试编写一个工作函数:
This little snippet is my last try to write a working function:
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))
这里的船"只是一个粉红色的像素.它在我点击屏幕时显示的反应是粗略地向我的点击移动,但在我点击的点的看似随机的距离处停止.
The "ship" is just a pink pixel here. The reaction it shows upon my clicks onto the screen is to move roughly towards my click but to stop at a seemingly random distance of the point I clicked.
变量是:
new_x
, new_y
= 鼠标点击位置speed
= 恒定速度取决于船舶类型clicked
= set true
由 MOUSEBUTTONDOWN
事件,以确保 self 的 xshift 和 yshift 只在玩家点击时定义,而不是每一帧再次.
new_x
, new_y
= position of mouseclick
speed
= constant speed depending on ship types
clicked
= set true
by the MOUSEBUTTONDOWN
event, to ensure that the xshift and yshift of self are only defined when the player clicked and not each frame again.
如何让飞船从当前位置平滑移动到玩家点击的位置?
How can I make the ship move smoothly from its current position to the point the player clicked?
推荐答案
说当前位置是pos
,玩家点击的点是target_pos
,然后取pos
和 target_pos
之间的向量.
Say the current position is pos
, and the point the player clicked is target_pos
, then take the vector between pos
and target_pos
.
现在您知道如何从 pos
到 target_pos
,但是要以恒定速度移动(而不是一次移动整个距离),您必须对向量进行归一化,并通过标量乘法应用速度常数.
Now you know how to get from pos
to target_pos
, but to move in constant speed (and not the entire distance at once), you have to normalize the vector, and apply a speed constant by scalar multiplication.
就是这样.
完整示例: (相关代码在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()
这篇关于使精灵一步步移动到鼠标点击位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!