简体   繁体   English

Tkinter & 龟蛇游戏

[英]Tkinter & Turtle Snake Game

I have been experimenting with Tkinter's canvas feature.我一直在试验 Tkinter 的画布功能。 I put turtle in the canvas and am trying to make a snake game.我把乌龟放在画布上,并试图制作一个蛇游戏。 I tried to run the code but have some problems:我试图运行代码但有一些问题:

  1. It doesn't print the score when you press close of escape to quit,当您按退出退出时,它不会打印分数,

  2. You can only take the pen up once, you can't put it back down or put it up again,笔只能举一次,不能放回去,也不能再放,

  3. The turtle called player sometimes doesn't spawn on the part of the screen you can actually see,称为玩家的乌龟有时不会生成在您实际可以看到的屏幕部分,

  4. The turtle called t doesn't add to the score as you touch the turtle called player or move the turtle called player.当您触摸名为 player 的乌龟或移动名为 player 的乌龟时,名为 t 的乌龟不会增加分数。

There might be other problems but these are the ones I know.可能还有其他问题,但这些是我所知道的。

Here is my code:这是我的代码:

import tkinter as tk
import random
import turtle
import time
import sys

game = False
forward = False
left = False
right = False
backward = False
draw = True
score = 0

def spawn(e=None):
    t.penup()
    t.goto(0,0)
    player=turtle.RawTurtle(app)
    player.penup()
    player.shapesize(0.5,0.5)
    player.shape("square")
    player.color("black")
    xrand = random.randint(-100, 100)
    yrand = random.randint(-100, 100)
    player.goto(x=xrand,y=yrand)
    if t.distance(player) <15:
        x = random.randint(-100, -100)
        y = random.randint(-100, -100)
        player.goto(x,y)
        score = score+1

def systemap(e=None):
    app.place(x=100,y=-4)
    button.place(x=660,y=470)

def f(e=None):
    if game == False:
        t.setheading(90)
        t.forward(5)
    elif game == True:
        forward == True
        while forward == True:
            left == False
            right == False
            backward == False
            t.forward(5)
        if forward == False:
            t.setheading(90)
            t.forward(5)

def l(e=None):
    if game == False:
        t.setheading(180)
        t.forward(5)
    elif game == True:
        left == True
        while left == True:
            forward == False
            right == False
            backward == False
            t.forward(5)
        if left == False:
            t.setheading(180)
            t.forward(5)

def r(e=None):
    if game == False:
        t.setheading(0)
        t.forward(5)
    elif game == True:
        right == True
        while right == True:
            forward == False
            left == False
            backward == False
            t.forward(5)
        if right == False:
            t.setheading(0)
            t.forward(5)

def b(e=None):
    if game == False:
        t.setheading(270)
        t.forward(5)
    elif game == True:
        backward == True
        while backward == True:
            forward == False
            left == False
            right == False
            t.forward(5)
        if backward == False:
            t.setheading(270)
            t.forward(5)

def quit(e=None):
    if game == False:
        time.sleep(1)
        window.destroy()
        sys.exit()
    elif game == True:
        time.sleep(2)
        window.destroy()
        print("Score: ",score)
        sys.exit()

def pen(e=None):
    if draw == True:
        t.penup()
        draw == False
    if draw == False:
        t.pendown()
        draw == True

window = tk.Tk()
window.iconbitmap('py.ico')
window.title("Turtle Graphics")
window.geometry("750x500")
window.resizable(False, False)

button = tk.Button(window,
                   text="      Close      ",
                   font="Calibri",
                   borderwidth=0,
                   background="White",
                   command=quit)

app = tk.Canvas(master=window, width=500, height=500, bg="white")

t=turtle.RawTurtle(app)

window.bind("<Up>", f)
window.bind("<Left>", l)
window.bind("<Right>", r)
window.bind("<Down>", b)

window.bind("<w>", f)
window.bind("<a>", l)
window.bind("<d>", r)
window.bind("<s>", b)

window.bind("<p>", pen)

window.bind("<Escape>", quit)

window.bind("<g>", spawn)

systemap()

window.mainloop()

So there are several correction that need to be made here.所以这里需要做几个更正。 I think you have some misconceptions about a few things.我认为你对一些事情有一些误解。

  1. You need to define global in your functions that contain variables that are in the global name space or need to be there.您需要在包含全局命名空间中或需要存在的变量的函数中定义global If you do not you run into errors like local variable 'score' referenced before assignment when trying to update the variable.如果不这样做,则在尝试更新变量时会遇到诸如local variable 'score' referenced before assignment类的错误。

  2. The == is a comparison only. ==只是一个比较。 You are using it in places that need to be a single = .您在需要是单个=地方使用它。

  3. You define a function called quit and this is a built in method.您定义了一个名为quit的函数,这是一个内置方法。 Please be careful not to overwrite build in methods.请注意不要覆盖内置方法。

  4. You never see the score printed because game is always False.您永远不会看到打印的分数,因为game总是错误的。 Nothing in your code changes it to True.您的代码中没有任何内容将其更改为 True。

  5. while and sleep() should not be used in the same thread as tkinter. whilesleep()不应与 tkinter 在同一线程中使用。 This will cause issue as both of those methods block the mainloop.这将导致问题,因为这两种方法都会阻塞主循环。 One way to manage this is to use the after() method or threading instead.管理这种情况的一种方法是改用after()方法或线程。 In this case I think threading is overkill and after() is probably the better choice here.在这种情况下,我认为线程是矫枉过正的, after()可能是更好的选择。

Lastly I cannot really completely fix you code as I am not sure where you need to add game = True .最后,我无法真正完全修复您的代码,因为我不确定您需要在哪里添加game = True

Here is your code cleaned up a bit.这是您的代码清理了一下。 I have corrected most of what was listed but without some more details I cannot guess at what you are needing for the rest.我已经更正了列出的大部分内容,但没有更多细节,我无法猜测您对其余部分的需求。

Let me know if you have any questions:如果您有任何问题,请告诉我:

import tkinter as tk
import random, turtle

game = False
forward = False
left = False
right = False
backward = False
draw = True
score = 0


def spawn(_=None):
    global score, forward, left, backward, player
    t.penup()
    t.goto(0, 0)
    player = turtle.RawTurtle(app)
    player.penup()
    player.shapesize(0.5, 0.5)
    player.shape("square")
    player.color("black")
    xrand = random.randint(-100, 100)
    yrand = random.randint(-100, 100)
    player.goto(x=xrand, y=yrand)
    if t.distance(player) < 15:
        x = random.randint(-100, -100)
        y = random.randint(-100, -100)
        player.goto(x, y)
        score = score + 1


def systemap(_=None):
    app.place(x=100, y=-4)
    button.place(x=660, y=470)


def f(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(90)
        t.forward(5)
    else:
        forward = True
        while forward:
            left = False
            right = False
            backward = False
            t.forward(5)
        if not forward:
            t.setheading(90)
            t.forward(5)


def l(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(180)
        t.forward(5)
    else:
        left = True
        while left:
            forward = False
            right = False
            backward = False
            t.forward(5)
        if not left:
            t.setheading(180)
            t.forward(5)


def r(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(0)
        t.forward(5)
    else:
        right = True
        while right:
            forward = False
            left = False
            backward = False
            t.forward(5)
        if not right:
            t.setheading(0)
            t.forward(5)


def b(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(270)
        t.forward(5)
    else:
        backward = True
        while backward:
            forward = False
            left = False
            right = False
            t.forward(5)
        if not backward:
            t.setheading(270)
            t.forward(5)


def quit_func(_=None):
    if not game:
        window.destroy()
    else:
        window.destroy()
        print("Score: ", score)


def pen(_=None):
    global draw
    if draw:
        t.penup()
        draw = False
    else:
        t.pendown()
        draw = True


window = tk.Tk()
window.title("Turtle Graphics")
window.geometry("750x500")
window.resizable(False, False)
button = tk.Button(window, text="Close", font="Calibri", borderwidth=0, background="White", command=quit_func)
app = tk.Canvas(master=window, width=500, height=500, bg="white")
t = turtle.RawTurtle(app)

window.bind("<Up>", f)
window.bind("<Left>", l)
window.bind("<Right>", r)
window.bind("<Down>", b)
window.bind("<w>", f)
window.bind("<a>", l)
window.bind("<d>", r)
window.bind("<s>", b)
window.bind("<p>", pen)
window.bind("<Escape>", quit_func)
window.bind("<g>", spawn)

systemap()
window.mainloop()

The primary issue I see is that you want the turtle to move constantly with the user of the program only changing the direction.我看到的主要问题是您希望海龟随着程序的用户不断移动而只改变方向。 I don't believe you'll ever get that effect with an infinite loop like:我不相信你会通过无限循环获得这种效果,例如:

    while right == True:
        forward == False
        left == False
        backward == False
        t.forward(5)

Which relies on some outside event to change the value of right but not really pausing to let other events run.这依赖于一些外部事件来改变right的值,但并没有真正暂停让其他事件运行。 (Plus the incorrect use of == vs = .) (加上===的错误使用。)

Other problems include:其他问题包括:

The player can only relocate once, always to the same spot due to a sign error:由于符号错误,玩家只能重新定位一次,始终移动到同一地点:

x = random.randint(-100, -100)
y = random.randint(-100, -100)

Lack of necessary global statements along with == vs = misuse:缺少必要的global语句以及== vs =误用:

def pen(e=None):
    if draw == True:
        t.penup()
        draw == False
    if draw == False:
        t.pendown()
        draw == True

You never should have coded as much as you did without testing some of these basic functions.如果没有测试这些基本功能中的一些,您永远不应该像您那样编码。 The more untested code you write, the harder it is to debug.您编写的未经测试的代码越多,调试起来就越困难。

Below is my rework of your code, implementing constant motion of the turtle (snake).下面是我对你的代码的返工,实现了乌龟(蛇)的恒定运动。 I also moved some turtle-related code out of the tkinter realm into turtle methods.我还将一些与海龟相关的代码从 tkinter 领域移到了海龟方法中。 I simplified some things for the example (eg only one set of motion keys, the arrows.) But I believe it's now a very basic but playable game:我为这个例子简化了一些东西(例如只有一组运动键,箭头。)但我相信它现在是一个非常基本但可玩的游戏:

import tkinter as tk
from turtle import TurtleScreen, RawTurtle
from random import randint

direction = None
score = 0

def spawn():
    player = RawTurtle(screen)
    player.hideturtle()
    player.shape('square')
    player.shapesize(0.5)
    player.color('black')
    player.penup()

    x = randint(-100, 100)
    y = randint(-100, 100)
    player.goto(x, y)
    player.showturtle()

    players.append(player)

def check_collision():
    global score

    for player in players:
        if turtle.distance(player) < 15:
            x = randint(-100, 100)
            y = randint(-100, 100)
            player.goto(x, y)
            score += 1

def f():
    global direction

    def move():
        check_collision()

        if direction == 'forward':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'forward':
        direction = 'forward'
        turtle.setheading(90)
        move()

def l():
    global direction

    def move():
        check_collision()

        if direction == 'left':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'left':
        direction = 'left'
        turtle.setheading(180)
        move()

def r():
    global direction

    def move():
        check_collision()

        if direction == 'right':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'right':
        direction = 'right'
        turtle.setheading(0)
        move()

def b():
    global direction

    def move():
        check_collision()

        if direction == 'backward':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'backward':
        direction = 'backward'
        turtle.setheading(270)
        move()

def pen():
    if turtle.isdown():
        turtle.penup()
    else:
        turtle.pendown()

def quit_game(e=None):  # called from either turtle or tkinter
    window.destroy()
    print("Score:", score)
    exit()

players = []

window = tk.Tk()
# window.iconbitmap('py.ico')
window.title("Turtle Graphics")
window.geometry("600x600")
window.resizable(False, False)

canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()

tk.Button(window, width=17, text='Close', borderwidth=0, command=quit_game).pack()

screen = TurtleScreen(canvas)
turtle = RawTurtle(screen)

screen.onkey(f, 'Up')
screen.onkey(l, 'Left')
screen.onkey(r, 'Right')
screen.onkey(b, 'Down')

screen.onkey(pen, 'p')
screen.onkey(quit_game, 'Escape')
screen.onkey(spawn, 'g')

screen.listen()
screen.mainloop()

在此处输入图片说明

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

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