简体   繁体   English

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

[英]How to launch a turtle program with a tkinter messagebox?

I am trying to launch a turtle game stored in one file with a message box from tkinter stored in another py file but both in the same directory. 我正在尝试启动一个存储在一个文件中的乌龟游戏,其中一个消息框来自存储在另一个py文件中的tkinter消息,但两者都在同一目录中。 However, I receive a _tkinter.TclError: image "pyimage2" doesn't exist error. 但是,我收到_tkinter.TclError: image "pyimage2" doesn't exist错误。

I have a function inside the game code that is called upon in the launcher code. 我在启动器代码中调用的游戏代码中有一个函数。 This function runs all of the code inside the main game program apart from importing modules which I have included in the function but makes no difference. 除了导入模块(我已包含在函数中)外,此函数运行主游戏程序中的所有代码,但没有区别。

Sorry for showing all but as I don't know what the problem is I thought this was best(removed as much code irrelevant to problem as I could(Assume anything unnamed that is called is deleted as irrelevant code) 很抱歉显示了所有内容,但我不知道问题出在哪里,我认为这是最好的(删除了尽可能多的与问题无关的代码(假设任何未命名的名称都被删除为无关的代码)

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

When the launcher is run a messagebox should appear saying do you wish to play and when "yes" is clicked the function to start the game is launched. 运行启动器时,将出现一个消息框,提示您是否要玩,单击“是”时,将启动启动游戏的功能。 However I receive the error: 但是我收到错误:

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

My first suggestion is that you use the turtle textinput() method (new in Python 3) instead of dragging tkinter and messagebox into the picture. 我的第一个建议是使用乌龟textinput()方法(Python 3中的新增功能),而不是将tkinter和messagebox拖动到图片中。

But if you're going to combine tkinter and turtle, you need to do it correctly. 但是,如果您要将tkinter和turtle结合使用,则需要正确进行操作。 Turtle is designed to run either standalone with its own Tk window or embedded in an existing tkinter window. Turtle被设计为既可以独立运行,也可以拥有自己的Tk窗口,也可以嵌入现有的tkinter窗口中。 You're attempting to run it standalone, embedded in a tkinter window. 您正在尝试独立运行它,将其嵌入到tkinter窗口中。 Ie instead of the standalone Turtle & Screen interface, you should be working with the embedded TurtleScreen , RawTurtle and ScrolledCanvas interface. 即,您应该使用嵌入式TurtleScreenRawTurtleScrolledCanvas界面来代替独立的TurtleScreen界面。

Besides this issue, your code is generally buggy. 除此问题外,您的代码通常是错误的。 You've lots of unfinished code. 您有许多未完成的代码。 Your use of global has to become nonlocal when you move the entire program inside the start() function. start()函数中移动整个程序时,对global使用必须变为nonlocal You're missing pieces of code necessary to run. 您缺少了运行所需的代码。 Finally, you have a while True: loop which has no business being in an event-driven environment like turtle. 最后,您有while True:循环,这与在诸如Turtle这样的事件驱动环境中没有任何关系。 I've repaced it with a timer event. 我用定时器事件来取消它。

I've reworked your code below to run as you intended. 我对您的代码进行了重新设计,使其可以按预期运行。 I've tossed incomplete and/or broken features to simplify the example. 为了简化示例,我抛弃了不完整和/或损坏的功能。 The startup code: 启动代码:

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

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

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