I'm very new to working with python and coding in general but I've been playing around with turtle for the past couple of days. I'm trying to create several functions where other functions move a turtle created within a different function. For instance:
import turtle as t
def setUp():
t.setup(900,600)
t.colormode(255)
win = t.Screen()
def turtles():
t1 = t.Turtle()
t1.shapesize(1.5,1.5,0)
t1.color('red')
t1.pensize(3)
t1.shape('turtle')
def moveTurtle():
t1.forward(50)
setUp()
turtles()
moveTurtle()
In my example here when python gets down to moveTurtles(), t1 isn't recognized due to it having been created in a previous function. If anyone could give me some insight into how I could go about doing this I'd really appreciate it. Thank you!
You have 2 options:
option 1:
return variable from first method and send it to second method:
import turtle as t
def setUp():
t.setup(900,600)
t.colormode(255)
win = t.Screen()
def turtles():
t1 = t.Turtle()
t1.shapesize(1.5,1.5,0)
t1.color('red')
t1.pensize(3)
t1.shape('turtle')
return t1
def moveTurtle(t1):
t1.forward(50)
setUp()
moveTurtle(turtles())
option 2:
Using global variable which is not recommended but usable:
import turtle as t
t1 = None
def setUp():
t.setup(900,600)
t.colormode(255)
win = t.Screen()
def turtles():
global t1
t1 = t.Turtle()
t1.shapesize(1.5,1.5,0)
t1.color('red')
t1.pensize(3)
t1.shape('turtle')
def moveTurtle():
t1.forward(50)
setUp()
turtles()
moveTurtle()
option 3:
Turtles, and the screen object, are global entities by design of the turtle package. (A turtle local to a function doesn't get reclaimed when the function returns.) Simply make them global, and access them globally or pass them to where they're needed:
from turtle import Screen, Turtle
def setUp(w):
w.setup(900, 600)
w.colormode(255)
def turtles(t):
t.shapesize(1.5, 1.5, 0)
t.color('red')
t.pensize(3)
t.shape('turtle')
def moveTurtle(t):
t.forward(50)
win = Screen()
t1 = Turtle()
setUp(win)
turtles(t1)
moveTurtle(t1)
Related
I have to generate two turtle windows and draw in each one, so I'm using tkinter to create and show the windows. My code currently opens the right screen and draws in it, but the turtle is really slow so I want to set the turtle tracer to false to use the update function, but I can't figure out how to.
This is my turtle_interpreter.py file, which has all the functions I use to draw the L-system:
import turtle
from tkinter import *
class Window(Tk):
def __init__(self, title, geometry):
super().__init__()
self.running = True
self.geometry(geometry)
self.title(title)
self.protocol("WM_DELETE_WINDOW", self.destroy_window)
self.canvas = Canvas(self)
self.canvas.pack(side=LEFT, expand=True, fill=BOTH)
self.turtle = turtle.RawTurtle(turtle.TurtleScreen(self.canvas))
def update_window(self):
'''
sets window to update
'''
if self.running:
self.update()
def destroy_window(self):
'''
sets window to close
'''
self.running = False
self.destroy()
def drawString(turt, dstring, distance, angle):
'''Interpret the characters in string dstring as a series
of turtle commands. Distance specifies the distance
to travel for each forward command. Angle specifies the
angle (in degrees) for each right or left command. The list
of turtle supported turtle commands is:
F : forward
- : turn right
+ : turn left
'''
for char in dstring:
if char == 'F':
turt.forward(distance)
elif char == '-':
turt.right(angle)
elif char == '+':
turt.left(angle)
def place(turt, xpos, ypos, angle=None):
'''
places turtle at given coordinates and angle
'''
turt.penup()
turt.goto(xpos, ypos)
if angle != None:
turt.setheading(angle)
turt.pendown()
def goto(turt, xpos, ypos):
'''
moves turtle to given coordinates
'''
turt.penup()
turt.goto(xpos, ypos)
turt.pendown()
def setColor(turt, color):
'''
sets turtle color
'''
turt.color(color)
And this is the file where the functions get called. Running it draws the L-system.
import turtle_interpreter as turt_int
import lsystem_scene_three as lsystem
def turtle_scene_two():
'''
generates scene two
'''
# create window
win_two = turt_int.Window('Turtle Scene 2', '640x480+650+0')
# assign turtle
turt2 = win_two.turtle
# lsystem setup
lsystemFile = lsystem.Lsystem('lsystem_scene_two.txt')
tstr = lsystemFile.buildString(4)
# draw stuff
turt_int.setColor(turt2, (0, 0, 0))
turt_int.place(turt2, 0, -200, 90)
turt_int.drawString(turt2, tstr, 4, 90)
# update window (loop)
while win_two.running:
win_two.update_window()
turtle_scene_two()
Hope this makes sense. Let me know if it doesn't.
Appreciate your help!
Tried a few things but nothing was promising. Calling turtle generates another screen (which I don't want).
Since you didn't provide all your code, I can't test this, so I'm guessing a good start would be changing this:
self.turtle = turtle.RawTurtle(turtle.TurtleScreen(self.canvas))
to something like:
screen = turtle.TurtleScreen(self.canvas)
screen.tracer(False)
self.turtle = turtle.RawTurtle(screen)
I want to create multiple small games in pygame zero, with a main window on which you have buttons to click - when clicking a button it would start a new window and a new subgame (coded on its own in another file). The secondary games should be able to return if the game was won or lost. Is this possible using pygame-zero? I am thinking the subgame should be encapsulated in some function to be able to give a return value, but I am not sure if this is doable in pygame-zero since it calls some functions itself... any idea?
Or am I better off adding some kind of game state in the main program and do everything there like this?
def update():
if state == 'game1':
#all of the game1 update code here
elif state == 'game2':
#all of the game2 update code here
#etc
def draw():
if state == 'game1':
#all of the game1 draw code here
elif state == 'game2':
#all of the game2 draw code here
#etc
I think you are definitely better off by implementing a game state. I'd use an object-oriented approach like:
class GameState:
def update():
pass
def draw():
pass
class Game1(GameState):
def update():
# ...
def draw():
# ...
class GameChooser(GameState):
def update():
# choose game here
global state
if ...:
state = Game1()
def draw():
# ...
state = GameChooser()
def update():
state.update()
def draw():
state.draw()
I am trying to make a turtle race, but I get an error that the class "turtles" has no attribute "forward". Here is my code:
class turtles:
def __init__(self, color, posX):
self = turtle.Turtle(shape='turtle', visible=False)
self.color(color)
self.penup()
self.shape('turtle')
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def start_race(self):
self.forward(random.randrange(0,10))
t1 = turtles('red',-150)
t2 = turtles('orange', -100)
t3 = turtles('yellow',-50)
t4 = turtles('green', 0)
t5 = turtles('light blue', 50)
t6 = turtles('blue',100)
t7 = turtles('purple', 150)
def begin_race():
t1.start_race()
t2.start_race()
t3.start_race()
t4.start_race()
t5.start_race()
t6.start_race()
t7.start_race()
begin_race()
Replace your turtles class with this:
class turtles(turtle.Turtle):
def __init__(self, color, posX):
self.color(color)
self.penup()
self.shape('turtle')
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def start_race(self):
self.forward(random.randrange(0,10))
Inheritance in Python is done by specifying a class in brackets after declaring a class name.
In this case, your turtles class inherits from the turtle.Turtle class and then has its attributes changed. Seems there was also some repetition with specifying the turtle's colour and visibility (I removed that for you)
The reason you get this error is because there is no attribute (i.e. a variable or method) called forward in your turtles class. The forward method is part of the turtle.Turtle class. You could solve this in different ways:
Method 1: using inheritance
You could derive your turtles class from the existing turtle.Turtle class. To do that, you should make the following changes:
The class turtles should be defined as class turtles(turtle.Turtle) to derive from it.
In the __init__() method you should not reassign self, because this is a reference to the actual object that's being initialized.
You should call the __init__() method of the original Turtle class.
So the full code could be like below. I renamed start_race() to advance_race() because that better describes what it does. And I added an infinite loop so you'll see the turtles "racing". This is just for demonstration, of course.
import random
import turtle
class turtles(turtle.Turtle):
def __init__(self, color, posX):
super().__init__(shape='turtle', visible=False)
self.color(color)
self.penup()
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def advance_race(self):
self.forward(random.randrange(0,10))
t1 = turtles('red', -150)
t2 = turtles('orange', -100)
t3 = turtles('yellow', -50)
t4 = turtles('green', 0)
t5 = turtles('light blue', 50)
t6 = turtles('blue', 100)
t7 = turtles('purple', 150)
while True:
t1.advance_race()
t2.advance_race()
t3.advance_race()
t4.advance_race()
t5.advance_race()
t6.advance_race()
t7.advance_race()
Method 2: using a wrapper class
Alternatively, you could create a new class that "holds" a turtle object. Using this method, you should store the turtle "inside" self and access it as self.turtle (or any other name).
class turtles:
def __init__(self, color, posX):
self.turtle = turtle.Turtle(shape='turtle', visible=False)
self.turtle.color(color)
self.turtle.penup()
self.turtle.goto(posX, -300)
self.turtle.showturtle()
self.turtle.setheading(90)
def advance_race(self):
self.turtle.forward(random.randrange(0,10))
(rest of the code same as above)
I am trying to create turtle objects with a class for my project which is a game. Each "Plane" object consists of:
plane3 = RawTurtle(screen)
plane3.ht()
plane3.color("red")
plane3.shape("plane.gif")
plane3.penup()
plane3.speed('fastest')
plane3.setposition(-270, 200)
plane3.setheading(360)
When putting this into a class and looking at other stack overflows questions to find out what to do, i threw together the following code:
class planes():
def __init__(self):
self.RawTurtle = RawTurtle(screen)
#self.hideturtle()
self.color = "red"
self.shape = ("plane.gif")
#self.penup()
self.speed = "fastest"
self.setposition = (-270, 100)
self.setheading = 360
Plane4 = planes()
When the code is run the turtle takes no shape or colour and is just a black triangle even though it causes no errors. However, errors do occur with the plane.hideturtle and plane.penup() functions which is why they are commented out.
File "C:/Users/marco/Desktop/Trooper shooter/TrooperShooter.py", line 694, in init
self.hideturtle()
AttributeError: 'planes' object has no attribute 'hideturtle'
Planes outside the class work perfectly and all planes are exactly identical. Any help is appreciated!
hideturtle() and penup() are both methods for the RawTurtle class, you haven't defined them for your planes class. So instead of this:
self.hideturtle()
self.penup()
you should have this:
self.RawTurtle.hideturtle()
self.RawTurtle.penup()
I believe your real problem is that your designed your plane class such that it has a turtle instead of designing it such that it is a turtle.
Taking the has a approach, every time you want to enable some additional turtle feature on your plane, you have to add a method to pass the call through to the contained turtle. Taking the is a approach, all turtle methods are in play:
from turtle import RawTurtle, TurtleScreen
from tkinter import Tk, Canvas, RIGHT
class Plane(RawTurtle):
def __init__(self):
super().__init__(screen)
self.hideturtle()
self.color('red')
self.shape('plane.gif')
# self.speed('fastest') # commented out while debugging
self.penup()
self.setposition(-270, 100)
self.setheading(0)
self.showturtle()
root = Tk()
canvas = Canvas(root, width=600, height=400)
canvas.pack(side=RIGHT)
screen = TurtleScreen(canvas)
screen.register_shape('plane.gif')
plane4 = Plane()
plane4.forward(400)
screen.mainloop()
I made new method called start() and pasted my mainloop() there, but it's not showing a picture anymore. How to fix it?
class Beerpong():
def __init__(self):
self.__main = Tk()
self.__main.title("Beerpong made by: x")
#Making background for game
bg_image = PhotoImage(file="beerpong_table.gif")
bg = Label(self.__main,image=bg_image)
bg.pack()
def start(self):
self.__main.mainloop()
def main():
ui = Beerpong()
ui.start()
main()
The problem is the PhotoImage created in the __init__() method is getting destroyed when it returns because it's stored in a the local variable bg_image (and local variables disappear when a function exits).
Here's some documentation I found that describes this (search for the "# keep a reference!" comment in the example code):
So here's how to apply the recommend way to to your own code (by making it an attribute of something that will still exist after the method returns):
from tkinter import *
class Beerpong():
def __init__(self):
self.__main = Tk()
self.__main.title("Beerpong made by: x")
#Making background for game
bg_image = PhotoImage(file="beerpong_table.gif")
bg = Label(self.__main,image=bg_image)
bg.image = bg_image # Save a reference to the PhotoImage.
bg.pack()
def start(self):
self.__main.mainloop()
def main():
ui = Beerpong()
ui.start()
main()