turtle() does not rotate multiple balls plus attribute error

Viewed 115

I would like to create balls going around in a circle with different radiuses, similar to the solar system. In my attempt, the algorithm should create balls -initialize them to locations of radius , then start spinning at the same time, in my attempt the balls do not start at the same time, I suspect it's something to do with the for loop.

import turtle, numpy as np 

a = np.linspace(0,2*np.pi,100)
balls = []
ball_colour = ['orange','blue','brown','black','red','pink','yellow']
ball_shape =['circle', 'square','triangle'] 

for _ in range(3):
    balls.append(turtle.Turtle())
    
for ball in balls:    
    raduis = np.random.randint(0,8)
    x = raduis*np.cos(a)
    y = raduis*np.sin(a)
    
    ball.shape(ball_shape[np.random.randint(0, 3)])
    ball.color(ball_colour[np.random.randint(0,(len(ball_colour)-1))] )
    ball.goto(raduis,y[i])
    ball.dy =0.001
    ball.dx = 0.001    
    ball.speed(np.random.randint(15))

for ball in balls:
    for i in range(100):
        ball.sety(ball.ycor()+raduis*np.sin(a)[i] +ball.dy)
        ball.setx(ball.xcor()+raduis*np.cos(a)[i]+ ball.dy)

    

worth pointing out that sometimes I run into an error saying that the turtle has no attribute 'dy', but sometimes it does not show the error. Nevertheless the my main goal is to initialize the balls at different radius and that start at the same time.

2 Answers

You misrepresent your code as working but with bugs -- your code doesn't run at all and fixing the first few bugs one encounters isn't enough:

In this line:

ball.goto(raduis,y[i])

There's no i variable defined at this point in the code. This radius range is way too narrow for turtles which take up about 20 pixels each:

raduis = np.random.randint(0,8)

The planets would overlap to the point of being hard to tell apart. It's not clear what this doing:

ball.speed(np.random.randint(15))

Turtle's speed() method only works in the range 0 - 10, not 15. And it won't make any real difference in your animation. This is the strangest of all:

raduis*np.sin(a)[i]

Over and over again in your loop, you have numpy convert an entire array of angles into their sines and then use only one of them -- you could have picked out one of them, and taken its sine. Your code generally shows a lack of understanding of the array operations of numpy, and could have been written without it. Finally, this motion calculation is bogus:

ball.sety(ball.ycor()+raduis*np.sin(a)[i] +ball.dy)

We're moving in a circle based on radius and angle, so ball.ycor() and ball.dy have no business here.

Here's my rework of your code to get three objects in orbit around the center.

from turtle import Screen, Turtle
from random import choice
from numpy import linspace, pi, cos, sin

angles = linspace(0, pi*2, 100)
sines, cosines = sin(angles), cos(angles)

ball_colours = ['orange', 'blue', 'brown', 'black', 'red', 'pink', 'yellow']
ball_shapes = ['circle', 'square', 'triangle']

screen = Screen()

balls = []

for radius in range(40, 160, 40):
    x = radius * cosines[0]
    y = radius * sines[0]

    ball = Turtle()
    ball.shape(choice(ball_shapes))
    ball.color(choice(ball_colours))
    ball.penup()
    ball.goto(x, y)
    ball.pendown()

    ball.radius = radius

    balls.append(ball)

for i in range(1, len(angles)):
    for ball in balls:
        ball.goto(ball.radius * cosines[i], ball.radius * sines[i])

screen.mainloop()

What's missing is having the objects move at different speeds -- I leave that as an exercise for you:

enter image description here

You can also use the built-in method from turtle to draw your circles:

from turtle import Screen, Turtle
from random import choice

ball_colours = ['orange', 'blue', 'brown', 'black', 'red', 'pink', 'yellow']
ball_shapes = ['circle', 'square', 'triangle']

balls = []

for radius in range(40, 160, 40):
    ball = Turtle()
    ball.shape(choice(ball_shapes))
    ball.color(choice(ball_colours))
    ball.radius = radius
    ball.speed(0)
    ball.penup()
    ball.goto(0,-radius)
    ball.pendown()
    balls.append(ball)
    
for a in range(360):
    for ball in balls:
        ball.circle(ball.radius,1)

screen.mainloop()

Output:enter image description here

Sometimes I run into an error saying that the turtle has no attribute 'dy', but sometimes it does not show the error.

You need to make sure you define Turtle.dy before you call it.

Related