简体   繁体   中英

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

( 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)

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM