简体   繁体   English

如何使用箭头键在 Python 3 中移动海龟

[英]How to move turtles in Python 3 with arrow keys

I am having trouble getting my turtle to be able to follow the arrow keys, any help on how to do so would be greatly appreciated.我无法让我的乌龟跟随箭头键,任何有关如何操作的帮助将不胜感激。 I'm sure this question has been asked before, though I can't seem to find it, and the ones I do find are for older versions.我确定这个问题以前有人问过,虽然我似乎找不到它,而且我找到的那些是针对旧版本的。

import turtle
#screen
wn=turtle.Screen()
wn.bgcolor("lightblue")

I plan on this being a spaceship game
#Turtle Player
spaceship= turtle.Turtle()
spaceship.color("red")
spaceship.penup()
speed=1

This is where I am stuck, I don't know how to make the turtle follow the arrow keys这就是我卡住的地方,我不知道如何让乌龟跟随方向键

#keyboard bindings

while True:
    spaceship.forward(speed)

Avoid using an infinite loop like while True: inside a turtle graphics program, it can keep some of your events from firing.避免使用像while True:这样的无限循环while True:在海龟图形程序中,它可以阻止您的某些事件触发。

Below is the minimal code I could come up with to make your spaceship navigatible.下面是我可以想出的最小代码,以使您的宇宙飞船可导航。 You should be able to build on this:您应该能够以此为基础:

from turtle import Turtle, Screen

wn = Screen()
wn.bgcolor('lightblue')

spaceship = Turtle()
spaceship.color('red')
spaceship.penup()

speed = 1

def travel():
    spaceship.forward(speed)
    wn.ontimer(travel, 10)

wn.onkey(lambda: spaceship.setheading(90), 'Up')
wn.onkey(lambda: spaceship.setheading(180), 'Left')
wn.onkey(lambda: spaceship.setheading(0), 'Right')
wn.onkey(lambda: spaceship.setheading(270), 'Down')

wn.listen()

travel()

wn.mainloop()

Click on the turtle graphics window before issuing keyboard commands to make sure it is listening.在发出键盘命令之前单击海龟图形窗口以确保它正在侦听。 Also, there are other approaches to how the keys should work, I've used absolute motion here but you might want relative where each press incrementally modifies your direction.此外,还有其他方法可以解决按键的工作方式,我在这里使用了绝对运动,但您可能需要相对,每次按下都会增量修改您的方向。

First, we got to understand the basics.首先,我们必须了解基础知识。 In order for the user to be able to interact with the turtle through key presses, we need to let the window listen for key presses.为了让用户能够通过按键与海龟交互,我们需要让窗口 监听按键。 Since your screen is named wn , that can be done simply by calling wn.listen() .由于您的屏幕名为wn ,因此只需调用wn.listen()即可完成。

Now that the turtle graphics are listening for key presses, how will you tell the program to do something through key presses?既然海龟图形正在侦听按键,您将如何通过按键告诉程序执行某些操作? Functions!职能! Let's say you want a new turtle to be created every time a key is pressed;假设您希望每次按下一个键时都创建一个新的海龟; you will need to define a function like so (you can use lambda for the function, but for now, let's stick to def ) :您将需要像这样定义一个函数(您可以将lambda用于该函数,但现在,让我们坚持使用def

def create_new_turtle():
    new_turtle = turtle.Turtle()

Keep in mind that you shall not pass any positional arguments into the brackets when defining the function, as you will not be able to pass your arguments in when you use the function, resulting in an TypeError .请记住,在定义函数时不应将任何位置参数传递到括号中,因为在使用函数时将无法传递参数,从而导致TypeError

Now, let's get into how we can actually call these function during run-time when a key is pressed.现在,让我们深入了解如何在运行时按下按键时实际调用这些函数。 With wn.listen() initiated, now all you'll need is wn.onkey , or wn.onkeypress .启动wn.listen() ,现在您只需要wn.onkeywn.onkeypress Taking the function above, if you want a new turtle to be created every time the user presses the SPACE key:以上面的函数为例,如果你想在每次用户按下空格键时都创建一个新的海龟:

wn.onkey(create_new_turtle, 'space')

Do you see why we can't pass positional arguments into the function?你明白为什么我们不能将位置参数传递给函数吗? As you can see, when using the function inside wn.onkey , we do not call it (as in, we did not add brackets on the right side of the function) ;如您所见,在wn.onkey使用函数时,我们没有调用它(例如,我们没有在函数右侧添加括号) wn.onkey does it for us. wn.onkey为我们做到了。

Taking what we've learned, let's see them in action:结合我们学到的知识,让我们看看它们的实际效果:

import turtle

#Screen
wn = turtle.Screen()
wn.bgcolor("lightblue")

#Turtle Player
spaceship = turtle.Turtle()
spaceship.color("red")
spaceship.penup()

#Constant
speed = 1

def up():
    spaceship.setheading(90)

def down():
    spaceship.setheading(270)
    
def left():
    spaceship.setheading(180)

def right():
    spaceship.setheading(0)

wn.listen()
wn.onkey(up, 'Up')
wn.onkey(down, 'Down')
wn.onkey(left, 'Left')
wn.onkey(right, 'Right')

while True:
    spaceship.forward(speed)

Can you guess what this does?你能猜出这是做什么的吗? It's pretty obvious;这很明显; when the user hits the 'Up' arrow, the up function defined above will be called, when the user hits the 'Down' arrow, the down function defined above will be called, an so on.当用户点击'Up'箭头时,将调用上面定义的up函数,当用户点击'Down'箭头时,将调用上面定义的down函数,以此类推。

Defining a whole function for a single command doesn't seem right, and we can't just do为单个命令定义整个函数似乎不正确,我们不能只是这样做

wn.onkey(spaceship.setheading(90), 'Up')
wn.onkey(spaceship.setheading(270), 'Down')
wn.onkey(spaceship.setheading(180), 'Left')
wn.onkey(spaceship.setheading(0), 'Right')

Like in the most upvoted answer, the solution is to use lambda , where the error causing code right above can be corrected to就像在最受好评的答案中一样,解决方案是使用lambda ,其中导致上面代码的错误可以更正为

wn.onkey(lambda: spaceship.setheading(90), 'Up')
wn.onkey(lambda: spaceship.setheading(270), 'Down')
wn.onkey(lambda: spaceship.setheading(180), 'Left')
wn.onkey(lambda: spaceship.setheading(0), 'Right')

Lastly, if you want your turtle to turn 90 degrees maximum on each turn, you can avoid 180 degree turn with if statements in the functions (which, as the functions get more advanced, it is better to use def to define the functions instead of using lambda ) :最后,如果你想让你的海龟在每次转弯时最大转90度,你可以在函数中使用if语句来避免180度转(随着函数变得更高级,最好使用def来定义函数而不是使用lambda )

import turtle

#Screen
wn = turtle.Screen()
wn.bgcolor("lightblue")

#Turtle Player
spaceship = turtle.Turtle()
spaceship.color("red")
spaceship.penup()

#Constant
speed = 1

def up():
    if spaceship.heading() != 270:
        spaceship.setheading(90)

def down():
    if spaceship.heading() != 90:
        spaceship.setheading(270)
    
def left():
    if spaceship.heading() != 0:
        spaceship.setheading(180)

def right():
    if spaceship.heading() != 180:
        spaceship.setheading(0)

wn.listen()
wn.onkey(up, 'Up')
wn.onkey(down, 'Down')
wn.onkey(left, 'Left')
wn.onkey(right, 'Right')

while True:
    spaceship.forward(speed)

Test run:测试运行:

在此处输入图片说明

I have solution for you.我有你的解决方案。 The code is not ideal but it works and you can work on it.该代码并不理想,但它有效,您可以对其进行处理。 You have to be aware, that the turtle has deafult position, and you have to tune it.你必须知道,乌龟的位置是默认的,你必须调整它。 That is why I pointed in the setup method my turtle to look up.这就是为什么我在设置方法中指出我的海龟要查找的原因。

Now, You have to remember, that right(deg) and left(deg) methods are saying "please turn around by such amount of degree in given direction".现在,您必须记住, right(deg)left(deg)方法是说“请在给定方向上以这样的度数转身”。

So keep in mind, what was your last direction.所以请记住,你最后的方向是什么。

Key for understanding here is that You don't have access to any absolute here.理解这里的关键是您无法访问这里的任何绝对值 You only can change something in relation to your current posisition.您只能更改与您当前职位相关的某些内容。 So, you can't turn left, but if you know previous direction, you know how many degree you should turn your turtle to actually turn left.所以,你不能左转,但如果你知道以前的方向,你就知道你应该把乌龟转多少度才能真正向左转。

My working code for your task is:我为您的任务工作的代码是:

import turtle
wn = turtle.Screen()

last_pressed = 'up'

def setup(col, x, y, w, s, shape):
  turtle.up()
  turtle.goto(x,y)
  turtle.width(w)
  turtle.turtlesize(s)
  turtle.color(col)
  turtle.shape(shape)
  turtle.lt(90)
  turtle.down()
  wn.onkey(up, "Up")
  wn.onkey(left, "Left")
  wn.onkey(right, "Right")
  wn.onkey(back, "Down")
  wn.onkey(quitTurtles, "Escape")
  wn.listen()
  wn.mainloop()




#Event handlers
def up():
  global last_pressed
  if last_pressed == 'left':
    turtle.rt(90)
    turtle.fd(10)
  elif last_pressed == 'right':
    turtle.lt(90)
    turtle.fd(10)
  elif last_pressed == 'up':
    turtle.fd(10)
  else:
    turtle.rt(180)
    turtle.fd(10)

  last_pressed = 'up'

def left():
  global last_pressed
  if last_pressed == 'left':
    turtle.fd(10)
  elif last_pressed == 'right':
    turtle.lt(180)
    turtle.fd(10)
  elif last_pressed == 'up':
    turtle.lt(90)
    turtle.fd(10)
  else:
    turtle.rt(90)
    turtle.fd(10)

  last_pressed = 'left'


def right():
  global last_pressed
  if last_pressed == 'left':
    turtle.rt(180)
    turtle.fd(10)
  elif last_pressed == 'right':
    turtle.fd(10)
  elif last_pressed == 'up':
    turtle.rt(90)
    turtle.fd(10)
  else:
    turtle.lt(90)
    turtle.fd(10)

  last_pressed = 'right'

def back():
  global last_pressed
  if last_pressed == 'left':
    turtle.lt(90)
    turtle.fd(10)
  elif last_pressed == 'right':
    turtle.rt(90)
    turtle.fd(10)
  elif last_pressed == 'up':
    turtle.rt(180)
    turtle.fd(10)
  else:
    turtle.fd(10)

  last_pressed = 'down'

def quitTurtles():
  wn.bye()

setup("blue",-200,200,2,2,"turtle")

Please bear in mind that it takes some time for the turtle to actually turn, so don't press keys, click them.请记住,乌龟真正转动需要一些时间,所以不要按键,点击它们。

I think that You can go further with this.我认为你可以更进一步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM