Pygame Making A Sprite Face The Mouse

左心房为你撑大大i 提交于 2020-01-10 04:18:17

问题


Im New To Pygame But Kinda OK On Python, Im Creating A Zombie Shooting Game With an overhead view.
I managed to make the character move when pressing the arrow keys. But now i need to get the player to FACE the mouse/cursor without clicking the screen all the time.
Any Help?


回答1:


for event in pygame.event.get():
    if event.type == MOUSEMOTION:
        mousex, mousey = event.pos
        # build a vector between player position and mouse position
        moveVector = (mousex-playerx, mousey-playery)

        """
        compute the angle of moveVector from current vector that player is facing (faceVector).
        you should be keeping and updating this unit vector, with each mouse motion
        assume you have initial facing vector as (1,0) - facing East
        """

        # compute angle as in [1]

        # rotate the image to that angle and update faceVector

[1] - How to Find the Angle Between Two Vectors: http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Your image may lose quality when rotated at a small angle. It's discussed in Pygame documentation page: http://pygame.org/docs/ref/transform.html#pygame.transform.rotate




回答2:


import math

mouseX, mouseY = pygame.mouse.get_pos()
playerX, playerY = player.get_pos()

angle = math.atan2(playerX-mouseX, playerY-mouseY)

You might have to fiddle with the order of subtraction (ie, it might be mousePosition-playerPosition) or the order of the x and y parameters to atan2 (ie, you might need to pass in the Y difference as the first parameter rather than the X) but that depends on your coordinate system.




回答3:


working code :

import pygame, sys, math
from pygame.locals import *


#converte in base ai gradi le cordinate x,y
#maxXY= surface MaxXY
#gradoRot = grado di rotazione
#distXY = spostamento in x,y lungo il vettore di cordinate locali dalle cordinate x,y

#movement from one point to another
def Move(t0,t1,psx,psy,speed):
    global mx
    global my

    speed = speed

    distance = [t0 - psx, t1 - psy]
    norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
    direction = [distance[0] / norm, distance[1 ] / norm]

    bullet_vector = [direction[0] * speed, direction[1] * speed]
    return bullet_vector
# Main Function
if __name__ == '__main__':
    pygame.init()
    FPS = 30 # frames per second setting
    fpsClock = pygame.time.Clock()
    # set up the window
    DISPLAYSURF = pygame.display.set_mode((800, 600), 0, 32)
    alfhaSurface = DISPLAYSURF.convert_alpha() 
    pygame.display.set_caption('test')
    shipImg = pygame.image.load('ship.png')
    shipImgcpy=shipImg.copy()
    vetShip=pygame.math.Vector2(400,300)
    gradi = 0
    gradiRot=0
    mouseX=0
    mouseY=0
    SHIP_W=40
    SHIP_H=40
    vetMouse=pygame.math.Vector2(mouseX,mouseY)
    #main loop
    while True:
        DISPLAYSURF.fill((0,0,0)) 
        alfhaSurface.fill((0,0,0))
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()  
            if event.type == MOUSEBUTTONDOWN:
                mouseX, mouseY = pygame.mouse.get_pos()
                vetMouse=pygame.math.Vector2(mouseX,mouseY)

                gradiRot=**math.atan2(vetShip.x-vetMouse.x, vetShip.y-vetMouse.y)**
                gradiRot=**math.degrees(gradiRot)**
                pygame.display.set_caption(""+str(gradi) +"="+ str(gradiRot)+" "+ str(vetMouse.angle_to(vetShip)) ) 
        pygame.draw.line(alfhaSurface, (255,255,255), (vetShip.x+SHIP_W,vetShip.y+SHIP_H),(vetMouse.x,vetMouse.y),1)                      
        if gradi != int(gradiRot) :
            if gradiRot > gradi and gradi != gradiRot :
                gradi=gradi+1

            if gradiRot < gradi and gradi != gradiRot :
                gradi=gradi-1    

            shipImgcpy=pygame.transform.rotate(shipImg.copy(),gradi) 

        elif int(vetMouse.distance_to(vetShip)) >0:
            posNext=Move(mouseX,mouseY,vetShip.x+SHIP_W,vetShip.y+SHIP_H,1)                  
          vetShip=pygame.math.Vector2(vetShip.x+posNext[0],vetShip.y+posNext[1])


        alfhaSurface.blit(shipImgcpy, tuple(vetShip))
        DISPLAYSURF.blit(alfhaSurface,(0,0))
        pygame.display.update()
        fpsClock.tick(FPS)   



回答4:


_, angle = (pg.mouse.get_pos()-self.pos).as_polar()

This line first calculates a vector to the mouse position (self.pos has to be a pygame.math.Vector2) and .as_polar() returns the polar coordinates of the vector which consist of the radial distance and the angle. Finally use the negative angle (because pygame's y-axis is flipped) to rotate the image of the sprite and recalculate the rect.

import pygame as pg


class Player(pg.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.image = pg.Surface((50, 30), pg.SRCALPHA)
        pg.draw.polygon(
            self.image,
            pg.Color('dodgerblue1'),
            ((1, 1), (49, 15), (1, 29)))
        self.orig_img = self.image
        self.rect = self.image.get_rect(center=pos)
        self.pos = pg.math.Vector2(pos)
        self.vel = pg.math.Vector2(0, 0)

    def update(self):
        self.rotate()
        self.pos += self.vel
        self.rect.center = self.pos

    def rotate(self):
        _, angle = (pg.mouse.get_pos()-self.pos).as_polar()
        self.image = pg.transform.rotozoom(self.orig_img, -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()
    all_sprites.add(Player((300, 200)))

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

math.atan2 can be used as an alternative.

def rotate(self):
    rel_x, rel_y = pg.mouse.get_pos() - self.pos
    angle = -math.degrees(math.atan2(rel_y, rel_x))
    self.image = pg.transform.rotozoom(self.orig_img, angle, 1)
    self.rect = self.image.get_rect(center=self.pos)



回答5:


if event.type == MOUSEBUTTONDOWN:
    mouseX, mouseY = pygame.mouse.get_pos()
    vetMouse=pygame.math.Vector2(mouseX,mouseY)
    gradiRot=vetMouse.angle_to(vetShip)


来源:https://stackoverflow.com/questions/6775897/pygame-making-a-sprite-face-the-mouse

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