Why it doesn't spin in a circle? And how to fix it?

Viewed 104

I'm not sure what the name of the shape that is being created, but I think is a combination of circle and square or maybe is similar to a cylinder. You can run the code to see what shape it makes. And could you suggest a site where I can learn to code a game (algorithms behind the basic games)? I hope you understand what I mean because I'm not good at English.

import pygame
import sys
import math

pygame.init()

width = 640
height = 480
screen = pygame.display.set_mode((width,height))

img = pygame.Surface((50,50))
img.set_colorkey((255,0,0))

angle = 0
clock = pygame.time.Clock()

c_list = []

x = 100
y = 100

vel = 5

def draw_line(surface, color, pos1, pos2):
    pygame.draw.line(surface, color, pos1, pos2)

while True:
    screen.fill((122,122,122))
    keys = pygame.key.get_pressed()
    angle -= 3
    if angle % 360 < 90:
        x -= math.sin(angle/180*math.pi)**2*vel
        y -= math.cos(angle/180*math.pi)**2*vel
    elif angle % 360 < 180:
        x -= math.sin(angle/180*math.pi)**2*vel
        y += math.cos(angle/180*math.pi)**2*vel
    elif angle % 360 < 270:
        x += math.sin(angle/180*math.pi)**2*vel
        y += math.cos(angle/180*math.pi)**2*vel
    else:
        x += math.sin(angle/180*math.pi)**2*vel
        y -= math.cos(angle/180*math.pi)**2*vel

    if (x,y) not in c_list:
        c_list.append((x,y))
    for i in range(len(c_list)-1):
        draw_line(screen,(0,0,0),c_list[i],c_list[i+1])
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit(-1)

    img_copy = pygame.transform.rotate(img, angle)
    screen.blit(img_copy,(x-int(img_copy.get_width()/2),y-int(img_copy.get_width()/2)))

    pygame.display.flip()
1 Answers

You have to find the tangent of the circle. If you have an angle then the vector to the point on the circle is:

vx, vy = cos(angle), sin(angle)

The tangent to the circle is the vector rotated by 90°:

tx, ty = -vy, vy

Add the tangent multiplied by the velocity to the point (x, y) in every frame:

x -= math.sin(angle*math.pi/180)*vel
y += math.cos(angle*math.pi/180)*vel 
angle += 3

See also Move and rotate.


Minimal example:

import pygame
import sys
import math

pygame.init()
width = 640
height = 480
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()

img = pygame.Surface((50,50))
img.set_colorkey((255,0,0))
angle = 0
c_list = []
x, y = 300, 200
vel = 5

def draw_line(surface, color, pos1, pos2):
    pygame.draw.line(surface, color, pos1, pos2)

start = False
while True:
    screen.fill((122,122,122))
    keys = pygame.key.get_pressed()
    
    x -= math.sin(angle*math.pi/180)*vel
    y += math.cos(angle*math.pi/180)*vel 
    angle += 3

    if (x,y) not in c_list:
        c_list.append((x,y))
    for i in range(len(c_list)-1):
        draw_line(screen,(0,0,0),c_list[i],c_list[i+1])
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit(-1)

    img_copy = pygame.transform.rotate(img, -angle)
    screen.blit(img_copy,(x-int(img_copy.get_width()/2),y-int(img_copy.get_width()/2)))
    pygame.display.flip()
Related