我想在turtlegraphics的墙上弹跳一个球,但他们停下来,他们徘徊并发送错误

问题描述 投票:1回答:2

我绘制了一些三角形,它们应该在墙上反弹,但是它们不会弹跳,它们不会直线,它们会在几秒钟后打印出错误信息。

当我让三角形只以十字形移动时,三角形会动摇并出现错误信息。

import turtle
import random
def draw_sq(t,distance=400):#Draw a box
    t.penup()
    t.goto(-200,200)
    t.pendown()
    t.forward(distance)
    t.right(90)
    t.forward(distance)
    t.right(90)
    t.forward(distance)
    t.right(90)
    t.forward(distance)
    t.penup()
    t.goto(0,0)
    t.pendown()
def add_tri():
    global l_tri
    t=turtle.Turtle()
    t.shape("triangle")
    x=-200
    y=random.randint(-200,200)
    t.penup()
    t.goto(x,y)
    t.setheading(random.randint(-89,89))
    # make triangle and start
    l_tri.append(t)# add a triangle to list
def successMan():#write word succes 
    global playing
    if playing==True:
        t.write("success")

def turn_right():
    global right
    right = True

def turn_left():
    global left
    left = True

def turn_up():
    global up
    up = True

def turn_down():
    global down
    down = True

def _turn_right():
    global right
    right = False

def _turn_left():
    global left
    left = False

def _turn_up():
    global up
    up = False

def _turn_down():
    global down
    down = False

def is_touch(x,y,triangle,threshold=20):
    global playing
    if((x-triangle.position()[0])**2+(y-triangle.position()[1])**2<=threshold**2):
        playing=False#if triangle touches the turtle make playing False

def timer_go():
    global heading
    global l_tri
    global t
    global playing
    global up
    global left
    global down
    global right# heading is where turtle heads
    if up:
        if right:
            heading=45
        elif left:
            heading=135
        elif down:
            heading = heading
        else:
            heading=90
    if down:
        if right:
            heading=315
        elif left:
            heading=225
        elif up:
            pass
        else:
            heading = 270
    if left:
        if right:
            heading = heading
        elif up:
            pass
        elif down:
            pass
        else:
            heading = 180
    if right:
        if left:
            pass
        elif up:
            pass
        elif down:
            pass
        else:
            heading = 0

    t.setheading(heading)
    t.forward(10)
        # turtle controller
    for i in range(3):#triangles move
        if (l_tri[i].position()[0]<-200):
            l_tri[i].setheading(180-l_tri[i].heading())
            l_tri[i].forward(10)
        if (l_tri[i].position()[0]>200):
            l_tri[i].setheading(180-l_tri[i].heading())
            l_tri[i].forward(10)
        if (l_tri[i].position()[1]<-200):
            l_tri[i].setheading(-l_tri[i].heading())
            l_tri[i].forward(10)
        if (l_tri[i].position()[1]>200):
            l_tri[i].setheading(-l_tri[i].heading())
            l_tri[i].forward(10)#triangle bounces on the wall
        l_tri[i].forward(10)
        is_touch(t.position()[0],t.position()[1],l_tri[i],threshold=20)
    # check triangle and turtle
    if (playing==False):
        t.write("FAIL")
        #Fail

up = False
down = False
right = False
left = False
playing = True
heading = 0
l_tri = []

t = turtle.Turtle()
t.shape('turtle')
t.speed(0)
draw_sq(t)
screen = t.screen

screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')
screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')


for i in range(3):
    add_tri()
for i in range(1,200):
    time = i*100
    screen.ontimer(timer_go, time)
screen.ontimer(successMan,20000)
screen.listen()
screen.mainloop()

这应该是玩家避开盒子中的三角形的游戏。

python turtle-graphics
2个回答
1
投票

当我运行它时,我看到错误

RecursionError: maximum recursion depth exceeded while calling a Python object

但我没有在代码中看到递归。

也许问题是

for i in range(1,200):
    time = i*100
    screen.ontimer(timer_go, time)

可能它创造了太多的功能。

你可以运行一次

screen.ontimer(timer_go, 100)

并在timer_go()结束时再次使用它

def timer_go():

    # ... rest of code ...

    screen.ontimer(timer_go, 100)

它会一直重复。

即使在官方文档中也可以看到这种方法:turtle.ontimer


0
投票

我同意@furas(+1)关于如何设置你的ontimer(timer_go, 100),但我看到你的代码存在其他问题。我在下面重写了它,我希望你能找到一些有用的变化。

具体问题:您需要(重新)阅读有关global的一半时间,因为您错误地使用它;你不需要重新发明turtle.distance()(例如在is_touch());你需要将playing == False与失败分开,因为你需要在成功或失败时停止游戏;您只需要在一个地方指定三角形的数量:

from turtle import Screen, Turtle
from random import randint, choice

FONT = ('Arial', 16, 'normal')

def draw_square(turtle, distance=400):  # Draw a box
    turtle.speed('fastest')
    turtle.penup()
    turtle.goto(-200, 200)
    turtle.pendown()

    for _ in range(4):
        turtle.forward(distance)
        turtle.right(90)

def add_triangle():
    triangle = Turtle("triangle")
    triangle.penup()
    triangle.goto(choice([(choice([-150, 150]), randint(-150, 150)), (randint(-150, 150), choice([-150, 150]))]))
    triangle.setheading(randint(-89, 89))
    # make triangle and start
    triangles.append(triangle)  # add a triangle to list

def successMan():  # write word success
    global playing

    if playing:
        player.write("Success!", font=FONT)
        playing = False

def turn_right():
    global right
    right = True

def turn_left():
    global left
    left = True

def turn_up():
    global up
    up = True

def turn_down():
    global down
    down = True

def _turn_right():
    global right
    right = False

def _turn_left():
    global left
    left = False

def _turn_up():
    global up
    up = False

def _turn_down():
    global down
    down = False

def is_touch(player, triangle, threshold=20):
    return player.distance(triangle) < threshold

def timer_go():
    global playing

    heading = player.heading()

    if up:
        if right:
            heading = 45
        elif left:
            heading = 135
        elif down:
            pass
        else:
            heading = 90

    if down:
        if right:
            heading = 315
        elif left:
            heading = 225
        elif up:
            pass
        else:
            heading = 270

    if left:
        if right:
            pass
        elif up:
            pass
        elif down:
            pass
        else:
            heading = 180

    if right:
        if left:
            pass
        elif up:
            pass
        elif down:
            pass
        else:
            heading = 0

    player.setheading(heading)
    player.forward(10)

    # turtle controller
    for triangle in triangles:  # triangles move
        x, y = triangle.position()

        if not -200 < x < 200:
            triangle.setheading(180 - triangle.heading())
            triangle.forward(10)

        if  not -200 < y < 200:
            triangle.setheading(-triangle.heading())
            triangle.forward(10)

        triangle.forward(10)

        # check triangle and turtle
        if is_touch(player, triangle, threshold=20):
            playing = False
            player.write("FAIL!", font=FONT)  # Fail

    if playing:
        screen.ontimer(timer_go, 100)

up = False
down = False
right = False
left = False

playing = True
triangles = []

draw_square(Turtle(visible=False))

for _ in range(3):
    add_triangle()

player = Turtle('turtle')
player.speed('fastest')

screen = Screen()

screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')

screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')

screen.ontimer(successMan, 20_000)

timer_go()

screen.listen()
screen.mainloop()

我怀疑你的RecursionError是由于你的关键事件,因为你的模型似乎是多个键可以一次关闭。但是如果一个键保持太长时间,它可能会导致键事件中的键事件,这看起来像递归。您通常可以通过禁用键事件处理程序作为事件处理程序中的第一件事,执行您的工作,然后重新启用键事件处理程序来解决此问题。

但是,您可能还有操作系统控制的自动键重复逻辑对您不利。如果您的密钥处理结果是一个问题,请考虑使用更简单的方法。

© www.soinside.com 2019 - 2024. All rights reserved.