# How do I move a character based on it's rotation?

## Issue

I have a character in PyGame which I want to move forward depending on its rotation. Currently it’s very strange and wonky.

Here’s all my code: https://www.toptal.com/developers/hastebin/enapuravet.lua

Here’s the relevent code:

``````    def rotate(self, amount):
self.rotation += amount
if self.rotation == 181:
self.rotation = -180
elif self.rotation == -181:
self.rotation = 180
print(self.rotation)
self.capybara = pygame.transform.rotate(self.base_capybara, self.rotation)
self.rect = self.capybara.get_rect(center = self.rect.center)

def move_forward(self, speed):
print(self.rotation)
new_coordinates = calculate_new_xy((self.x, self.y), 2, self.rotation*(math.pi/180))
self.x = new_coordinates
self.y = new_coordinates
self.rect = self.capybara.get_rect(center = (self.x, self.y))

return new_x, new_y
``````

Here’s what it does:
https://gyazo.com/3b7bf1c5b2e760a53913b6d3acae6e67

I also tried some other x_y calculating functions like this:

``````    move_vec = pygame.math.Vector2()
move_vec.from_polar((speed, angle_in_degrees))
return old_xy + move_vec
``````

but they had the same/very similar results.

This is the capybara: ## Solution

Since `pygame.Rect` is supposed to represent an area on the screen, a `pygame.Rect` object can only store integral data.

The coordinates for Rect objects are all integers. […]

If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the `pygame.Rect` object. `round` the coordinates and assign it to the location (e.g. `.center`) of the rectangle.

The unit of the angle of `math.sin` and `math.cos` is Randian. You needs to convert the angle from degrees to radians with `math.radians`:

``````class Capybara:
def __init__(self, size_multiplier):
# [...]

self.x, self.y = 300, 300
self.rect = self.capybara.get_rect(center = (round(self.x), round(self.y)))

def rotate(self, amount):
self.rotation += amount
ifv self.rotation > 360:
self.rotation -= 360
elif self.rotation < 0:
self.rotation += 360
self.capybara = pygame.transform.rotate(self.base_capybara, self.rotation)
self.rect = self.capybara.get_rect(center = (round(self.x), round(self.y)))

def move(self, move):
self.x += move * math.cos(math.radians(self.rotation + 90))
self.y -= move * math.sin(math.radians(self.rotation + 90))
``````

Minimal example: ``````import pygame, math
pygame.init()

size = width, height = 600, 600
green = 50, 168, 82

screen = pygame.display.set_mode(size)

class Capybara:
def __init__(self, size_multiplier):
self.o_size = 92, 206
self.new_size = (self.o_size * size_multiplier,self.o_size * size_multiplier)
self.capybara = pygame.transform.scale(self.capybara, self.new_size)
self.base_capybara = self.capybara
self.rotation = 0
self.x, self.y = 300, 300
self.rect = self.capybara.get_rect(center = (round(self.x), round(self.y)))

def rotate(self, amount):
self.rotation += amount
if self.rotation > 360:
self.rotation -= 360
elif self.rotation < 0:
self.rotation += 360
self.capybara = pygame.transform.rotate(self.base_capybara, self.rotation)
self.rect = self.capybara.get_rect(center = (round(self.x), round(self.y)))

def move(self, move):
self.x += move * math.cos(math.radians(self.rotation + 90))
self.y -= move * math.sin(math.radians(self.rotation + 90))

capybara = Capybara(0.8)

fpsClock = pygame.time.Clock()

rotate_l = False
rotate_r = False

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()

quit()

keys = pygame.key.get_pressed()
rotate = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move = keys[pygame.K_DOWN] - keys[pygame.K_UP]
capybara.move(-move * 5)
capybara.rotate(-rotate)

screen.fill(green)
screen.blit(capybara.capybara, capybara.rect)
pygame.display.update()
fpsClock.tick(60)
`````` 