1

Basically I need to make the player face the mouse pointer, and though I can see something is happening, it's not at all what I need.

I know this has been asked before, but trying to implement those answers doesn't seem to work. So if someone could look over my code and maybe tell me where I mess up, that would be greatly appreciated!

class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):
        self._layer = PLAYER_LAYER
        self.groups = game.all_sprites
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.image = game.player_img
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.hit_rect = PLAYER_HIT_RECT
        self.hit_rect.center = self.rect.center
        self.vel = vec(0, 0)
        self.pos = vec(x, y)
        self.rot = 0
    def update(self):
        rel_x, rel_y = pygame.mouse.get_pos() - self.pos
        self.rot = -math.degrees(math.atan2(rel_y, rel_x))
        self.image = pygame.transform.rotate(self.game.player_img, self.rot)
        self.rect = self.image.get_rect()
        self.rect.center = self.pos
        self.pos += self.vel * self.game.dt

class Camera:
    def __init__(self, width, height):
        self.camera = pygame.Rect(0, 0, width, height)
        self.width = width
        self.height = height

    def apply(self, entity):
        return entity.rect.move(self.camera.topleft)

    def apply_rect(self, rect):
        return rect.move(self.camera.topleft)

    def update(self, target):
        x = -target.rect.centerx + int(WIDTH / 2)
        y = -target.rect.centery + int(HEIGHT / 2)

        x = min(-TILESIZE, x)
        y = min(-TILESIZE, y)
        x = max(-(self.width - WIDTH - TILESIZE), x)
        y = max(-(self.height - HEIGHT - TILESIZE), y)
        self.camera = pygame.Rect(x, y, self.width, self.height)

Placing my player in the upper left corner, where there is no camera offset, makes the rotation work, however when placed elsewhere, it screws it up.

Thoft
  • 75
  • 1
  • 7

1 Answers1

2

See How to rotate an image(player) to the mouse direction?. What you want to do depends on which part of the player (top or right etc.) should be orientated to the mouse.

Don't compute and sum relative angles. Calculate the vector form the the player to the mouse:

player_x, player_y = # position of the player
mouse_x, mouse_y   = pygame.mouse.get_pos()
   
dir_x, dir_y = mouse_x - player_x, mouse_y - player_y

The angle of the vector can be calculated by math.atan2. The angle has to be calculated relative to the base orientation of the player.

e.g.

The right side of the player is orientated to the mouse:

angle = (180 / math.pi) * math.atan2(-dir_y, dir_x)

The top of the player is orientated to the mouse:

angle = (180 / math.pi) * math.atan2(-dir_x, -dir_y)

A basic alignment can be set using a correction angle. For example 45 for a player looking at the top right:

angle = (180 / math.pi) * math.atan2(-dir_y, dir_x) - 45

The method update may look like this:

def update(self):
    self.pos += self.vel * self.game.dt

    mouse_x, mouse_y = pygame.mouse.get_pos()
    player_x, player_y = self.pos

    dir_x, dir_y = mouse_x - player_x, mouse_y - player_y
    
    #self.rot = (180 / math.pi) * math.atan2(-dir_y, dir_x)
    #self.rot = (180 / math.pi) * math.atan2(-dir_y, dir_x) - 45
    self.rot = (180 / math.pi) * math.atan2(-dir_x, -dir_y)
    
    self.image = pygame.transform.rotate(self.game.player_img, self.rot)
    self.rect = self.image.get_rect()
    self.rect.center = self.pos

Minimal example: repl.it/@Rabbid76/PyGame-RotateWithMouse

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • This seems to restrict my rotation even more, down to less than 45 degrees. I'm gonna look over my code to see if something else is messing with the rotation, since I used to use arrow keys to turn. The funny thing is, I had no problem making the zombies face the player. Thanks for the quick reply though! – Thoft Jun 18 '19 at 07:54
  • @Thoft *"This seems to restrict my rotation even more, down to less than 45 degrees"* then you did something completely wrong. Of course I've tested theis code. Ensure that `player_x` and `player_y` are correct. – Rabbid76 Jun 18 '19 at 07:59
  • I've updated my question with what I've implemented (and sorry for using too much code, just wanted to make sure you could see enough) "then you did something completely wrong" No doubt. And I never said there was anything wrong with your code, just that it doesn't seem to be working for me atm :) I'm new at both coding and stackoverflow, hope you can bear with me – Thoft Jun 18 '19 at 08:44
  • @Thoft the code should work, it works for me. When you `print(dir_x, dir_y)`, does the direction seem to work? Update `self.pos` before rotating the image, but this may cause only a small correction. – Rabbid76 Jun 18 '19 at 09:04
  • The dir_x and dir_y seem to be working, though changing when I move the character (without moving the mouse) due to camera scrolling...not sure if this is a problem? – Thoft Jun 18 '19 at 09:30
  • @Thoft Do the light direction become positive and negative? What is *"camera scrolling"*. – Rabbid76 Jun 18 '19 at 09:37
  • Sorry for not replying to you sooner. I did some more research, and I will update my question with the camera class included, and another way to do the rotation calculations which got me closer. However, it seems to be the drawing offset the camera provides that fucks with it all – Thoft Jun 24 '19 at 08:26