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?
-
3so you've already solve the problem of making the player face the location of the mouse click, so all you really need to do is listen for the mouse movement and update the player in the same way you do with a click. so the problem to solve is _how to listen to the mouse movements in pygame_? – Dan D. Jul 21 '11 at 12:21
5 Answers
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

- 324
- 2
- 7
- 14
-
2if `event.type == pygame.MOUSEMOTION`, you can just use `event.pos` to get the mouse position, rather than call `pygame.mouse.get_pos()`. – Dan D. Jul 21 '11 at 12:26
-
Its Working But Pygames 'pygame.transform.rotate' uses Angle so how do i do that? – Jul 21 '11 at 12:46
-
@Firetryer: Learn vector arithmetic. http://en.wikipedia.org/wiki/Dot_product#Properties – JAB Jul 21 '11 at 13:42
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.

- 765
- 7
- 17
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)
-
i just tested the nose of ship image look the mouse and follow ,try your self – Manfre Manfre Jul 07 '17 at 07:44
_, 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)

- 19,980
- 5
- 34
- 48
-
@Coder22 it works correctly for me and the triangle rotates towards the mouse. What exactly doesn't work? – skrx Apr 21 '18 at 18:27
if event.type == MOUSEBUTTONDOWN:
mouseX, mouseY = pygame.mouse.get_pos()
vetMouse=pygame.math.Vector2(mouseX,mouseY)
gradiRot=vetMouse.angle_to(vetShip)

- 82,685
- 13
- 120
- 165