1

I've been trying to work on a system whereby the player character is able to both move around the screen using the WASD keys while also always be facing towards the position of the mouse. What I mean by this is no matter where the sprite is on screen, it's top edge will always be looking towards wherever the mouse is located - the position of the mouse should have no impact upon it's movement, only its rotation. Incidentally, the WASD keys should have no impact upon the character's rotation, only its position.

I have been able to implement the WASD movement and the continuous character rotation towards the mouse position to work separately but I have been having difficulty with getting them both to work together at the same time (the rotation towards the mouse is supposed to be able to happen at the same time as moving around the screen).

Any help would be greatly appreciated.

import pygame
import time
import math

pygame.init()

#color defining
BLACK = (0 , 0 , 0)
WHITE = (255 , 255 , 255)
RED = (255 , 0 , 0)
GREEN = (0 , 255 , 0)
BLUE = (0 , 0 , 255)
DARKBLUE = (36 , 90 , 190)
LIGHTBLUE = (0 , 176 , 240)

#opening a window
screenSize = (800 , 600)
screen = pygame.display.set_mode(screenSize)
pygame.display.set_caption("Test")

#create sprites list
all_sprites_list = pygame.sprite.Group()

#sprites creation
class Char(pygame.sprite.Sprite):
    
    def __init__(self , color , width , height):
        super().__init__()
        
        #Set the colour, height and width and position
        self.image = pygame.Surface([width , height])
        self.image.fill(BLACK)
        self.image.set_colorkey(BLACK)
        
        #draw chars
        pygame.draw.rect(self.image , color , [0 , 0 , width , height])
        self.rect = self.image.get_rect(center = (width , height))
        self.orig_img = self.image
        
        #get initial sprite position
        self.pos = self.rect.x , self.rect.y
        self.x = self.rect.x
        self.y = self.rect.y
        self.rect.center = self.pos

    #----Char Methods
    #--Movement Methods
    
    #Check if moving off the screen
    def moveLeft(self, pixels):
        self.rect.x -= pixels   
        if self.rect.x < 0:
            self.rect.x = 0

    def moveRight(self, pixels):
        self.rect.x += pixels   
        if self.rect.x > 750:
            self.rect.x = 750

    def moveUp(self, pixels):
        self.rect.y -= pixels   
        if self.rect.y < 0:
            self.rect.y = 0

    def moveDown(self, pixels):
        self.rect.y += pixels   
        if self.rect.y > 550:
            self.rect.y = 550

    #Allows player rotation towards the mouse location
    def rotateToMouse(self):
      pos = self.rect.x, self.rect.y
      mouse_x, mouse_y = pygame.mouse.get_pos()
      rel_x, rel_y = mouse_x - self.x, mouse_y - self.y
      angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
      self.image = pygame.transform.rotate(self.orig_img, int(angle))
      self.rect = self.image.get_rect(center=pos)

char = Char(LIGHTBLUE , 50 , 50)
char.rect.x = 450
char.rect.y = 450

#adding objects to group
all_sprites_list.add(char)

#game running flag
run = True

#clock setup
clock = pygame.time.Clock()

##----MAIN GAME----##
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x:
                run = False

    #----key bindings
    keys = pygame.key.get_pressed()
    if keys[pygame.K_a]:
        char.moveLeft(3) #moves left with speed of 3
    if keys[pygame.K_d]:
        char.moveRight(3) #moves right with speed of 3
    if keys[pygame.K_w]:
        char.moveUp(3) #moves up with speed of 3
    if keys[pygame.K_s]:
        char.moveDown(3) #moves down with speed of 3
    
    char.rotateToMouse()

    #----game logic
    all_sprites_list.update()

    #----drawing
    #reset screen
    screen.fill(DARKBLUE)

    #display statistics

    #draw sprites
    all_sprites_list.draw(screen)

    #update screen
    pygame.display.flip()

    #clock control
    clock.tick(60)

pygame.quit()
15thepper
  • 13
  • 3

1 Answers1

0

There are 2 problems.

  1. Get the center of the .rect attribute instead of the top lelft:

pos = self.rect.x, self.rect.y

pos = self.rect.centerx, self.rect.centery
  1. Use the center position (pos) instead of the x and y attribute to comoute the angle:

rel_x, rel_y = mouse_x - self.x, mouse_y - self.y

rel_x, rel_y = mouse_x - pos[0], mouse_y - pos[1]

The x and y attribute have no meaning. You don't need them at all.


rotateToMouse method:

class Char(pygame.sprite.Sprite):
    # [...]

    def rotateToMouse(self):
        pos = self.rect.centerx, self.rect.centery
        mouse_x, mouse_y = pygame.mouse.get_pos()
        rel_x, rel_y = mouse_x - pos[0], mouse_y - pos[1]
        angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
        self.image = pygame.transform.rotate(self.orig_img, int(angle))
        self.rect = self.image.get_rect(center=pos)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174