I am working on a game, where you can input the function to a graph, it then draw that graph and a Rocket followes it. My problem is, that while rotating the rocket, it stutters a lot.I've tried rounding and setting the interval of points where the rocket appeares lower, but it didnt help. I'm getting the angle of rotation through math.atan2(dy,dx).
my Code:
import math
import sys
import pygame
import numpy as np
pygame.init()
# variables
background_colour = (255, 255, 255)
screen = pygame.display.set_mode((1920, 1080))
pt_list = []
base_font = pygame.font.SysFont("calibri", 16)
user_text = ""
clock = pygame.time.Clock()
input_rect = pygame.Rect(20, 20, 140, 32)
color_active = (255, 255, 255)
color_passive = (255, 126, 0)
color = color_passive
box_active = False
function_input = user_text
fixed_text_inp_box = "f(x) = "
coord_list = []
draw = False
black = (0, 0, 0)
drawn = False
coord_index = 0
angle = 0
bg = pygame.image.load("bg1.png")
bg = pygame.transform.scale(bg, (1920, 1080))
rocket = pygame.image.load("rocket-1.png")
rocket = pygame.transform.scale(rocket, (200, 116))
def replace_x(function):
f = lambda x: eval(function)
return f
def convert_y(y_coords):
y_coords = 540 - y_coords
return y_coords
def convert_x(x_coord):
x_coord = x_coord + 960
return x_coord
def get_pt_list(user_inp, fixed_text_box):
user_inp = user_inp.replace("^", "**")
user_inp = user_inp.replace("1x", "1*x")
user_inp = user_inp.replace("2x", "2*x")
user_inp = user_inp.replace("3x", "3*x")
user_inp = user_inp.replace("4x", "4*x")
user_inp = user_inp.replace("5x", "5*x")
user_inp = user_inp.replace("6x", "6*x")
user_inp = user_inp.replace("7x", "7*x")
user_inp = user_inp.replace("8x", "8*x")
user_inp = user_inp.replace("9x", "9*x")
user_inp = user_inp.replace("0x", "0*x")
user_inp = user_inp.replace(")(", ")*(")
user_inp = user_inp.replace("x(", "x*(")
user_inp = user_inp.replace("1(", "1*(")
user_inp = user_inp.replace("2(", "2*(")
user_inp = user_inp.replace("3(", "3*(")
user_inp = user_inp.replace("4(", "4*(")
user_inp = user_inp.replace("5(", "5*(")
user_inp = user_inp.replace("6(", "6*(")
user_inp = user_inp.replace("7(", "7*(")
user_inp = user_inp.replace("8(", "8*(")
user_inp = user_inp.replace("9(", "9*(")
user_inp = user_inp.replace("0(", "0*(")
user_inp = user_inp.replace(")0", ")*0")
user_inp = user_inp.replace(")1", ")*1")
user_inp = user_inp.replace(")2", ")*2")
user_inp = user_inp.replace(")3", ")*3")
user_inp = user_inp.replace(")4", ")*4")
user_inp = user_inp.replace(")5", ")*5")
user_inp = user_inp.replace(")6", ")*6")
user_inp = user_inp.replace(")7", ")*7")
user_inp = user_inp.replace(")8", ")*8")
user_inp = user_inp.replace(")9", ")*9")
user_inp = user_inp.replace(")x", ")*x")
f = replace_x(user_inp)
try:
for x in np.arange(-32, 32, 0.0625):
pt_list.append((x, f(x)))
except (ValueError, SyntaxError, NameError):
fixed_text_inp_box = "Invalid Function"
print("wrong")
return user_text
for pt in pt_list:
x = round(convert_x(pt[0] * 30))
y = round(convert_y(pt[1] * 30))
coord_list.append((x, y))
return coord_list
def custom_round(x, base=5):
return base * round(x/base)
# def draw_func(self, coord_list, animated):
screen.fill(background_colour)
pygame.display.set_caption('Mathe Kreativarbeit')
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
box_active = True
else:
box_active = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
box_active = False
if box_active:
if event.key == pygame.K_BACKSPACE:
if user_text == "Invalid Input":
user_text = ""
else:
user_text = user_text[:-1]
pt_list = []
coord_list = []
draw = False
elif event.key == pygame.K_RETURN:
draw = True
else:
user_text += event.unicode
screen.blit(bg, (0, 0))
# draws the coordinate system
pygame.draw.line(screen, (255, 255, 255), (960, 0), (960, 1080), 2)
pygame.draw.line(screen, (255, 255, 255), (0, 540), (1920, 540), 2)
for numbers in range(0, 64):
pygame.draw.aaline(screen, (255, 255, 255), (numbers * 30, 530), (numbers * 30, 550))
for numbers in range(0, 36):
pygame.draw.aaline(screen, (255, 255, 255), (950, numbers * 30), (970, numbers * 30))
if box_active:
color = color_active
else:
color = color_passive
pygame.draw.rect(screen, color, input_rect, 2)
text_surface = base_font.render(fixed_text_inp_box + user_text, False, (255, 255, 255))
input_rect.w = max(100, text_surface.get_width() + 10)
screen.blit(text_surface, (input_rect.x + 5, input_rect.centery - 5))
if len(coord_list) > 1:
try:
pygame.draw.aalines(screen, (255, 255, 255), False, coord_list, 3)
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
if draw:
try:
coord_list = get_pt_list(user_text, fixed_text_inp_box)
print(coord_list)
prev_x = coord_list[0]
for x in coord_list:
pygame.draw.aaline(screen, (255, 255, 255), prev_x, x)
pygame.display.flip()
pygame.time.delay(2)
prev_x = x
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
draw = False
drawn = True
if drawn:
try:
y1 = int(coord_list[coord_index][1])
y2 = int(coord_list[coord_index + 1][1])
x1 = int(coord_list[coord_index][0])
x2 = int(coord_list[coord_index + 1][0])
dy = y1 - y2
dx = x2 - x1
angle = math.degrees(math.atan2(dy, dx))
custom_round(angle, 5)
angle %= 360
rot_rocket = pygame.transform.rotate(rocket, angle)
screen.blit(rot_rocket, (int(coord_list[coord_index][0]) - 100, int(coord_list[coord_index][1])))
pygame.display.flip()
angle = 0
coord_index += 10
pygame.time.delay(10)
except IndexError:
coord_index -= 2
drawn = False
pygame.display.flip()
clock.tick(60)