我正在使用Python 3使用tkinter和turtle图形制作迷宫。除了无法弄清楚如何在游戏中“销毁”“黄金”之外,大多数代码都有效。具体来说,即使我是从有关乌龟Python迷宫游戏的教程中获得此信息的,调用player.collision()
时也会说Question object has no attribute xcor
。我认为它的工作原理与在那种情况下相同,但是使用tkinter时,一切似乎都在改变。该问题发生在player.collision()
和结尾的while
循环下。这些是用于“破坏”或隐藏“金”龟的代码的两个部分。我已经(几乎)包含了整个代码,以便每个人都可以看到发生了什么。
(除了这个问题,我想创建一种使用箭头键而不是框架上的按钮移动播放器的方法,但是我不知道怎么做。)
我尝试专门命名乌龟,而不仅仅是在collision()
函数中命名“ other”。我还尝试通过分别返回Question
和tur3.xcor()
在tur3.ycor()
类下为“ getX”和“ getY”创建新方法。但是除了给我另一个错误之外,它什么也没做。就像我说的那样,当它只是一个乌龟迷宫时,此代码就可以使用,但是自从添加了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()
基本上,我希望当我移过“金”龟时,我希望它们像收集了它们一样消失。
(对于运动,我希望使用箭头键来运动而不是使用按钮,但这又是次要的事情。)
答案 0 :(得分:0)
您的直接问题是这样:
if player.collision(question):
def collision(self, other):
# ...
a = tur2.xcor() - other.xcor()
您以collision()
作为第二个参数调用question
,并且函数在调用.xcor()
时假设第二个参数是乌龟。但这不是乌龟,而是包含乌龟的 Question实例。
更大的问题是您的程序完全是对类,实例和全局变量的误解。考虑一下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中从 embedding 乌龟中获得的收益很少,这可能更干净了,留下了 standalone 乌龟程序。而且由于从未调用过您的各种setup*()
方法/函数,因此您发布的代码实际上没有任何作用。