Math: `tan(angle) = dy/dx` so `angle = arctangle(dy/dx)`
Get positions for mouse and gun/player.
```
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
```
Calculate distance (dx, dy) between mouse and gun/player
```
dx = mouse_x - player_x
dy = mouse_y - player_y
```
Now `dy/dx` should give `tangle or angle` so I can use `arctangle` to get `angle` (in `radians`).
```
angle_radians = math.atan2(dy, dx)
angle = math.degrees(angle_radians)
```
And now rotate image with `-angle` (to rotate in correct direction).
```
player_image = pygame.transform.rotate(original_player_image, angle).convert_alpha()
```
To get better quality of rotated image you should always use original image.
You also have to use `convert_alpha()` to get colors in `RGBA` with transparent background.
And new `Image` needs new `Rect` with position from previous `Rect`.
```
player_rect = player_image.get_rect(centerx=player_x, centery=player_y)
```
---
Full working code. It rotates player to mouse position (even when it moves).
I used `set_caption` to display positions and angle in window's title.
```
import pygame
import os
import math
# --- constants --- # PEP8: `UPPER_CASE_NAMES` for constants
WIDTH, HEIGHT = 900, 500
WHITE = (255, 255, 255)
RED = (255, 0, 0)
FPS = 60
VEL = 5
BULLET_VEL = 7
# --- main --- # PEP8: `lower_case_names` for variables
pygame.init()
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('First Person Shooter')
#CHARACTER_PLAYER_ONE = pygame.image.load(os.path.join('Python', 'player_one.png'))
original_player_image = pygame.surface.Surface((100, 100)).convert_alpha()
original_player_image.fill((255,0,0,255))
original_player_image = pygame.transform.rotate(pygame.transform.scale(original_player_image, (55, 40)), 90)
player_image = original_player_image.copy()
player_rect = player_image.get_rect(centerx=100, centery=300)
def draw_window():
WIN.fill(WHITE)
WIN.blit(player_image, player_rect)
pygame.display.update()
def one_handle_movement(keys_pressed, one):
if keys_pressed[pygame.K_a] and one.left - VEL > -15: # left
one.x -= VEL
if keys_pressed[pygame.K_d] and one.right + VEL < 925: # right
one.x += VEL
if keys_pressed[pygame.K_w] and one.top - VEL > -15: # up
one.y -= VEL
if keys_pressed[pygame.K_s] and one.bottom + VEL < 500: # down
one.y += VEL
def main():
global player_image
global player_rect
bullets = []
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet = pygame.Rect()
# get positions
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x, player_y = player_rect.center
# get angle
dx = mouse_x - player_x
dy = mouse_y - player_y
angle = math.degrees(math.atan2(dy, dx))
pygame.display.set_caption(f"player: {player_x}, {player_y} | mouse: {mouse_x}, {mouse_y} | angle: {angle}")
# rotate
player_image = pygame.transform.rotate(original_player_image, -angle).convert_alpha()
# assign original center to new rectagle
player_rect = player_image.get_rect(centerx=player_x, centery=player_y)
# ---
keys_pressed = pygame.key.get_pressed()
one_handle_movement(keys_pressed, player_rect)
draw_window()
pygame.quit()
if __name__ == '__main__':
main()
```
---
**EDIT:**
Pygame has [pygame.math.Vector2.angle_to()](https://web.archive.org/web/20211006193710/http://www.pygame.org/docs/ref/math.html#pygame.math.Vector2.angle_to) to calculate angle (in degrees) between two verctors (points) but for some reason I got wrong results and couldn't find mistake.
```
mouse = pygame.mouse.get_pos()
player = player_rect.center
angle = pygame.math.Vector2(player).angle_to(mouse)
```
BTW: today pygame doc is not accessible so I used link to its copy on archive.org.
---
**EDIT:**
This gives correct `angle`
```
mouse = pygame.mouse.get_pos()
player = player_rect.center
dist = pygame.math.Vector2(mouse) - pygame.math.Vector2(player)
angle = pygame.math.Vector2().angle_to(dist)
```
---
```
def main():
global player_image
global player_rect
bullets = []
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet = pygame.Rect()
# get positions
mouse = mouse_x, mouse_y = pygame.mouse.get_pos()
player = player_x, player_y = player_rect.center
# get angle
wrong_angle = pygame.math.Vector2(mouse).angle_to(player) # gives results different then I expect
dist = pygame.math.Vector2(mouse) - pygame.math.Vector2(player)
angle = pygame.math.Vector2().angle_to(dist) # gives results different then I expect
pygame.display.set_caption(f"player: {player_x}, {player_y} | mouse: {mouse_x}, {mouse_y} | angle: {angle} | wrong: {wrong_angle}")
# rotate
player_image = pygame.transform.rotate(original_player_image, -angle).convert_alpha()
# assign original center to new rectagle
player_rect = player_image.get_rect(centerx=player_x, centery=player_y)
# ---
keys_pressed = pygame.key.get_pressed()
one_handle_movement(keys_pressed, player_rect)
draw_window()
pygame.quit()
```