I'm trying to rotate the whole scenario of a py-game, point by point, to simulate a 3d space. I've noticed, however, that simple rotation matrices just don't do well in the long run. If I run the test code bellow, the orbiting circle will tend to 'fall' to the center of its orbit. It is weird for me because I've made this work in more simple environments (geogebra) and I feel like it should work even better with python.
The test code would be:
import time
import numpy as np
import pygame
pygame.init()
#screensize
screensize = (width,height)=(600,600)
center=(int(width/2),int(height/2))
screen = pygame.display.set_mode(screensize)
#delta mov
do=0.1
#orbiting point
k=[100,100]
run=True
while run:
pygame.time.delay(20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run=False
#rotation
k[0]=np.cos(do)*k[0]-np.sin(do)*k[1]
k[1]=np.sin(do)*k[0]+np.cos(do)*k[1]
pygame.draw.circle(screen,(255,255,255),(int(k[0]+center[0]),int(k[1]+center[1])),5)
pygame.display.update()
screen.fill((0,0,0))
pygame.quit()
Sure, I can deal with the problem by reducing time.delay and the rotation angle to make better approximations, but it's not an option for the entire simulation I'm trying to draw, as it would consume lot of resources from my rather basic laptop... I'm afraid I'm just asking to much to the library.
¿Is there any suggestion on how to solve this problem? ¿Is it using numpy functions for sine and cosine a bad idea?
Maybe I'm just being silly and there's something wrong that I can't notice!
I'm not an expert, so I would really appreciate if there is some solution that don't involve extra libraries.
Thanks for all your help!
The issue is that you manipulate the original point k
. Because of the limited accuracy of the floating point operations, the point is slightly displaced at each step.
Keep the original point, but increment the angle and calculate a new point dependent on the original point in each frame. e.g.:
kr = np.cos(do)*k[0]-np.sin(do)*k[1], np.sin(do)*k[0]+np.cos(do)*k[1]
do += 0.1
See the example
do = 0.0
k = [100, 0]
run=True
while run:
pygame.time.delay(20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run=False
#rotation
kr = np.cos(do)*k[0]-np.sin(do)*k[1], np.sin(do)*k[0]+np.cos(do)*k[1]
do += 0.1
pygame.draw.circle(screen,(255,255,255),(int(kr[0]+center[0]),int(kr[1]+center[1])),5)
pygame.display.update()
screen.fill((0,0,0))