如何使用tkinter消息框启动乌龟程序?

时间:2019-03-23 19:27:52

标签: python tkinter turtle-graphics python-3.7

我正在尝试启动一个存储在一个文件中的乌龟游戏,并带有一个消息框,消息框来自存储在另一个py文件中的tkinter,但两者都在同一目录中。但是,我收到  _tkinter.TclError: image "pyimage2" doesn't exist错误。

我在游戏代码中有一个函数,该函数在启动器代码中被调用。除了导入模块(我已包含在该函数中)外,此函数运行主游戏程序中的所有代码,但没有区别。

很抱歉显示了所有内容,但我不知道问题是什么,我认为这是最好的(删除了尽可能多的与问题无关的代码(假设任何未命名的名称都被删除为不相关的代码)

def start():
    import turtle
    import math
    import time

    counter = 0

    wn = turtle.Screen()
    wn.setup(800, 600)

    wn.bgcolor("black")
    wn.title("Trooper shooter")
    wn.bgpic("background1.png")
    wn.update()

    turtle.register_shape("invader.gif")
    turtle.register_shape("plane.gif")
    turtle.register_shape("troop.gif")
    turtle.register_shape("player1.gif")
    turtle.register_shape("player2.gif")
    turtle.register_shape("bomb.gif")
    turtle.register_shape("boom.gif")

    #player
    soldier = turtle.Turtle()
    soldier.color("blue")
    soldier.shape("player1.gif")
    soldier.penup()
    soldier.speed(0)
    soldier.setposition(0,-200)
    soldier.setheading(90)
    soldierspd = 20

    #Bomb

    Numbombs = 2
    bombs = []
    for i in range(Numbombs):
        bombs.append(turtle.Turtle())
    for bomb in bombs:
        bomb.shape("bomb.gif")
        bomb.penup()
        bomb.speed(0)
        bomb.ht()
        x = -1700

        y = 2700
        bomb.setposition(x+30,y)
        bomb.setheading(270)
    bombspeed = 10

    #Plane
    plane = turtle.Turtle()
    plane.color("red")
    plane.shape("plane.gif")
    plane.penup()
    plane.speed(0)
    plane.setposition(-270,200)
    plane.setheading(360)
    planespd = 20

    #Plane2
    plane2 = turtle.Turtle()
    plane2.ht()
    plane2.color("red")
    plane2.shape("plane.gif")
    plane2.penup()
    plane2.speed(0)
    plane2.setposition(-270,200)
    plane2.setheading(360)
    planespd2 = 20

    #ParaTroopers
    num = 5
    Troopers = []

    for i in range(num):
        Troopers.append(turtle.Turtle())

    for Troop in Troopers:
        Troop.color("Purple")
        Troop.shape("troop.gif")
        Troop.penup()
        Troop.speed(0)
        Troop.ht()
        x = -170
        y = 270
        Troop.setposition(x+30,y)
        Troop.setheading(270)
    Troopspeed = 3

    #Bullet
    bullet = turtle.Turtle()
    bullet.color("yellow")
    bullet.shape("triangle")
    bullet.penup()
    bullet.speed(0)
    bullet.setheading(90)
    bullet.shapesize(0.5, 0.5)
    bullet.ht()

    bulletspeed = 30

    #Define bullet state
    #ready = ready to fire
    #fire = bullet is firing
    state = "ready"

    #Move player left
    def Left():
        x = soldier.xcor()
        x -= soldierspd
        soldier.setx(x)
        soldier.shape("player1.gif")
        if x < -280:
            x = -280
            soldier.setx(x)


    #Move player right
    def Right():
        x = soldier.xcor()
        x += soldierspd
        soldier.setx(x)
        soldier.shape("player2.gif")
        if x > 280:
            x = 280
            soldier.setx(x)
    #Shoot bullet

    def Shoot():
        #Declare bullet state as global
        global state
        if state == "ready":
            state = "fire"
            #Move bullet above player
            x = soldier.xcor()
            y = soldier.ycor()
            bullet.setposition(x, y +10)
            bullet.showturtle()

    #HitBoxes
    def checkCollision(A,B):
        distance = math.sqrt(math.pow(A.xcor() - B.xcor(), 2) +
        math.pow(A.ycor() - B.ycor(), 2))
        if distance < 30:
            return True
        else:
            return False

    #Move plane
    def MovePlane():

        x = plane.xcor()
        x += planespd
        plane.speed(1)
        plane.setx(x)
        if plane.xcor() > 280:
            plane.ht()

    turtle.listen()
    turtle.onkey(Left,"Left")
    turtle.onkey(Right,"Right")
    turtle.onkey(Shoot,"space")


    while True:
        #Move Plane
        MovePlane()

        #Move count
        incCount()



        #Show Paratrooper
        x = -200
        for Troop in Troopers:
            if plane.xcor() > x+50:
                x += 80
                Troop.setx(x)
                Troop.showturtle()
                y = Troop.ycor()
                y -= Troopspeed
                Troop.sety(y)
                if y < -280:
                    Troop.ht()

            if checkCollision(bullet, Troop):
                # Reset bullet
                bullet.ht()
                state = "ready"
                bullet.setposition(0, -400)
                Troop.shape("boom.gif")
                # Update Scoreboard
                score += 10
                scorestring = "Score: %s" % score
                score_pen.clear()
                score_pen.write(scorestring, False, align="left", font=("Arial", 14, "normal"))
                time.sleep(0.1)
                Troop.setposition(1000, 1000)

        #update background
        if counter == 30:
            wn.bgpic("background2.png")
            wn.update()
        if counter == 60:
            wn.bgpic("background3.png")
            wn.update()
        if counter == 90:
            wn.bgpic("background4.png")
            wn.update()
        if counter == 120:
            wn.bgpic("background5.png")
            wn.update()
        if counter == 150:
            wn.bgpic("background6.png")
            wn.update()


    wn.mainloop()

from tkinter import *
from tkinter import messagebox
import TrooperShooter



root = Tk()
launch = messagebox.askquestion("launcher","Play game?")
if launch == "yes":
    TrooperShooter.start()

运行启动器时,将出现一个消息框,提示您是否要播放  当单击“是”时,启动游戏启动功能。但是我收到错误:

Traceback (most recent call last):
  File "C:/Users/marco/Desktop/Trooper shooter/launcher.py", line 10, in <module>
    TrooperShooter.start()
  File "C:\Users\marco\Desktop\Trooper shooter\TrooperShooter.py", line 18, in start
    wn.bgpic("background1.png")
  File "C:\Program Files (x86)\Python37-32\lib\turtle.py", line 1482, in bgpic
    self._setbgpic(self._bgpic, self._bgpics[picname])
  File "C:\Program Files (x86)\Python37-32\lib\turtle.py", line 738, in _setbgpic
    self.cv.itemconfig(item, image=image)
  File "<string>", line 1, in itemconfig
  File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 2578, in itemconfigure
    return self._configure(('itemconfigure', tagOrId), cnf, kw)
  File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1476, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage2" doesn't exist

Process finished with exit code 1

1 个答案:

答案 0 :(得分:1)

我的第一个建议是您使用乌龟textinput()方法(Python 3中的新增功能),而不是将tkinter和messagebox拖动到图片中。

但是,如果您要结合使用tkinter和turtle,则需要正确进行。 Turtle被设计为使用自己的Tk窗口运行独立或在现有的tkinter窗口中运行嵌入式。您正在尝试独立运行它,将其嵌入到tkinter窗口中。即而不是独立的TurtleScreen接口,您应该使用嵌入式TurtleScreenRawTurtleScrolledCanvas接口。

除此问题外,您的代码通常是错误的。您有许多未完成的代码。在global函数内移动整个程序时,对nonlocal的使用必须变为start()。您缺少了运行所需的代码。最后,您有一个while True:循环,在像乌龟这样的事件驱动环境中没有任何生意。我用计时器事件来代替它。

我对下面的代码进行了重新整理,使其可以按预期运行。为了简化示例,我抛弃了不完整和/或损坏的功能。启动代码:

from tkinter import Tk
from tkinter import messagebox
import TrooperShooter

root = Tk()

launch = messagebox.askquestion("launcher", "Play game?")

if launch == "yes":

    TrooperShooter.start(root)

TrooperShooter.py

import tkinter as tk
from turtle import TurtleScreen, ScrolledCanvas, RawTurtle

def start(root):

    # Move player left
    def Left():
        soldier.shape("player1.gif")

        x = soldier.xcor() - soldierspd
        soldier.setx(x)

        if x < -280:
            soldier.setx(-280)

    # Move player right
    def Right():
        soldier.shape("player2.gif")

        x = soldier.xcor() + soldierspd
        soldier.setx(x)

        if x > 280:
            soldier.setx(280)

    # Shoot bullet
    def Shoot():
        # Declare bullet state as global
        nonlocal state

        if state == "ready":
            state = "fire"
            # Move bullet above player
            x, y = soldier.position()
            bullet.setposition(x, y + 10)
            bullet.showturtle()

    # HitBoxes
    def checkCollision(a, b):
        return a.distance(b) < 30

    # Move plane
    def MovePlane():
        x = plane.xcor() + plane_speed
        plane.setx(x)

        if plane.xcor() > 280:
            plane.hideturtle()

    def action():
        nonlocal state, score

        # Move Plane
        MovePlane()

        # Show Paratrooper
        x = -200
        for troop in troopers:
            if plane.xcor() > x + 50:
                x += 80
                troop.setx(x)
                troop.showturtle()
                y = troop.ycor() - troop_speed
                troop.sety(y)
                if y < -280:
                    troop.hideturtle()

            if checkCollision(bullet, troop):
                # Reset bullet
                bullet.hideturtle()
                state = "ready"
                bullet.setposition(0, -400)
                troop.shape("boom.gif")
                # Update Scoreboard
                score += 10
                scorestring = "Score: %s" % score
                score_pen.clear()
                score_pen.write(scorestring, align="left", font=("Arial", 14, "normal"))
                troop.setposition(1000, 1000)

        if state == "fire":
            y = bullet.ycor()

            if y > 300:
                state = 'ready'
                bullet.hideturtle()
            else:
                bullet.sety(y+ bullet_speed)

        screen.ontimer(action, 100)

    score = 0

    # Define bullet state
    # ready = ready to fire
    # fire = bullet is firing
    state = "ready"

    root.geometry("800x600")
    root.title("Trooper shooter")

    canvas = ScrolledCanvas(root)
    canvas.pack(fill=tk.BOTH, expand=tk.YES)

    screen = TurtleScreen(canvas)

    screen.bgcolor("black")
    screen.bgpic("background1.png")

    screen.register_shape("invader.gif")
    screen.register_shape("plane.gif")
    screen.register_shape("troop.gif")
    screen.register_shape("player1.gif")
    screen.register_shape("player2.gif")
    screen.register_shape("boom.gif")

    # Player
    soldier = RawTurtle(screen)
    soldier.color("blue")
    soldier.shape("player1.gif")
    soldier.penup()
    soldier.speed('fastest')
    soldier.setposition(0, -200)
    soldier.setheading(90)
    soldierspd = 20

    # Score
    score_pen = RawTurtle(screen)
    score_pen.speed('fastest')
    score_pen.hideturtle()

    # Plane
    plane = RawTurtle(screen)
    plane.color("red")
    plane.shape("plane.gif")
    plane.penup()
    plane.speed('fastest')
    plane.setposition(-270, 200)
    plane.setheading(360)
    plane_speed = 20

    # ParaTroopers
    number_troops = 5
    troopers = []

    for _ in range(number_troops):
        troop = RawTurtle(screen)
        troop.color("Purple")
        troop.shape("troop.gif")
        troop.penup()
        troop.speed('fastest')
        troop.hideturtle()
        x, y = -170, 270
        troop.setposition(x + 30, y)
        troop.setheading(270)

        troopers.append(troop)

    troop_speed = 3

    # Bullet
    bullet = RawTurtle(screen)
    bullet.color("yellow")
    bullet.shape("triangle")
    bullet.penup()
    bullet.speed('fastest')
    bullet.setheading(90)
    bullet.shapesize(0.5)
    bullet.hideturtle()

    bullet_speed = 30

    screen.onkey(Left, "Left")
    screen.onkey(Right, "Right")
    screen.onkey(Shoot, "space")
    screen.listen()

    action()

    screen.mainloop()