Pygame haciendo una cara de Sprite el ratón

Soy nuevo en Pygame, pero está bastante bien en Python, estoy creando un juego de disparos de zombies con una vista aérea.
Me las arreglé para hacer que el personaje se moviera al presionar las teclas de flecha. Pero ahora necesito hacer que el jugador ENFACE el mouse / cursor sin hacer clic en la pantalla todo el tiempo.
¿Alguna ayuda?

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] – Cómo encontrar el ángulo entre dos vectores: http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Su imagen puede perder calidad cuando se gira en un ángulo pequeño. Se discute en la página de documentación de Pygame: http://pygame.org/docs/ref/transform.html#pygame.transform.rotate

 import math mouseX, mouseY = pygame.mouse.get_pos() playerX, playerY = player.get_pos() angle = math.atan2(playerX-mouseX, playerY-mouseY) 

Es posible que tenga que jugar con el orden de sustracción (es decir, puede ser mousePosition-playerPosition) o el orden de los parámetros x e y para atan2 (es decir, puede que tenga que pasar la diferencia Y como primer parámetro en lugar de X) pero eso depende de tu sistema de coordenadas.

código de trabajo:

 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) 
 _, angle = (pg.mouse.get_pos()-self.pos).as_polar() 

Esta línea primero calcula un vector para la posición del mouse ( self.pos debe ser un pygame.math.Vector2 ) y .as_polar() devuelve las coordenadas polares del vector que consisten en la distancia radial y el ángulo. Finalmente use el ángulo negativo (porque el eje y de pygame está volteado) para rotar la imagen del sprite y recalcular el rectángulo.

 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 puede usar math.atan2 como alternativa.

 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) 
 if event.type == MOUSEBUTTONDOWN: mouseX, mouseY = pygame.mouse.get_pos() vetMouse=pygame.math.Vector2(mouseX,mouseY) gradiRot=vetMouse.angle_to(vetShip)