PYGAME – Move Character with Vector

Tags: , ,



I am teaching myself pygame and am looking at making my character able to rotate and then move in the direction they are facing.

I can do the rotation but cannot get the character to move in the direction the image is then facing.

The code is on Trinket HERE

class Bob(pygame.sprite.Sprite):
  def __init__(self, color , height , width):
    super().__init__()
    self.image = pygame.Surface([width , height])
    self.image.fill(BLACK)
    self.image.set_colorkey(BLACK)
    
    #Loading the image for the character
    self.img = pygame.image.load("char.jfif")
    #creating a copy of the image
    self.img_orig = self.img.copy()
    #defining the starting angle of the character image
    self.angle = 0
    
    self.velocity = 5
    self.rect = self.img_orig.get_rect()
    
  def moveLeft(self):
    self.angle += 1
    self.img = pygame.transform.rotate(self.img_orig, self.angle)
      
  def moveRight(self):
    self.rect.x += self.velocity
    if self.rect.x > 485:
      self.rect.x = 485
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            
    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
      pSprite.moveForward()
    if keys[pygame.K_DOWN]:
      pSprite.moveDown()
    if keys[pygame.K_LEFT]:
      pSprite.moveLeft()
    if keys[pygame.K_RIGHT]:
      pSprite.moveRight()

    #---- Game Logic Here
    
      
    #--- Drawing Code Here
    #Reset the screen to blank
    screen.fill(BLUE)
    #Draw Play Area
    
    #Draw Sprites
    screen.blit(pSprite.img,(pSprite.rect.x, pSprite.rect.y))

Answer

Rotate the player around its center (see How do I rotate an image around its center using PyGame?):

self.angle += 1
self.img = pygame.transform.rotate(self.img_orig, self.angle)
self.rect = self.img.get_rect(center = self.rect.center)

Use an attribute x and y to store the position of the player with floating point accuracy.

class Bob(pygame.sprite.Sprite):
  def __init__(self, color , height , width):
    # [...]

    self.x, self.y = self.rect.center

Compute the direction of the player dependent on the angle with the trgonometric function math.sin and math.cos. Change the position attributes and update the rect attribute:

self.x += self.velocity * math.cos(math.radians(self.angle + 90))
self.y -= self.velocity * math.sin(math.radians(self.angle + 90))
self.rect.center = round(self.x), round(self.y)

The y-axis needs to be reversed (-dy) as the y-axis is generally pointing up, but in the PyGame coordinate system the y-axis is pointing down. In addition, a correction angle must be deducted (+ 90). Since the “angle” is 0 ° when the sprite is looking up, you need to add 90 ° to the angle for the calculation of the direction vector.

See also te in pygame while moving with the keys](How to turn the sprite in pygame while moving with the keys.


Class Bob:

import pygame
import math
BLACK = (0,0,0)

class Bob(pygame.sprite.Sprite):
  def __init__(self, color , height , width):
    super().__init__()
    self.image = pygame.Surface([width , height])
    self.image.fill(BLACK)
    self.image.set_colorkey(BLACK)
    
    #Loading the image for the character
    self.img = pygame.image.load("char.jfif")
    #creating a copy of the image
    self.img_orig = self.img.copy()
    #defining the starting angle of the character image
    self.angle = 0
    
    self.velocity = 5
    self.rect = self.img_orig.get_rect()
    self.x, self.y = self.rect.center
    
  def rotate(self, change_angle):
    self.angle += change_angle
    self.img = pygame.transform.rotate(self.img_orig, self.angle)
    self.rect = self.img.get_rect(center = self.rect.center)
    
  def move(self, distance):
    self.x += distance * math.cos(math.radians(self.angle + 90))
    self.y -= distance * math.sin(math.radians(self.angle + 90))
    self.rect.center = round(self.x), round(self.y)
    
  def moveLeft(self):
    self.rotate(1) 
  def moveRight(self):
    self.rotate(-1)
    
  def moveForward(self):
    self.move(self.velocity)
  def moveDown(self):
    self.move(-self.velocity)

When setting the starting position of the player, you need to set the x, y and rect attribute:

pSprite = Bob(WHITE , 25,25)
pSprite.rect.x = 50
pSprite.rect.y = 50
pSprite.x, pSprite.y = pSprite.rect.center


Source: stackoverflow