0
\$\begingroup\$

Basically, I'm doing a game for a school project and I am not really sure how to make a player point towards the mouse pointer in a pygame tab. also if anyone has ideas of how i could point a bullet towards the mouse and then fire in the direction of the mouse after i click fire (without continuously changing angles towards the mouse pointer) that would be awesome

Here is my code:

import pygame import os WIDTH, HEIGHT = 900, 500 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('First Person Shooter') WHITE = (255,255,255) FPS = 60 VEL = 5 BULLET_VEL = 7 CHARACTER_PLAYER_ONE = pygame.image.load(os.path.join('Python', 'player_one.png')) CHARACTER_PLAYER_ONE = pygame.transform.rotate(pygame.transform.scale(CHARACTER_PLAYER_ONE, (55, 40)), 90) def draw_window(one): WIN.fill(WHITE) WIN.blit(CHARACTER_PLAYER_ONE, (one.x, one.y)) pygame.display.update() def one_handle_movement(keys_pressed, one): if keys_pressed[pygame.K_a] and one.x - VEL > -15: # left one.x -= VEL if keys_pressed[pygame.K_d] and one.x + VEL + one.width < 925: # right one.x += VEL if keys_pressed[pygame.K_w] and one.y - VEL > -15: # up one.y -= VEL if keys_pressed[pygame.K_s] and one.y + VEL + one.height < 500: # down one.y += VEL def main(): one = pygame.Rect(100, 300, 55, 40) 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() keys_pressed = pygame.key.get_pressed() one_handle_movement(keys_pressed, one) draw_window(one) pygame.quit() if __name__ == '__main__': main() 

I would really appreciate help if you are willing to provide it!

P.S. i didn't really define the bullets yet, but the player one sprite is the main thing im looking for at the moment

Much of this code is as shown in https://www.youtube.com/watch?v=jO6qQDNa2UY

-Luckee365-

\$\endgroup\$
2
  • \$\begingroup\$ first you have to get position of mouse and gun, and calculate distance (dx, dy) between mouse and gun and value dy/dy gives you tangle of angle - and this angle you can use to rotate bullet. SO it needs some math ;) Luckly PyGame.math.Vector should have functions to calculate distance and/or angle between two points. \$\endgroup\$ Commented Feb 28, 2022 at 15:27
  • \$\begingroup\$ BTW: because one is a Rect() so instead of one.x + one.width. You can use one.right. You have also one.left, one.top, one.botton. one.center, one.centerx, one,centery, one.topleft, one.size, etc. \$\endgroup\$ Commented Feb 28, 2022 at 16:48

1 Answer 1

0
\$\begingroup\$

Math: tan(angle) = dy/dx so angle = arctangle(dy/dx)

And as dx, dy you can use differnce between mouse position and gun/player position.


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() 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() ``` 
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.