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