我是 Python 新手,但我用其他语言编写过代码,主要是针对硬件。我用Python用turtle做了pong,但是有点问题。我想知道你们中是否有人可以检查一下并提供建议。我还想添加开始屏幕和结束屏幕,但我有点不确定如何添加。另外,如果您对如何改进碰撞检测有任何建议,请告诉我。
我在下面粘贴代码
import os
import math
import random
import time
#set up screen
screen = turtle.Screen()
screen.bgcolor("green")
screen.title("Pong")
# set up border
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-300,-300)
border_pen.pendown()
border_pen.pensize(3)
for side in range(4):
border_pen.fd(600)
border_pen.lt(90)
border_pen.hideturtle()
#set score to 0
score = 0
#set time to zero
time = 0
seconds = 0
#Draw score
score_pen = turtle.Turtle()
score_pen.speed(0)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 310)
scorestring = "Score %s" %score
score_pen.write(scorestring, False, align="left", font= ("Arial", 14, "normal"))
score_pen.hideturtle()
#Draw timer
time_pen = turtle.Turtle()
time_pen.speed(0)
time_pen.color("white")
time_pen.penup()
time_pen.setposition(260, 310)
timestring = "Time %s" %time
time_pen.write(timestring, False, align="left", font= ("Arial", 14, "normal"))
time_pen.hideturtle()
#create the player turtle
player = turtle.Turtle()
player.color("blue")
player.shape("square")
player.shapesize(0.5, 4)
player.penup()
player.speed(0)
player.setposition(-280,-250)#(x,y)
player.setheading(90)
playerspeed = 15
#create the AIplayer turtle
AIplayer = turtle.Turtle()
AIplayer.color("black")
AIplayer.shape("square")
AIplayer.shapesize(0.5, 4)
AIplayer.penup()
AIplayer.speed(0)
AIplayer.setposition(280,250)#(x,y)
AIplayer.setheading(90)
AIplayerspeed = 15
#create the pong
pong = turtle.Turtle()
pong.color("red")
pong.shape("circle")
pong.shapesize(0.5, 0.5)
pong.penup()
pong.speed(10)
pong.setposition(0,0)#(x,y)
pongspeed = 15
pong.goto(0, 265)
pong.dy = -5
pong.dx = 5
#Move player up and down
def move_up():
y = player.ycor()
y += playerspeed
if y > 265:
y = 260
player.sety(y)
def move_down():
y = player.ycor()
y -= playerspeed
if y < -265:
y = -260
player.sety(y)
#keyboard bindings
turtle.listen()
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
#turtle.onkey(fire_bullet, "space")
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()- t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 20:
return True
else:
return False
#main game loop
while True:
#move pong ball
pong.sety(pong.ycor() +pong.dy)
pong.setx(pong.xcor() +pong.dx)
#check for bounce and redirect it
if pong.ycor() < -300:
pong.dy *= -1
if pong.ycor() > 300:
pong.dy *= -1
if pong.xcor() < -300:
pong.dx *= -1
print("Game Over")
exit()
if pong.xcor() > 300:
pong.dx *= -1
#move AI paddle (might speed up pong movement)
y = pong.ycor()
y += AIplayerspeed
AIplayer.sety(y)
if AIplayer.ycor() > 265:
AIplayerspeed *= -1
if AIplayer.ycor() < -250:
AIplayerspeed *= -1
#collision pong and player
if isCollision(pong, player):
pong.dy *= -1
pong.dx *= -1
#Update the score
score += 10
scorestring = "Score: %s" %score
score_pen.clear()
score_pen.write(scorestring, False, align="left", font=("Arial", 14, "normal"))
#collision pong and AIplayer
if isCollision(pong, AIplayer):
pong.dy *= -1
pong.dx *= -1
#updates timer and increases ball speed
if seconds > 29:
pong.dy *= -2
pong.dx *= -2
if seconds > 59:
pong.dy *= -3
pong.dx *= -3
#displays timer but makes game laggy
# seconds += 0.1
# time = seconds
# timestring = "Time: %s" %time
# time_pen.clear()
# time_pen.write(timestring, False, align="Left", font=("Arial", 14, "normal"))
我看到的一些问题:
您已将 20 x 20 的正方形拉伸为 10 x 80:
AIplayer.shapesize(0.5, 4)
但是你的碰撞距离距离中心只有 20,所以你的球可以 越过桨的底部或顶部,实际上没有 碰撞。
你的
isCollision()
功能与海龟自己的功能大部分是多余的
.distance()
方法。
在像海龟这样的事件驱动世界中,你不应该有
while True:
因为它可能会阻止某些事件的触发。最好
将其替换为计时器事件。
一些碰撞会在应该改变 x 和 y 增量的情况下改变它们 只改变其中之一。
您应该避免在主循环中对海龟进行冗余查询以及检查被其他逻辑子句否定的条件。 IE。在主循环中尽可能少做。
下面是我按照上述思路对您的游戏进行的重做,以及许多其他风格和逻辑的更改:
from turtle import Turtle, Screen
FONT = ("Arial", 16, "normal")
def isCollision(t1, t2):
return t1.distance(t2) < 15
# set up screen
screen = Screen()
screen.bgcolor("darkgreen")
screen.title("Pong")
# set up border
border_pen = Turtle(visible=False)
border_pen.speed('fastest')
border_pen.color('white')
border_pen.pensize(3)
border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()
for _ in range(4):
border_pen.forward(600)
border_pen.left(90)
# set score to 0
score = 0
# set time to zero
seconds = 0
# Draw score
score_pen = Turtle(visible=False)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 310)
score_pen.write("Score {}".format(score), False, align="left", font=FONT)
# Draw timer
time_pen = Turtle(visible=False)
time_pen.color("white")
time_pen.penup()
time_pen.setposition(260, 310)
time_pen.write("Time {}".format(int(seconds)), False, align="left", font=FONT)
# create the player turtle
player = Turtle("square", visible=False)
player.shapesize(0.5, 3)
player.speed('fastest')
player.setheading(90)
player.color("blue")
player.penup()
player.setposition(-280, -250) # (x,y)
player.showturtle()
playerspeed = 15
# create the AIplayer turtle
AIplayer = Turtle("square", visible=False)
AIplayer.shapesize(0.5, 3)
AIplayer.speed('fastest')
AIplayer.setheading(90)
AIplayer.color("black")
AIplayer.penup()
AIplayer.setposition(280, 250) # (x,y)
AIplayer.showturtle()
AIplayerspeed = 15
# create the pong
pong = Turtle("circle", visible=False)
pong.shapesize(0.5, 0.5)
pong.speed('fast')
pong.color("red")
pong.penup()
pong.sety(265)
pong.showturtle()
pongspeed = 15
pong_dx, pong_dy = 5, -5
# Move player up and down
def move_up():
player.forward(playerspeed)
y = player.ycor()
if y > 265:
y = 260
player.sety(y)
screen.update()
def move_down():
player.backward(playerspeed)
y = player.ycor()
if y < -265:
y = -260
player.sety(y)
screen.update()
# keyboard bindings
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")
screen.listen()
# main game loop
def move():
global pong_dx, pong_dy, AIplayerspeed, seconds, score
# move pong ball
x, y = pong.position()
x += pong_dx
y += pong_dy
pong.setposition(x, y)
if isCollision(pong, player): # collision pong and player
pong_dx *= -1
# Update the score
score += 10
score_pen.undo()
score_pen.write("Score: {}".format(score), align="left", font=FONT)
elif isCollision(pong, AIplayer): # collision pong and AIplayer
pong_dx *= -1
elif y < -300 or y > 300: # check for bounce and redirect it
pong_dy *= -1
elif x > 300:
pong_dx *= -1
elif x < -300:
print("Game Over")
screen.bye()
return
# move AI paddle (might speed up pong movement)
AIplayer.forward(AIplayerspeed)
y = AIplayer.ycor()
if y < -250 or y > 250:
AIplayerspeed *= -1
# display timer
seconds += 0.05
time_pen.undo()
time_pen.write("Time: {}".format(int(seconds)), False, align="Left", font=FONT)
screen.ontimer(move, 50)
screen.update()
screen.tracer(False)
move()
screen.mainloop()
我无法理解你的“增加球速”的逻辑,所以我把它省略了。我使用了较暗的背景颜色,因为原件在我的屏幕上很难看清。
与乒乓球/球速度相关的问题可能是由于您的CPU造成的。每次屏幕更新时,球都会在(x 和 y)方向移动 5 个像素,更新速率取决于 CPU 速度。 CPU 执行的进程不是恒定的,因此 CPU 速度会波动。另外,因为我们将
screen.tracer()
设置为 False
,所以它不显示动画。 因此,由于缺乏动画和CPU速度不一致,我们看到乒乓球/球的速度增加/减少。
有关
screen.tracer()
的说明,请参阅https://youtu.be/LH8WgrUWG_I?t=123
“增加速度”解释请参考https://youtu.be/Hw1H3rG3POM?t=40
为了获得更一致的行为,您可以在循环中添加足够长的暂停,以抵消计算时间的可变性并避免绘制无用的帧。您可以使用
time
来完成此操作
import time
# Initialization
...
while True:
time.sleep(1 / 60)
# The rest of your game logic
...