【问题标题】:Make a sprite move to the mouse click position step by step让精灵一步步移动到鼠标点击位置
【发布时间】:2013-04-29 21:54:56
【问题描述】:

我正在用 Pygame 写一个小海盗游戏。如果你在《帝国全面战争》中玩过海战,你就会知道我想要实现的目标:

船的精灵位于(x1|y1)。玩家现在点击屏幕上的(x2|y2)。精灵现在应该将(x2|y2) 作为它的新位置 - 一步一步地去那里,而不是立即在那里发光。

我发现它与矩形的对角线有关 (x1|y1),(x1|y2),(x2|y2),(x2|y1) 但我就是想不通,尤其是与保持速度无关无论对角线的角度如何,并且考虑到任一(ship 或 click)的 xy 值可能比另一个更大或更小,都相同。

这个小sn-p是我最后一次尝试写一个工作函数:

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 = 由MOUSEBUTTONDOWN 事件设置true,以确保xshift和 self 的 yshift 仅在玩家单击时定义,而不是在每一帧再次定义。

如何让飞船从当前位置平稳移动到玩家点击的位置?

【问题讨论】:

    标签: python pygame


    【解决方案1】:

    假设当前位置为pos,玩家点击的点为target_pos,则取postarget_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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-13
      • 2019-08-02
      • 1970-01-01
      • 2014-10-09
      • 2019-03-12
      • 2011-06-19
      • 2014-10-04
      相关资源
      最近更新 更多