Получить координаты «сокровищ» (черепах) в игре Лабиринт, которая использует Python tkinter и turtle - PullRequest
0 голосов
/ 11 мая 2019

Я использую Python 3 для создания лабиринта с использованием графики tkinter и turtle.Большая часть кода работает, за исключением того, что я не могу понять, как «уничтожить» «золото» в игре.В частности, вызывая player.collision(), он говорит Question object has no attribute xcor, хотя я получил это из учебника об игре в лабиринт с черепахой на Python.Я полагал, что это будет работать так же, как и в этом контексте, но с tkinter все, похоже, изменится.Проблема возникает при player.collision() и цикле while в конце.Это две части кода, предназначенные для «уничтожения» или скрытия «золотых» черепах.Я включил (почти) весь свой код, чтобы все могли видеть, что происходит.

(В дополнение к этому вопросу я хотел бы создать способ перемещения игрока с помощью клавиш со стрелками, а не кнопокна кадре, но я не могу понять, как.)

Я пытался называть черепаху конкретно, а не просто «другой» в функции collision().Я также попытался создать новые методы в классе Question для «getX» и «getY», возвращая tur3.xcor() и tur3.ycor() соответственно.Но это не сделало ничего, кроме как дать мне еще одну ошибку.Как я уже сказал, этот код работал, когда он был просто лабиринтом черепахи, но после добавления tkinter мне пришлось изменить целый ряд вещей.

import turtle
import tkinter
import math

# Create window and canvas using tkinter.
root = tkinter.Tk()
root.title("Language Labyrinth")
cv = tkinter.Canvas(root, width=600, height=600)
cv.pack()

# Create frame where button(s) will be.
frame = tkinter.Frame(root)
frame.pack()

# Create Pen class to draw the maze.
class Pen():
    def __init__(self):
        global tur
        global screen
        tur = turtle.RawTurtle(cv)
        screen = tur.getscreen()
        tur.shape("square")
        tur.color("white")
        screen.bgcolor("black")
        tur.penup()
        tur.speed(0)

# Create setup so the maze will be drawn.
    def setup(self, level):
        global tur, walls
        for y in range(len(level)):
            for x in range(len(level[y])):
                char = level[y][x]

                screenx = -288 + (x * 24)
                screeny = 288 - (y * 24)

                if char == "X":
                    tur.goto(screenx, screeny)
                    tur.stamp()

                    walls.append((screenx, screeny))

# Create player class to have a player.
class Player():
    def __init__(self):
        global tur2
        tur2 = turtle.RawTurtle(cv)
        tur2.shape("square")
        tur2.color("blue")
        tur2.penup()
        tur2.speed(0)

# Create setup to create the player on the screen.
    def setup2(self, level):
        global tur2
        for y in range(len(level)):
            for x in range(len(level[y])):
                char = level[y][x]

                screenx = -288 + (x * 24)
                screeny = 288 - (y * 24)

                if char == "P":
                    tur2.goto(screenx, screeny)

# Define a function that will allow player to move up.
    def up(self):
        global tur2, walls
        # Calculate the spot to move to.
        movetoX = tur2.xcor()
        movetoY = tur2.ycor() + 24

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            tur2.goto(movetoX, movetoY)

# Define a function that will allow player to move down.
    def down(self):
        global tur2, walls
        # Calculate the spot to move to.
        movetoX = tur2.xcor()
        movetoY = tur2.ycor() - 24

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            tur2.goto(movetoX, movetoY)

# Define a function that will allow player to move left.
    def left(self):
        global tur2, walls
        # Calculate the spot to move to.
        movetoX = tur2.xcor() - 24
        movetoY = tur2.ycor()

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            tur2.goto(movetoX, movetoY)

# Define a function that will allow player to move right.
    def right(self):
        global tur2, walls
        # Calculate the spot to move to.
        movetoX = tur2.xcor() + 24
        movetoY = tur2.ycor()

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            tur2.goto(movetoX, movetoY)

# Check if player touches the question.
    def collision(self, other):
        global tur2
        a = tur2.xcor() - other.xcor()
        b = tur2.ycor() - other.ycor()
        distance = math.sqrt((a ** 2) + (b ** 2))

        if distance < 5:
            return True
        else:
            return False

# Create Question class to create the "gold" in the game.
class Question():
    def __init__(self, x, y):
        global tur3
        tur3 = turtle.RawTurtle(cv)
        tur3.shape("circle")
        tur3.color("gold")
        tur3.penup()
        tur3.speed(0)
        tur3.goto(x, y)

    # Define function that will remove gold when collided with.
    def destroy(self):
        global tur3
        tur3.goto(2000, 2000)
        tur3.hideturtle()

# Create a levels list.
levels = [""]

# Define first level.
level_1 = [
"XXXXXXXXXXXXXXXXXXXXXXXXX",
"XP XXXXXXX          XXXXX",
"X  XXXXXXX  XXXXXX  XXXXX",
"X       XX  XXXXXX  XXXXX",
"X       XX  XXX        XX",
"XXXXXX  XX  XXX   Q    XX",
"XXXXXX  XX  XXXXXX  XXXXX",
"XXXXXX  XX    XXXX  XXXXX",
"X  XXX Q      XXXX  XXXXX",
"X  XXX  XXXXXXXXXXXXXXXXX",
"X         XXXXXXXXXXXXXXX",
"X     Q          XXXXXXXX",
"XXXXXXXXXXXX     XXXXX  X",
"XXXXXXXXXXXXXXX  XXXXX  X",
"XXX  XXXXXXXXXX         X",
"XXX               Q     X",
"XXX         XXXXXXXXXXXXX",
"XXXXXXXXXX  XXXXXXXXXXXXX",
"XXXXXXXXXX              X",
"XX   XXXXX        Q     X",
"XX   XXXXXXXXXXXXX  XXXXX",
"XX    XXXXXXXXXXXX  XXXXX",
"XX    Q     XXXX        X",
"XXXX                    X",
"XXXXXXXXXXXXXXXXXXXXXXXXX"
]

# Add questions list.
questions = []

# Add the level(s) to the levels list.
levels.append(level_1)

# Class instances.
pen = Pen()
player = Player()

# Wall coordinate list.
walls = []

# Define function to setup the "gold" in the game.
def setup3(level):
    for y in range(len(level)):
        for x in range(len(level[y])):
            char = level[y][x]

            screenx = -288 + (x * 24)
            screeny = 288 - (y * 24)

            if char == "Q":
                questions.append(Question(screenx, screeny))

#screen.onkeypress(player.up, "Up")
#screen.onkeypress(player.down, "Down")
#screen.onkeypress(player.left, "Left")
#screen.onkeypress(player.right, "Right")

# Creation of buttons that will allow player to move. (BIND ARROWS W/O BUTTONS??)
up = tkinter.Button(frame, text="Up", command=player.up)
up.bind("<Up>", player.up)
up.pack()
down = tkinter.Button(frame, text="Down", command=player.down)
down.bind("<Down>", player.down)
down.pack()
left = tkinter.Button(frame, text="Left", command=player.left)
left.bind("<Left>", player.left)
left.pack()
right = tkinter.Button(frame, text="Right", command=player.right)
right.bind("<Right>", player.right)
right.pack()

# Define a function for the quit button.
def quitPlaying():
    root.destroy()
    root.quit()

# Creation of quit button.
quitButton = tkinter.Button(frame, text="Quit", command=quitPlaying)
quitButton.pack()

# Game loop in regards to the gold. (Needs debugging)
while True:
    # Check for player collision with a question.
    # Iterate through the questions list.
    for question in questions:
        if player.collision(question):
            # Destroy the question.
            question.destroy()
            # Remove question from questions list.
            questions.remove(question)

    # Update screen.
    screen.update()

# Call main game loop.
tkinter.mainloop()

В основном я ожидаю, что когда я перейду по«золотые» черепахи, я хочу, чтобы они исчезли, как будто я собрал их.

(А для движения я бы ожидал использовать клавиши со стрелками для перемещения вместо кнопок, но опять же, этовторостепенная вещь.)

1 Ответ

0 голосов
/ 11 мая 2019

Ваша непосредственная проблема заключается в следующем:

if player.collision(question):

def collision(self, other):
    # ...
    a = tur2.xcor() - other.xcor()

Вы вызываете collision() с question в качестве второго аргумента, и функция предполагает, что вторым аргументом является черепаха, когда она вызывает на ней .xcor(),Но это не черепаха, это экземпляр вопроса , который содержит черепаху.

Большая проблема в том, что ваша программа представляет собой полное недопонимание классов, экземплярови глобалы.Рассмотрим экземпляр pen класса Pen - вы создаете его и игнорируете его, поскольку его работа выполняется глобальным tur, созданным вами как побочный эффект!Подобные вещи повторяются в вашей программе.И очевидно, что вы не понимаете ключевое слово global, поэтому я предлагаю вашему (пере) прочитать об этом.

Я переработал вашу программу ниже, чтобы исправить многие, но не все, проблемы, которые я видел,Классы Pen, Player и Question теперь являются подклассами RawTurtle, а не содержат их.И никакие глобалы не установлены через побочный эффект.Ваше золото теперь исчезает, когда вы достигаете его, и вы можете использовать клавиши со стрелками (сначала просто нажмите на окно.)

from turtle import RawTurtle, TurtleScreen
import tkinter

# Create Pen class to draw the maze.
class Pen(RawTurtle):
    def __init__(self):
        super().__init__(screen, shape='square')
        self.speed('fastest')
        self.color('white')
        self.penup()

    # Create setup so the maze will be drawn.
    def setup(self, level):
        for y in range(len(level)):
            screen_y = 288 - (y * 24)

            for x in range(len(level[y])):
                if level[y][x] == 'X':
                    screen_x = (x * 24) - 288

                    self.goto(screen_x, screen_y)
                    self.stamp()

                    walls.append((screen_x, screen_y))

# Create player class to have a player.
class Player(RawTurtle):
    def __init__(self):
        super().__init__(screen, shape='square')
        self.speed('fastest')
        self.color('blue')
        self.penup()

    # Create setup to create the player on the screen.
    def setup(self, level):
        for y in range(len(level)):
            for x in range(len(level[y])):
                if level[y][x] == 'P':
                    screen_x = (x * 24) - 288
                    screen_y = 288 - (y * 24)

                    self.goto(screen_x, screen_y)

                    return

    # Define a function that will allow player to move up.
    def move_up(self):
        # Calculate the spot to move to.
        movetoX = self.xcor()
        movetoY = self.ycor() + 24

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            self.goto(movetoX, movetoY)

            gold_encounter()

    # Define a function that will allow player to move down.
    def move_down(self):
        # Calculate the spot to move to.
        movetoX = self.xcor()
        movetoY = self.ycor() - 24

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            self.goto(movetoX, movetoY)

            gold_encounter()

    # Define a function that will allow player to move left.
    def move_left(self):
        # Calculate the spot to move to.
        movetoX = self.xcor() - 24
        movetoY = self.ycor()

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            self.goto(movetoX, movetoY)

            gold_encounter()

    # Define a function that will allow player to move right.
    def move_right(self):
        # Calculate the spot to move to.
        movetoX = self.xcor() + 24
        movetoY = self.ycor()

        # Check if the space has a wall.
        if (movetoX, movetoY) not in walls:
            self.goto(movetoX, movetoY)

            gold_encounter()

    # Check if player touches the question.
    def collision(self, other):
        return self.distance(other) < 5

# Create Question class to create the "gold" in the game.
class Question(RawTurtle):
    def __init__(self, x, y):
        super().__init__(screen, shape='circle', visible=False)

        self.speed('fastest')
        self.color('gold')
        self.penup()
        self.goto(x, y)
        self.showturtle()

    # Define function that will remove gold when collided with.
    def destroy(self):
        self.hideturtle()

# Define function to setup the "gold" in the game.
def setup(level):
    for y in range(len(level)):
        for x in range(len(level[y])):
            char = level[y][x]

            screen_x = -288 + (x * 24)
            screen_y = 288 - (y * 24)

            if char == 'Q':
                questions.append(Question(screen_x, screen_y))

# Define a function for the quit button.
def quitPlaying():
    root.destroy()
    root.quit()

# Game loop in regards to the gold.
def gold_encounter():
    # Check for player collision with a question.
    # Iterate through the questions list.
    for question in questions:
        if player.collision(question):
            # Destroy the question.
            question.destroy()
            # Remove question from questions list.
            questions.remove(question)

# Create window and canvas using tkinter.
root = tkinter.Tk()
root.title("Language Labyrinth")

canvas = tkinter.Canvas(root, width=600, height=600)
canvas.pack()

screen = TurtleScreen(canvas)
screen.bgcolor('black')

# Create frame where button(s) will be.
frame = tkinter.Frame(root)
frame.pack()

# Add questions list.
questions = []

# Wall coordinate list.
walls = []

# Create a levels list.
levels = []

# Define first level.
level_1 = [
"XXXXXXXXXXXXXXXXXXXXXXXXX",
"XP XXXXXXX          XXXXX",
"X  XXXXXXX  XXXXXX  XXXXX",
"X       XX  XXXXXX  XXXXX",
"X       XX  XXX        XX",
"XXXXXX  XX  XXX   Q    XX",
"XXXXXX  XX  XXXXXX  XXXXX",
"XXXXXX  XX    XXXX  XXXXX",
"X  XXX Q      XXXX  XXXXX",
"X  XXX  XXXXXXXXXXXXXXXXX",
"X         XXXXXXXXXXXXXXX",
"X     Q          XXXXXXXX",
"XXXXXXXXXXXX     XXXXX  X",
"XXXXXXXXXXXXXXX  XXXXX  X",
"XXX  XXXXXXXXXX         X",
"XXX               Q     X",
"XXX         XXXXXXXXXXXXX",
"XXXXXXXXXX  XXXXXXXXXXXXX",
"XXXXXXXXXX              X",
"XX   XXXXX        Q     X",
"XX   XXXXXXXXXXXXX  XXXXX",
"XX    XXXXXXXXXXXX  XXXXX",
"XX    Q     XXXX        X",
"XXXX                    X",
"XXXXXXXXXXXXXXXXXXXXXXXXX"
]

# Add the level(s) to the levels list.
levels.append(level_1)

# Class instances.
pen = Pen()
pen.setup(level_1)
player = Player()
player.setup(level_1)
setup(level_1)

# Creation of quit button.
quitButton = tkinter.Button(frame, text='Quit', command=quitPlaying)
quitButton.pack()

screen.onkeypress(player.move_up, 'Up')
screen.onkeypress(player.move_down, 'Down')
screen.onkeypress(player.move_left, 'Left')
screen.onkeypress(player.move_right, 'Right')

screen.listen()

# Call main game loop.
screen.mainloop()

Вы, кажется, получаете очень мало от встраивания черепахи вtkinter, и это могло бы быть чище, оставив автономную программу черепахи.А поскольку ваши различные setup*() методы / функции никогда не вызывались, ваш опубликованный код ничего не делает.

...