I am making an Astroid clone where you only move with the keyboard. The player is able to rotate and needs to move forward to were it is facing.
For example:
When I rotate the player by 30 degrees and push W to go forward I want the player to go forward in the direction the player is facing. I can't just use self.rect.x += self.vel
I also tried to use this function:
def calculate_new_xy(speed, degrees):
add_x = (speed*(math.sin((degrees)*math.pi/180)))
add_y = (speed*(math.cos((degrees)*math.pi/180)))
return add_x, add_y
In theory, it should work because I am taking the sin and cos of this Triangle.
But when I added that to my code the movement of the player wasn't as smooth as I hoped it to be. And sometimes the player moved indirectly forward.
I also noticed that the player moves faster when facing to the top left than to the bottom right.
Due to that the player doesn't move in a circle when turning always right. Instead the player moves elliptical to the top left.
Here is the code:
import pygame
import time
import random
import math
from os import path
#Colors:
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
#Settings:
pygame.init()
pygame.mixer.init() #for sound
WIDTH = 700
HEIGHT = 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Astroids")
clock = pygame.time.Clock()
FPS = 60
#Images/Sounds:
game_folder = path.dirname(__file__)
img_folder = path.join(game_folder, "img")
player = pygame.image.load(path.join(img_folder, 'Player.png'))
stone = pygame.image.load(path.join(img_folder, 'Stein.png'))
#Game Classes
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.original_image = player
self.image = self.original_image.copy()
self.rect = self.image.get_rect()
self.rect.center = (WIDTH/2, HEIGHT/2)
self.speed_x = 0
self.speed_y = 0
self.vel = 3
self.degrees = 0
def boundary(self):
if self.rect.left > WIDTH:
self.rect.right = 0
if self.rect.bottom < 0:
self.rect.top = HEIGHT
if self.rect.right < 0:
self.rect.left = WIDTH
if self.rect.top > HEIGHT:
self.rect.bottom = 0
def movement(self):
'''Player Movement'''
keystate = pygame.key.get_pressed()
if keystate[pygame.K_q]:
self.degrees += 3
if keystate[pygame.K_e]:
self.degrees -= 3
if keystate[pygame.K_w]:
self.rect.centerx += (self.vel*(math.sin((self.degrees+180)*math.pi/180)))
self.rect.centery += (self.vel*(math.cos((self.degrees+180)*math.pi/180)))
if keystate[pygame.K_s]:
self.rect.centery += -self.vel * math.sin(math.radians(self.degrees - 90))
self.rect.centerx += self.vel * math.cos(math.radians(self.degrees - 90))
def rotate(self):
old_center = self.rect.center
self.image = pygame.transform.rotate(self.original_image, self.degrees)
self.rect = self.image.get_rect()
self.rect.center = old_center
def update(self):
'''Picture is "printed"'''
self.movement()
self.boundary()
self.rotate()
#self.rect.y += self.speed_y
class Astroid(pygame.sprite.Sprite):
def __init__(self, life):
pygame.sprite.Sprite.__init__(self)
self.original_image = stone
self.image = self.original_image.copy()
self.rect = self.image.get_rect()
self.rect.center = (WIDTH/2, HEIGHT/2)
self.speed = 2
self.life = life
self.speed_x = random.randrange(-3, 3)
self.speed_y = random.randrange(-3, 3)
self.rect.x = random.randrange(0, WIDTH - self.rect.width)
self.rect.y = random.randrange(-3, 3)
self.last_rotation = pygame.time.get_ticks() # keeps track of time in milliseconds
self.rotation_deegre = random.randint(0, 360)
self.rotation_speed = 5
def rotate(self):
current_time = pygame.time.get_ticks()
if current_time - self.last_rotation > 50:
self.last_rotation = current_time
self.rotation_deegre += self.rotation_speed
old_center = self.rect.center
self.image = pygame.transform.rotate(self.original_image, self.rotation_deegre)
self.rect = self.image.get_rect()
self.rect.center = old_center
'''def new_astroids(self):
for i in range(2):
m = Astroid()
all_sprites.add(m)
all_astroids.add(m)''' #to do
def boundary(self):
if self.rect.left > WIDTH:
self.rect.right = 0
if self.rect.bottom < 0:
self.rect.top = HEIGHT
if self.rect.right < 0:
self.rect.left = WIDTH
if self.rect.top > HEIGHT:
self.rect.bottom = 0
def movement(self):
self.rect.x += self.speed_x
self.rect.y += self.speed_y
def update(self):
'''Picture is "printed"'''
self.movement()
self.boundary()
self.rotate()
#Game Funktions
def calculate_new_xy(speed, degrees):
add_x = (speed*(math.sin((degrees)*math.pi/180)))
add_y = (speed*(math.cos((degrees)*math.pi/180)))
return add_x, add_y
#Game Sprites
all_astroids = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range (1):
m = Astroid(3)
all_astroids.add(m)
all_sprites.add(m)
#Main Game Loop
running = True
while running:
#Keep the game runnung at 60 FPS
clock.tick(FPS)
#Check for events:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#Update for Sprites
all_sprites.update()
#Check to see if any Astroids hit the player
astroid_colision = pygame.sprite.spritecollide(player, all_astroids, False)
if astroid_colision:
running = False
#Draw/Render
screen.fill(BLACK)
all_sprites.draw(screen)
#Update the display
pygame.display.update()
pygame.quit()
Any help is welcomed.