Pygame Making A Sprite Face The Mouse
Solution 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
Solution 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.
Solution 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)
Solution 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)
Solution 5:
if event.type == MOUSEBUTTONDOWN:
mouseX, mouseY = pygame.mouse.get_pos()
vetMouse=pygame.math.Vector2(mouseX,mouseY)
gradiRot=vetMouse.angle_to(vetShip)
Post a Comment for "Pygame Making A Sprite Face The Mouse"