For a classwork assignment everyone in the class had to make a program where when you click the shape it will disappear then reappear in a different location. However, it just disappears in mine. My teacher looked over it and saw no issues, but I still can't figure out how to fix it. Here is the code I wrote:
#-----import statements-----
import turtle as trtl
import random as rand
#-----game configuration----
dizzy_color = "red"
dizzy_size = 3
dizzy_shape = "circle"
#-----initialize turtle-----
dizzy = trtl.Turtle()
dizzy.shape(dizzy_shape)
dizzy.shapesize(dizzy_size)
dizzy.fillcolor(dizzy_color)
#-----game functions--------
def change_position():
new_xpos = rand.randint(-100, 100)
new_ypos = rand.randint(-50, 50)
dizzy.penup()
dizzy.hideturtle()
goto(new_xpos,new_ypos)
dizzy.showturtle()
dizzy.pendown()
def dizzy_clicked(x,y):
change_position()
#-----events----------------
dizzy.onclick(dizzy_clicked)
wn = trtl.Screen()
wn.mainloop()
Also the Turtle's name is dizzy.
The problem is you called the goto() method but forgot the object:
goto(new_xpos,new_ypos)
It should be:
dizzy.goto(new_xpos,new_ypos)
If you, or your teacher, are using a proper Python programming environment, you should have seen the related error message:
NameError: name 'goto' is not defined
Here's how I would go about writing this program:
from turtle import Screen, Turtle
from random import randint
DIZZY_COLOR = 'red'
DIZZY_SIZE = 3
DIZZY_SHAPE = 'circle'
def change_position():
new_xpos = randint(-100, 100)
new_ypos = randint(-50, 50)
dizzy.hideturtle()
dizzy.goto(new_xpos, new_ypos)
dizzy.showturtle()
def dizzy_clicked(x, y):
dizzy.onclick(None) # disable handler inside handler
change_position()
dizzy.onclick(dizzy_clicked)
screen = Screen()
dizzy = Turtle()
dizzy.penup()
dizzy.shape(DIZZY_SHAPE)
dizzy.shapesize(DIZZY_SIZE)
dizzy.fillcolor(DIZZY_COLOR)
dizzy.onclick(dizzy_clicked)
screen.mainloop()
Related
The code is as follows:
import turtle
width = 400
length = 300
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("x")
drawer = turtle.Turtle()
drawer.speed(3)
drawer.begin_fill()
drawer.color("blue", "yellow")
def drawern():
drawer.seth(90)
drawer.fd(1)
def drawerw():
drawer.seth(180)
drawer.fd(1)
def drawers():
drawer.seth(270)
drawer.fd(1)
def drawere():
drawer.seth(0)
drawer.fd(1)
wn.onkeypress(drawern, "w")
wn.onkeypress(drawerw, "a")
wn.onkeypress(drawers, "s")
wn.onkeypress(drawere, "d")
wn.listen()
wn.mainloop()
It gives a stack overflow error. Does anyone know why this issue persists? It doesn't happen when i let go of it once in a while.
I believe the stack overflow error is due to repeated assigning of angle to the stack. To prevent this, you can introduce a debounce. We will name our debounce as move.
A debounce, in simple terms, is fail-safe to prevent an event for triggering again and again while keeping the rest of the code running.
Define the variable in global space:
move = False
As for the function:
def drawern():
global move #To let the function know the variable is from global scope
if not move: #The key is pressed first time
drawer.seth(90)
move = True #Sets our debounce to True, it will not activate until the key is released
drawer.fd(1)
wn.onkeypress(drawern, "w")
We need to have another function with an event to reset our debounce:
def reset_db():
global move
move = False #Resets the debounce, referencing the key has been released
wn.onkeyrelease(reset_db, "w") #Connects the event
I have demonstrated for w key here only. You can duplicate it for the rest of the keys too.
I'm trying to do a pause menu for my game in Ursina Engine and I can't fount informatino how the function pause() works or how to do it.
Can someone help me?
Pausing is already implemented in ursina. Just set application.paused to True or False. application.pause() and application.resume() does the same.
from ursina import *
app = Ursina()
# Make a simple game so we have something to test with
from ursina.prefabs.first_person_controller import FirstPersonController
player = FirstPersonController(gravity=0, model='cube', color=color.azure)
camera.z = -10
ground = Entity(model='plane', texture='grass', scale=10)
# Create an Entity for handling pausing an unpausing.
# Make sure to set ignore_paused to True so the pause handler itself can still recieve input while the game is paused.
pause_handler = Entity(ignore_paused=True)
pause_text = Text('PAUSED', origin=(0,0), scale=2, enabled=False) # Make a Text saying "PAUSED" just to make it clear when it's paused.
def pause_handler_input(key):
if key == 'escape':
application.paused = not application.paused # Pause/unpause the game.
pause_text.enabled = application.paused # Also toggle "PAUSED" graphic.
pause_handler.input = pause_handler_input # Assign the input function to the pause handler.
app.run()
So I'm trying to monkey patch the onkey function in turtle so it calls a function with the button hit instead of just calling it with no arguments. I'm using the string "tester" to see if it works, but it looks like the original functions never got changes. Can someone explain what I'm doing wrong?
from threading import Thread
from time import sleep
from turtle import *
def NEWonkeypress(self, fun, key=None):
if fun is None:
if key in self._keys:
self._keys.remove(key)
elif key is not None and key not in self._keys:
self._keys.append(key)
self._onkeypress(fun, key)
def _NEWonkeypress(self, fun, key=None):
if fun is None:
if key is None:
self.cv.unbind("<KeyPress>", None)
else:
self.cv.unbind("<KeyPress-%s>" % key, None)
else:
def eventfun(event):
fun("tester")
if key is None:
self.cv.bind("<KeyPress>", eventfun)
else:
self.cv.bind("<KeyPress-%s>" % key, eventfun)
Turtle.onkeypress = NEWonkeypress
Turtle._onkeypress = _NEWonkeypress
board = Turtle()
screen = board.getscreen()
screen.tracer(0, 0)
temp = Turtle()
def textinput(testing):
print(testing)
def getroomname(option):
global temp
global board
#Box
temp.fillcolor("White")
temp.width(10)
temp.goto(-150, -60)
temp.down()
temp.begin_fill()
for x in range(2):
temp.forward(300)
temp.left(90)
temp.forward(120)
temp.left(90)
temp.end_fill()
temp.up()
temp.goto(0, 100)
screen.update()
#Box
temp.goto(0, -60)
screen.onkeypress(textinput)
listen()
getroomname(0)
mainloop()
(This is just a snippet of the main code, so don't worry about the random square it draws in space)
It's actually simpler than you're making it, we just need to go about it a little differently. When you run the code below, any key you type should get passed through turtle's event system and printed to the console:
from functools import partial
from turtle import Screen, Turtle
def getroomname():
temp.penup()
temp.goto(-150, -60)
temp.pendown()
temp.begin_fill()
for _ in range(2):
temp.forward(300)
temp.left(90)
temp.forward(120)
temp.left(90)
temp.end_fill()
def _onkeypress(self, fun, key=None):
if fun is None:
if key is None:
self.cv.unbind("<KeyPress>", None)
else:
self.cv.unbind("<KeyPress-%s>" % key, None)
else:
def eventfun(event):
fun(event.char)
if key is None:
self.cv.bind("<KeyPress>", eventfun)
else:
self.cv.bind("<KeyPress-%s>" % key, eventfun)
def keyinput(key):
print(key)
screen = Screen()
screen._onkeypress = partial(_onkeypress, screen) # monkey patch (protected access)
temp = Turtle()
temp.speed('fastest')
temp.fillcolor("white")
temp.width(10)
getroomname()
screen.onkeypress(keyinput)
screen.listen()
screen.mainloop()
I simplified your unrelated code. However, you're not using global correctly so I suggest you review a tutorial about that before you run into trouble. Also, you did from turtle import * but then did def textinput(...) where textinput is also method of Python 3 turtle -- so avoid doing from turtle import * to avoid even more trouble.
I am attempting to make pong using Turtle, I have most things working, however, I would like to implement the ability to hold a key to move the bumpers up and down, rather than having to tap the key multiple times. These are my functions for movement so far.
def lbump_move_up():
x = lbump.ycor()
x += bumpspeed
if x > 240:
x = 240
lbump.sety(x)
def lbump_move_down():
x = lbump.ycor()
x -= bumpspeed
if x < -240:
x = -240
lbump.sety(x)
def rbump_move_up():
x = rbump.ycor()
x += bumpspeed
if x > 240:
x = 240
rbump.sety(x)
def rbump_move_down():
x = rbump.ycor()
x -= bumpspeed
if x < -240:
x = -240
rbump.sety(x)
turtle.listen()
turtle.onkey(lbump_move_up,'w')
turtle.onkey(rbump_move_up,'Up')
turtle.onkey(lbump_move_down,'s')
turtle.onkey(rbump_move_down,'Down')
turtle.onkey(ball_move,'Return')
I don't have a complete answer to this, as I came here looking for one myself. However, I have some progress on it that someone else could finish...
You can create a new class that calls like a recursive function as follows:
class function2:
def __init__(self,fun,args=None):
self.fun=fun
self.args=args
def begin_loop(self):
self.looping=True
self.loop()
def loop(self):
self.fun(self.args)
if self.looping: self.loop()
def end_loop(self):
self.looping=False
Now to tie it to your example, you can convert your functions into function2s and thus call them onkeypress as follows:
l_up=function2(lbump_move_up)
r_up=function2(rbump_move_up)
l_down=function2(lbump_move_down)
r_down=function2(rbump_move_down)
Wn=turtle.Screen()
Wn.onkeypress(l_up.begin_loop,'w')
Wn.onkeypress(r_up.begin_loop,'Up')
Wn.onkeypress(l_down.begin_loop,'s')
Wn.onkeypress(r_down.begin_loop,'Down')
Wn.onkeyrelease(l_up.end_loop,'w')
Wn.onkeyrelease(r_up.end_loop,'Up')
Wn.onkeyrelease(l_down.end_loop,'s')
Wn.onkeyrelease(r_down.end_loop,'Down')
Wn.listen()
So to the issue: RecursionErrors
If you want your function to cause a small change, then you'll need to hold the button for a long time and that causes RecursionErrors - which at least in this case don't seem to be affected by try/except statements.
Once again, sorry for the incomplete solution, but I feel like you can probably get away with larger movements in pong.
I had the same issue, but found the "onkeypress" function in the Turtle documentation (https://docs.python.org/3/library/turtle.html#turtle.onkeypress), which resolved the issue for me.
turtle.onkeypress(fun, key=None)
"onkeypress", will move the turtle as long as the key is pressed, while "onkey" will move it once when the key is released.
Example:
from turtle import Turtle, Screen
turtle = Turtle("turtle")
turtle.penup()
screen = Screen()
screen.listen()
def move_forward():
turtle.forward(20)
def move_backward():
turtle.backward(20)
screen.onkeypress(move_forward, "w")
screen.onkey(move_backward, "s")
screen.exitonclick()
I'm in the process of creating a basic game in pygame at the moment, and one part of that is the procedural generation of new areas as you go off the screen. As a test, I'm looking to generate an object once per area by defining its variables, and then save that area's object within the class for if you come back to it later. Here's what I have at the moment:
#area_gen is set to "true" if you move to a new area
#swidth and sheight are set to the size of the screen
#x_area and y_area are defined as you change areas, acting as sector coordinates
#Red is defined in globals
class areas:
def __init__(self, coords):
self.coordinates = coords
self.generated = False
def gen_objects(self):
if not self.generated:
self.objs = []
obj_type = "test object"
center_x = random.randrange(105, swidth-25)
center_y = random.randrange(25, swidth - 175)
self.objs.append([obj_type, center_x, center_y])
self.generated = True
#Within The Game Loop
if area_gen == "true":
coords = str(str(x_area) + " " + str(y_area))
area = areas(coords)
area.gen_objects()
for thing in area.objs:
if thing[0] == "test object":
pygame.draw.rect(screen, Red, (thing[1], thing[2], 250, 250))
#Bottom of the Game Loop
area_gen = "false"
What I thought the self.generated variable would do was stop the new object generation if one already existed, but that doesn't seem to be working. The square still generates at a new location even if the area has already been visited. My knowledge on classes is relatively limited, so I'm a bit stuck as to where to go from here.
Pass area_gen into the constructor for the areas class, and set self.generated = area_gen. Does this work? I can't see enough of your code to know, to be honest.