PYTHON & PYGAME How to move and rotate polygon towards the mouse position?

你说的曾经没有我的故事 提交于 2019-12-11 07:30:04

问题


(EDIT: The rotation doesn't matter too much to me anymore - just the movement. I am still curious and would love to know how to do the rotation however.)

def angle_between(p1, p2):
    ang1 = np.arctan2(*p1[::-1])
    ang2 = np.arctan2(*p2[::-1])
    return (ang1 - ang2) % (2 * np.pi)  



class Minion:  # Shape: Triangle
        def __init__(self):
            self.rotation = 0
            self.position = (200,200)
            self.radius = 50
            self.vertices = ((1,1), (10,10), (1,10))

        def determine_vertices(self):
            x = self.position[0]
            y = self.position[1]
            target_pos = pygame.mouse.get_pos()
            x2 = target_pos[0]
            y2 = target_pos[1]
            # Will start off pointing to the right (pre-rotation)
            vertex_A = (x + self.radius, y)
            vertex_B = (x + (cos(2*pi/3))*self.radius, y + (sin(2*pi/3))*self.radius)
            vertex_C = (x + (cos(4*pi/3))*self.radius, y + (sin(4*pi/3))*self.radius)
            self.vertices = (vertex_A,vertex_B,vertex_C)  # NOT YET ROTATED
            # Now let's find the angle between my location and the target location
            self.rotation = angle_between((x,y),(x2,y2))
            # Here is where I am stuck

Okay, so I have found the location of my vertices before they are rotated, and have also found the angle (in radians) in which I want to rotate it towards. Here are the links I've looked at:

Results I wasn't looking for

Didn't understand / know how to convert to my code

Graph data instead of raw data

EDIT: I have changed my vertex formulas to rotate but they rotate the wrong direction and way too fast. I have no clue why. Here is the code:

vertex_A = (x + (cos(self.rotation))*self.radius, y + (sin(self.rotation))*self.radius)
vertex_B = (x + (cos((2*pi/3) + self.rotation))*self.radius, y + (sin((2*pi/3) + self.rotation))*self.radius)
vertex_C = (x + (cos((4*pi/3) + self.rotation))*self.radius, y + (sin((4*pi/3) + self.rotation))*self.radius)

回答1:


To move an object towards the mouse, you can use vectors. Just subtract the position from the mouse pos, normalize the resulting vector and mutliply it by the desired speed. That gives you the velocity vector which you can add to the self.pos each frame (also update the rect which serves as the blit position and for collision detection).

Call the Vector2.as_polar method (it returns the polar coordinates) to get the angle of the vector and then use it to rotate the original image.

import pygame as pg
from pygame.math import Vector2


class Entity(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((50, 30), pg.SRCALPHA)  # A transparent image.
        # Draw a triangle onto the image.
        pg.draw.polygon(self.image, pg.Color('dodgerblue2'),
                        ((0, 0), (50, 15), (0, 30)))
        # A reference to the original image to preserve the quality.
        self.orig_image = self.image
        self.rect = self.image.get_rect(center=pos)
        self.vel = Vector2(0, 0)
        self.pos = Vector2(pos)

    def update(self):
        # Subtract the pos vector from the mouse pos to get the heading,
        # normalize this vector and multiply by the desired speed.
        self.vel = (pg.mouse.get_pos() - self.pos).normalize() * 5

        # Update the position vector and the rect.
        self.pos += self.vel
        self.rect.center = self.pos

        # Rotate the image.
        # `Vector2.as_polar` returns the polar coordinates (radius and angle).
        radius, angle = self.vel.as_polar()
        self.image = pg.transform.rotozoom(self.orig_image, -angle, 1)
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    entity = Entity((100, 300), all_sprites)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        all_sprites.update()
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()


来源:https://stackoverflow.com/questions/47163486/python-pygame-how-to-move-and-rotate-polygon-towards-the-mouse-position

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!