Как запустить программу Turtle с окном сообщений tkinter? - PullRequest
0 голосов
/ 23 марта 2019

Я пытаюсь запустить игру-черепаху, которая хранится в одном файле, с окном сообщения из tkinter, которое хранится в другом файле py, но оба находятся в одном каталоге. Тем не менее, я получаю _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 Ответ

1 голос
/ 24 марта 2019

Мое первое предложение заключается в том, что вы используете метод textinput() черепахи (новый в Python 3) вместо перетаскивания tkinter и messagebox на изображение.

Но если вы собираетесь объединить tkinter и turtle,вам нужно сделать это правильно.Turtle предназначен для работы либо автономно со своим собственным окном Tk, либо внедренным в существующее окно tkinter.Вы пытаетесь запустить его автономно, встроенный в окно tkinter.Т.е. вместо автономного интерфейса Turtle & Screen вы должны работать со встроенным интерфейсом TurtleScreen, RawTurtle и ScrolledCanvas.

Кроме этой проблемы, ваш код, как правило, содержит ошибки.У вас много незаконченного кода.Использование global должно стать nonlocal при перемещении всей программы внутри функции start().Вам не хватает фрагментов кода, необходимых для запуска.Наконец, у вас есть цикл while True:, который не имеет никакого отношения к среде, управляемой событиями, такой как turtle.Я изменил его с помощью события таймера.

Я переработал ваш код ниже, чтобы он работал так, как вы хотели.Я бросил незавершенные и / или сломанные функции, чтобы упростить пример.Код запуска:

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