我希望在海龟图形学中将弹跳球放在墙上,但是它们停下来,徘徊并发送错误

时间:2019-04-28 05:27:22

标签: python turtle-graphics

我画了一些三角形,它们应该在墙上弹跳,但它们不会弹跳,它们不能笔直,它们会在几秒钟后显示错误消息。

当我让三角形仅以十字形移动时,三角形摇摇欲坠,并出现错误消息。

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()

这应该是一款游戏,玩家在盒子中避开三角形。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

对于如何设置ontimer(timer_go, 100),我同意@furas(+1),但是我发现您的代码还有其他问题。我在下面对其进行了重新设计,希望您发现一些有用的更改。

特定问题:您需要(重新)阅读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是由于您的按键事件造成的,因为您的模型似乎是一次可以关闭多个按键。但是,如果键的按住时间太长,则可能导致键事件内部发生键事件,这看起来像递归。通常,您可以通过禁用键事件处理程序作为事件处理程序中的第一件事来解决此问题,完成您的工作,然后重新启用键事件处理程序。

但是,您可能还需要操作系统控制的自动按键重复逻辑来对付您。如果您发现密钥处理有问题,请考虑使用更简单的方法。