How to change the size of python turtle [duplicate] - python

I am trying to double the size of the turtle in the window every time I press x on my keyboard. I tried using .turtlesize(2,2,2), but that's not right. I need to double every time the key is pressed so if the turtle size is (1,1,1), it will become (2,2,2) then (4,4,4) and so on each time I press x.
This is what I have so far:
import turtle
turtle.setup(500,500)
wn = turtle.Screen()
wn.title("Commands")
wn.bgcolor("black")
tess = turtle.Turtle()
tess.shape("triangle")
tess.color("red")
tess.left(90)
def increaseSize():
size = tess.turtlesize()
increase = tuple([2 * num for num in size])
tess.turtlesize(increase) #this is where the error occurs
wn.onkey(increaseSize, "x")
wn.listen()

Change this line:
tess.turtlesize(increase)
to instead be:
tess.turtlesize(*increase)
turtlesize() wants three separate values but you were passing one tuple of three values so we need to spread that tuple across the argument list.

The default size of a Turtle object is 20 pixels, which is the equivalent of the ratio 1 when resizing the Turtle.
For example:
import turtle
tess = turtle.Turtle()
print(tess.shapesize())
Output:
(1.0, 1.0, 1)
The first two 1.0s in the tuple represents how many units 20 pixels the Turtle's width and height are, and the last 1 represents the width of the Turtle's outline.
You won't be able to see the outline if you only pass one argument into the tess.color() brackets, because by default, there is no outline.
To increase the Turtle's size, simply pass in the number of 20 pixels you want each of the Turtle's dimensions to be into tess.shapesize() or tess.turtesize():
import turtle
tess = turtle.Turtle()
tess.shapesize(2, 3, 1) # Sets the turtle's width to 60px and height to 90px
The other answer points out that the turtlesize function does not take in an
array; it takes in ints or floats, so you'll need to unpack the tuple with a *
when you pass the tuple into the function.
In your increaseSize function, the tuple and [] wrappers aren't necessary,
and only wastes efficiency. Simply use ():
def increaseSize():
size = tess.turtlesize()
increase = (2 * num for num in size)
tess.turtlesize(*increase)
On top of your code there is
turtle.setup(500,500)
wn = turtle.Screen()
Since you defined a Screen object, wn, it's cleaner to use wn.setup() instead of turtle.setup():
wn = turtle.Screen()
wn.setup(500,500)
All together:
import turtle
wn = turtle.Screen()
wn.setup(500,500)
tess = turtle.Turtle("triangle")
tess.color("red")
tess.left(90)
def increaseSize():
size = tess.turtlesize()
increase = (2 * num for num in size)
tess.turtlesize(*increase)
wn.onkey(increaseSize, "x")
wn.listen()
Output:

Related

Trying to get borders to my python turtle module game

I am trying to make this game where once you hit the borders of the box the turtle will return to the position it was at directly before it hit the border of the box. I am pretty new so any help would be appreciated. So far I have if y cord is greater than the box it goes back to right before it hit but it doesn't seem to be working.
import turtle
wn = turtle.Screen()
wn.bgcolor('black')
line = turtle.Turtle()
line.goto(-450,-15)
line.speed(9999)
line.pendown
line.color('white')
line.forward(850)
line.left(90)
line.forward(400)
line.left(90)
line.forward(850)
line.left(90)
line.forward(410)
line.color('black')
fred = turtle.Turtle()
fred.penup()
fred.goto(-430, 0)
fred.shape('square')
fred.color('white')
fred.penup()
fred.delay = 0.1
fred.direction = "Stop"
#Set Up (Controls)
wn.listen()
def ahead():
fred.forward(10)
def behind():
fred.backward(10)
if fred.ycor() < -500:
fred.goto(0, -500)
if fred.ycor() > 500:
fred.goto(0, 500)
wn.onkey(behind,"a")
wn.onkey(ahead,"d")
wn.mainloop()
You should use if inside functions - and values in if you may have to calculate manually.
def ahead():
fred.forward(10)
#print(fred.xcor())
if fred.xcor() > 430 - 50: # minus turtle width
fred.backward(10)
def behind():
fred.backward(10)
#print(fred.xcor())
if fred.xcor() < -430 :
fred.forward(10)
But problem will be if you will have more elements which should stop turtle.
turtle doesn't have function to detect collisions and you may have to access tkinter functions for this or you would have to create own function which checks xcor, ycor with coordinates from some list. And list should have coordinates for all objects. And this may need to calculate coordinates manually.
turtle is nice for drawing figures but not for games. There are better modules - like PyGame, Arcade, PGzero (PyGame Zero)

How can I get the color that is at a set of coordinates in python turtle?

With python, I'm trying to make a function that gets the colour that the turtle is currently on top of. I've found that turtle.pos() gives me coordinates of its location, how can I use those coordinates to get colours?
I think the best way to do this would be using the steps shown here: https://www.kite.com/python/answers/how-to-find-the-rgb-value-of-a-pixel-in-python
One way to go about this is to append every turtle you create into a list, then in your main game loop, loop through the list of turtle to see if the turtle.distance() is smaller than a certain value:
import turtle
wn = turtle.Screen()
turtles = []
yertle = turtle.Turtle('turtle')
while True:
wn.tracer(0)
for t in turtles:
if yertle.distance(t) < 20 and yertle != t:
print(f'Touched {t.color()}')
wn.update()
In the above code I used if yertle.distance(t) < 20 which is for when all the turtles are the default size: 20.

Move turtle slightly closer to random coordinate on each update

I'm doing a homework and I want to know how can I move turtle to a random location a small step each time. Like can I use turtle.goto() in a slow motion?
Someone said I should use turtle.setheading() and turtle.forward() but I'm confused on how to use setheading() when the destination is random.
I'm hoping the turtle could move half radius (which is 3.5) each time I update the program to that random spot.
You use the term half radius twice in your question's title and text, but never really explain it. For purposes of your question, we're just talking about some arbitrary small distance -- correct?
I would avoid import time and time.sleep() as they work against an event-driven world like turtle. Instead, I would use turtle's own ontimer() method to keep things in synch:
from turtle import Screen, Turtle
from random import randrange
HALF_RADIUS = 3.5 # unexplained constant
DELAY = 1000 # milliseconds
WIDTH, HEIGHT = 640, 480
CURSOR_SIZE = 20
def forward_slowly(distance):
if distance > 0:
turtle.forward(min(distance, HALF_RADIUS))
remaining = max(distance - HALF_RADIUS, 0)
screen.ontimer(lambda d=remaining: forward_slowly(d), DELAY)
else:
screen.ontimer(move_target, DELAY)
def move_target():
x = randrange(CURSOR_SIZE - WIDTH//2, WIDTH//2 - CURSOR_SIZE)
y = randrange(CURSOR_SIZE - HEIGHT//2, HEIGHT//2 - CURSOR_SIZE)
target.goto(x, y)
target.pendown()
turtle.setheading(turtle.towards(target))
forward_slowly(turtle.distance(target))
screen = Screen()
screen.setup(WIDTH, HEIGHT)
turtle = Turtle('turtle')
turtle.speed('slowest')
turtle.width(3)
target = Turtle('turtle')
target.speed('fastest')
target.color('red')
target.penup()
move_target()
screen.exitonclick()
(Any resemblence to a Pepé Le Pew cartoon is purely coincidental.)
Do you mean that you want to move a small step, stop, and repeat? If so, you can ‘import time’ and add ‘time.sleep(0.1)’ after each ‘forward’

How to draw numbers from a random list to use as Y coordinates for turtle graphics

I am trying to generate a list of random Y coordinates for a turtle graphics program that needs to draw flowers, but to prevent the flowers from drawing over each other I need to draw them from back to front. What I need to do is sort the random list from largest to smallest, then have it draw the flowers in that order.
I have already set up the program to generate 9 random numbers and sort them from largest to smallest, but I don't know how to draw the numbers from that list in order and assign them the Y value of the flower
This is my code for generating the random list:
def draw_stem(t,StemX,StemY):
StemYcoordinates=random.sample(range(-200,0),9)
sorted(StemYcoordinates, key=int)
But I am having trouble connecting it to this part of the code where it goes to the xy position where I want the flower to be drawn
for i in range(9):
t.setheading(90)
t.pensize(7-(StemYcoordinate//40))
t.color("#39ff14")
t.penup()
t.goto(StemX,StemYcoordinates)
t.down()
any help would be greatly appreciated
I think for your code, you will need to use the setpos() method.
This method treats the screen in turtle like a coordinate plane with four quadrants.
Using this, set the x and y coordinates accordingly, or randomly if you want to.
For example, this puts the turtle in a random spot every time you run it:
from turtle import *
t = Turtle()
t.penup()
from random import randint
x = randint(-200, 200)
y = randint(-200, 200)
t.setpos(x, y)
Hope this Helps!!!
Based on the description of your problem, you seem to want something like:
from turtle import Screen, Turtle
from random import sample, random
RADIUS = 100
PETALS = 10
def draw_petal(t, radius):
heading = t.heading()
t.circle(radius, 60)
t.left(120)
t.circle(radius, 60)
t.setheading(heading)
def draw_flower(t):
for _ in range(PETALS):
draw_petal(t, RADIUS)
t.left(360 / PETALS)
def draw_flowers(t, stemX):
stemYcoordinates = sorted(sample(range(-200, 0), 9))
for stemYcoordinate in stemYcoordinates:
t.setheading(90)
t.pensize(7 + stemYcoordinate // 40)
t.color(random(), random(), random())
t.penup()
t.goto(stemX, stemYcoordinate)
t.pendown()
draw_flower(t)
screen = Screen()
turtle = Turtle(visible=False)
turtle.speed('fastest') # because I have no patience
draw_flowers(turtle, 0)
screen.exitonclick()
But if this isn't what you're looking for, take the time to reread and edit your question to clarify what you want to do. Add more (if not all) of the code you've written so far, to make it clear what you need help with.

How do I make a variable for a nested loop?

I have a bit of code that draws an array of lines (32X32 grid). The actual code that draws it starts from #Nested loop to draw anti-aliased lines in a 32X32 grid. Because I have a patch within it that has lines of different orientation, the codes is a few lines long.
At the moment, I have a .draw() at the end of the nested loop that draws my array.
It doesn't seem like a good way to do this.
Is there a way to create a variable for this entire nested loop so i can call it as and when I want? For instance myStim.draw()
# Import what is needed
import numpy as np
from psychopy import visual, event, core, logging
from math import sin, cos
import random, math
# Create space variables and a window
lineSpaceX = 0.55
lineSpaceY = 0.55
patch_orientation = 45 # zero is vertical, going anti-clockwise
surround_orientation = 90
#Jitter values
g_posJitter = 0.05 #gaussian positional jitter
r_posJitter = 0.05 #random positional jitter
g_oriJitter = 5 #gaussian orientation jitter
r_oriJitter = 5 #random orientation jitter
#Region where the rectangular patch would appear
x_rand=random.randint(6,13) #random.randint(Return random integers from low (inclusive) to high (inclusive).
y_rand=random.randint(6,16)
#rectangular patch dimensions
width=15
height=12
message = visual.TextStim(win,pos=(0.0,-12.0),text='...Press SPACE to continue...')
# Initialize clock to record response time
rt_clock = core.Clock()
#Nested loop to draw anti-aliased lines in a 32X32 grid
for x in xrange(1,33): #32x32 grid.
for y in xrange(1,33):
##Define x & y value (Gaussian distribution-positional jitter)
x_pos = (x-32/2-1/2 )*lineSpaceX + random.gauss(0,g_posJitter) #random.gauss(mean,s.d); -1/2 is to center even-numbered stimuli; 32x32 grid
y_pos = (y-32/2-1/2 )*lineSpaceY + random.gauss(0,g_posJitter)
if (x >= x_rand and x < x_rand+width) and (y >= y_rand and y < y_rand+height): # note only "=" on one side
Line_Orientation = random.gauss(patch_orientation,g_oriJitter) #random.gauss(mean,s.d) - Gaussian func.
else:
Line_Orientation = random.gauss(surround_orientation,g_oriJitter) #random.gauss(mean,s.d) - Gaussian func.
#stimOri = random.uniform(xOri - r_oriJitter, xOri + r_oriJitter) #random.uniform(A,B) - Uniform func.
visual.Line(win, units = "deg", start=(0,0), end=(0.0,0.35), pos=(x_pos,y_pos), ori=Line_Orientation, autoLog=False).draw() #Gaussian func.
frameN = 0
for frameN in range(80): #for exactly 80 frames; 1 frame = 16.67ms on the 1920 x 1080 monitor
if frameN == 0:
rt_clock.reset() # set reaction time clock to 0
message.draw()
win.flip()# display stimulus
frameN = frameN + 1
keys = event.waitKeys(keyList=['space', 'escape','q']) #create key list response
# handle key responses
if len(keys)>0:
rt = rt_clock.getTime()
if keys == ['space']:
event.clearEvents()
break
else:
print 'Stopped Early'
win.close()
core.quit()
print x_rand, y_rand
print keys, rt #display response and reaction time on screen output window
It's not a variable you want, but a function.
The way you are currently doing things (via visual.Line(...).draw()) is very inefficient. You're creating a new line on very iteration, just to draw it once, and not storing a reference to it. A much more time-efficient scheme is to create just a single line object instance, referenced with a variable name, and then on every iteration, simply update its attributes (orientation etc), before drawing it.
An alternative would be to create multiple line object instances once, but store each in a list. Then drawing them again as required is a simple matter of:
for line_instance in line_list:
line_instance.draw()

Categories