【问题标题】:Start the game when SPACE is pressed (Turtle module)按下空格键开始游戏(海龟模块)
【发布时间】:2020-02-12 14:01:03
【问题描述】:

我一直在尝试使用 Turtle Graphics 编写 Pong 迷你游戏。除了开始之外,一切似乎都完美无缺。我希望主循环仅在按下空格键后才开始迭代。 这是我一直遇到问题的部分:

## Start the game
start = False

def start_game():
    startmessage.clear()   #This is a turtle i created to show the message "Press SPACE to start"
    start = True
    ball_start()    #This is a function i created to get the ball moving

wn.onkeypress(start_game, "space")

## Main loop    
while start == True:  

我已经包含了 .listen() 和 .mainloop(),所以这不是问题所在。 完整代码如下。如果我使用该代码运行程序,它就是这样做的:

  1. 它要求用户输入最大分数。黑色窗口出现,分数表也出现,但由于某种原因边框没有出现。
  2. 在 shell 中输入 max points 值时,黑屏中会出现“Press SPACE to start”消息。
  3. 只要按下空格键,该消息就会消失,不会发生其他任何事情。

以下是完整代码,以防我遗漏重要内容:

import turtle
import random
import time



## Screen setup
wn = turtle.Screen()
wn.title("Pong!")
wn.bgcolor("black")
wn.setup(width = 900, height = 700)

wn.tracer(0)


# Border
collisions = 0

border = turtle.Turtle()
border.penup()
border.color("white")
border.setposition(-400,-300)
border.pendown()
for side in range(2):
    border.forward(800)
    border.left(90) 
    border.forward(600)
    border.left(90)

border.hideturtle()


# Scores
scoreA = 0
scoreB = 0

score_marker = turtle.Turtle()
score_marker.shape("blank")
score_marker.color("yellow")
score_marker.speed(0)
score_marker.penup()
score_marker.setposition(0, 310)
score_marker.pendown()
score_marker.write("Player A : {}       Player B:  {}".format(scoreA,scoreB), align = "center", font = ("Courier", 20, "bold"))


# Select number of points
maxpoints = int(input("Enter max points: "))
print("The player who first gets to {} points wins the game!".format(maxpoints))


# Start message
startmessage = turtle.Turtle()
startmessage.speed(0)
startmessage.color("white")
startmessage.shape("blank")
startmessage.penup()
startmessage.setposition(0,75)
startmessage.pendown()
startmessage.write("Press SPACE to start", align = "center", font = ("Courier", 20, "bold"))

# End message
endmessage = turtle.Turtle()
endmessage.speed(0)
endmessage.color("green")
endmessage.shape("blank")
endmessage.penup()
endmessage.setposition(0,0)
endmessage.pendown()


## Paddles

paddleB_speed = 25
paddleA_speed = paddleB_speed

wn.listen()

# Paddle A
paddleA = turtle.Turtle()
paddleA.speed(0)
paddleA.shape("square")
paddleA.color("white")
paddleA.shapesize(3.2,0.7)

paddleA.penup()
paddleA.goto(-350,0)


# Paddle A movement
def a_up():
    y = paddleA.ycor() + paddleA_speed
    paddleA.sety(y)

def a_down():
    y = paddleA.ycor() - paddleA_speed
    paddleA.sety(y)

wn.onkeypress(a_up,"w")
wn.onkeypress(a_down,"s")


# Paddle B
paddleB = turtle.Turtle()
paddleB.speed(0)
paddleB.shape("square")
paddleB.color("white")
paddleB.shapesize(3.2,0.7)

paddleB.penup()
paddleB.goto(350,0)


# Paddle B movement
def b_up():
    y = paddleB.ycor() + paddleB_speed
    paddleB.sety(y)

def b_down():
    y = paddleB.ycor() - paddleB_speed
    paddleB.sety(y)

wn.onkeypress(b_up,"Up")
wn.onkeypress(b_down,"Down")

## Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("circle")
ball.color("white")
ball.shapesize(0.5,0.5)

ball.penup()
ball.setposition(0,0)

ballspeed = 0.3
ballspeed_increase = 0.01


# Ball starting movement
def ball_start():
    angle_ranges = list(range(30,60)) + list(range(120,150)) + list(range(210,240)) + list(range(300,330))
    angle = random.choice(angle_ranges)
    ball.setheading(angle)

ball_start()


## Exit the game
def exit_game():
    wn.bye()


## Start the game
start = False

def start_game():
    startmessage.clear()
    start = True
    ball_start()

wn.onkeypress(start_game, "space")



## Main loop

while start == True:    

    wn.update()

    ### MOVEMENT

    ## Ball movement
    ball.forward(ballspeed)


    ### COLLISIONS

    ## Paddles and border

    # Paddle A
    if paddleA.ycor() > 268:
        paddleA.sety(268)

    if paddleA.ycor() < -268:
        paddleA.sety(-268)

    # Paddle B  
    if paddleB.ycor() > 268:
        paddleB.sety(268)

    if paddleB.ycor() < -268:
        paddleB.sety(-268)


    ## Ball and paddles
    if paddleA.distance(ball) <= 10:

        collisions += 1

        #direction = ball.heading()
        #ball.setheading(180 - random.randint(0,30) -  direction)
        ball.setheading(random.randint(110,250) + 180)
        ball.forward(ballspeed + ballspeed_increase)

    if paddleB.distance(ball) <= 10:

        collisions += 1

        #direction = ball.heading()
        #ball.setheading(180 - random.randint(0,30) -  direction)
        ball.setheading(random.randint(110,250))
        ball.forward(ballspeed + ballspeed_increase)


    ## Ball and border

    # Top and bottom borders
    if ball.ycor() < - 296 or ball.ycor() > 296:

        collisions += 1

        direction = ball.heading()
        ball.setheading(360 - direction)
        ball.forward(ballspeed + ballspeed_increase)

    # Left and right borders
    if ball.xcor() < -396:  #--> Player B wins the point
        delay = 0.1
        time.sleep(1)
        collisions += 1

        ball.setposition(0,0)

        scoreB += 1
        score_marker.clear()
        score_marker.write("Player A : {}       Player B:  {}".format(scoreA,scoreB), align = "center", font = ("Courier", 20, "bold"))
        ball_start()


    if ball.xcor() > 396:  #--> Player A wins the poin
        delay = 0.1
        time.sleep(1)
        collisions += 1

        ball.setposition(0,0)

        scoreA += 1
        score_marker.clear()
        score_marker.write("Player A : {}       Player B:  {}".format(scoreA,scoreB), align = "center", font = ("Courier", 20, "bold"))
        ball_start()


    # End of the game
    if scoreA == maxpoints or scoreB == maxpoints:
        if scoreA == maxpoints:
            print("Player A wins the game!")
            endmessage.write("Player A wins the game!\nA scored {} points\nB scored {} points".format(scoreA,scoreB), align = "center", font = ("Courier", 18, "bold"))
            time.sleep(1)
            endmessage.penup()
            endmessage.setposition(0,-100)
            endmessage.pendown()
            endmessage.color("red")
            endmessage.write("Press ESC to exit game", align = "center", font = ("Courier", 14, "normal"))
            wn.onkeypress(exit_game, "Escape")

            break

        if scoreB == maxpoints:
            print("Player B wins the game!")
            endmessage.write("Player B wins the game!\nA scored {} points\nB scored {} points".format(scoreA,scoreB), align = "center", font = ("Courier", 18, "bold"))
            time.sleep(1)
            endmessage.penup()
            endmessage.setposition(0,-100)
            endmessage.pendown()
            endmessage.color("red")
            endmessage.write("Press ESC to exit game", align = "center", font = ("Courier", 14, "normal"))
            wn.onkeypress(exit_game, "Escape")

            break


wn.mainloop()

【问题讨论】:

  • 在绑定所有关键事件后,您是否尝试过将wn.listen() 移动到?
  • 刚试过,没用,谢谢!
  • 游戏还能正常运行吗?唯一的问题是它会立即加载并启动?
  • 如果我使用上面的代码,我将编辑我的主要帖子以指定我的游戏会做什么

标签: python python-3.x turtle-graphics


【解决方案1】:

这段代码看起来就像它重置了start,但它没有——它设置了一个本地start并忽略了全局 start:

start = False

def start_game():
    startmessage.clear()
    start = True
    ball_start()

您需要global 声明:

start = False

def start_game():
    global start
    startmessage.clear()
    start = True
    ball_start()

以上是必要的,但还不够。下一个问题是您使用顶级while 循环而不是计时器事件的方式。我希望这个游戏启动和运行的方式更像是:

from turtle import Screen, Turtle

running = False

def start_game():
    global running

    start_message.clear()
    running = True
    ball_start()

def ball_start():
    start_message.write("We've started the game!", align="center", font=("Courier", 20, "bold"))
    # what really ball_start() really does replaces the above...

def move_one_step():

    if running:

        screen.update()

        # ...

    screen.ontimer(move_one_step, 100)

screen = Screen()

start_message = Turtle()
start_message.hideturtle()
start_message.penup()
start_message.sety(75)
start_message.write("Press SPACE to start", align="center", font=("Courier", 20, "bold"))

screen.onkeypress(start_game, 'space')
screen.listen()

move_one_step()

screen.mainloop()

【讨论】:

  • 我一直在尝试实现您对我的代码的回答,但我有两个疑问。首先, .ontimer(function,int) 做什么以及为什么它可以工作?第二,你写代码的顺序会影响结果吗?非常感谢!
  • @Pypau,ontimer() 方法在未来某个时间(以毫秒为单位)运行另一个函数。它比 sleep() 更好,因为它不会停止其他事情并且它与其他海龟事件。至于代码顺序,你必须更具体。
【解决方案2】:

我认为这可能是您使用空格键值的方式。你放入空间而不是返回。

wn.onkeypress(start_game, "return")

【讨论】:

  • Op 希望游戏从太空开始而不是返回。 'space' 是一个有效的监听键。
  • @JDunken 是的。但是我试过了,我得到了这个错误:
  • _tkinter.TclError: 错误的事件类型或键符“return”
  • 大声笑,我才意识到。对不起,对我来说还早。 X3
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 1970-01-01
相关资源
最近更新 更多