使精灵一步步移动到鼠标点击位置 [英] Make a sprite move to the mouse click position step by step

查看:24
本文介绍了使精灵一步步移动到鼠标点击位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 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) 但我就是想不通,尤其是不管对角线有什么角度都保持速度不变,并且考虑到 xy 值(发货或点击)可能比各自更大或更小.

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 trueMOUSEBUTTONDOWN 事件,以确保 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,然后取postarget_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.

现在您知道如何从 postarget_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆