如何检测乌龟 python 中两个 objects 之间的碰撞?
How to detect collision between two objects in turtle python?
所以我正在 python 乌龟中为 chrome 的恐龙游戏制作一个克隆。我已经对仙人掌进行了随机化(这是非常骇人听闻的,是的,如果有什么比我的 aaproach 更好,请帮助!)并且如标题所述,跳跃是 working.But,我无法正确检测碰撞。我试了这么多:
import turtle
import time
import random
print("dino game in turtle")
wn = turtle.Screen()
wn.bgcolor("white")
wn.setup(width=650, height=400)
wn.tracer(0)
delay = 0.1
#scoring system
score = 0
w = 1
h = 1
#dino
dino = turtle.Turtle()
dino.shape("square")
dino.shapesize(w, h)
dino.color("black")
dino.penup()
dino.goto(-200, -50)
#ground
g = turtle.Turtle()
g.penup()
g.goto(0, -60)
g.pendown()
g.lt(180)
g.fd(500)
g.rt(180)
g.fd(1000)
g.hideturtle()
#cactus
#y = random.randint(2, 4)
cactus = turtle.Turtle()
cactus.penup()
cactus.shape("square")
cactus.color("green")
cactus.shapesize(3, 0.5)
cactus.goto(-50, -30)
cactus2 = turtle.Turtle()
cactus2.penup()
cactus2.shape("square")
cactus2.color("green")
cactus2.shapesize(3, 0.5)
cactus2.goto(600, -30)
cactus3 = turtle.Turtle()
cactus3.penup()
cactus3.shape("square")
cactus3.color("green")
cactus3.shapesize(3, 0.5)
cactus3.goto(600, -30)
#score_pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Score: 0 High Score: 0", align="center", font=("Courier", 24, "normal"))
max_height = 150
def steady():
y = dino.ycor()
if y == -50:
return True
else:
return False
def jump():
y = dino.ycor()
if y != -50:
return True
else:
return False
def jumping():
y = dino.ycor()
y += 200
dino.sety(y)
def cactus_move():
x = cactus.xcor()
x -= 20
cactus.setx(x)
def cactus_move2():
x = cactus2.xcor()
x -= 20
cactus2.setx(x)
def cactus_move3():
x = cactus3.xcor()
x -= 20
cactus3.setx(x)
x = dino.xcor()
y = dino.ycor()
def check_rect_collision(dino, x, y, w, h):
if p.x >= x and p.x <= x+w and p.y >= y and p.y <= y+h:
# collision between p and rectangle
return True
return False
wn.listen()
wn.onkeypress(jumping, "space")
while True:
score += 1
check_rect_collision()
#print(score)
#pen.clear()
#pen.clear()
#pen.write("Score: {} ".format(score), align="center", font=("Courier", 24, "normal"))
x = random.randint(200, 300)
xm = random.randint(300, 500)
xms = random.randint(500, 550)
cactus_move()
cactus_move2()
cactus_move3()
y = dino.ycor()
if steady() == True and dino.distance(cactus) < 25:
print("Hello")
break
if steady() == True and dino.distance(cactus2) < 25:
print("Hello")
break
if steady() == True and dino.distance(cactus3) < 25:
print("Hello")
break
if jump() == True and dino.ycor() <= cactus.ycor():
print("Ycor")
break
if jump() == True and dino.ycor() <= cactus2.ycor():
print("Ycor")
break
if jump() == True and dino.ycor() <= cactus3.ycor():
print("Ycor")
break
if steady() == False:
y -= 25
dino.sety(y)
if y >= max_height:
y -= 200
dino.sety(y)
if cactus.xcor() < -400:
cactus.goto(x, -30)
if cactus2.xcor() < -400:
cactus2.goto(xm, -30)
if cactus3.xcor() < -400:
cactus3.goto(xms, -30)
time.sleep(delay)
wn.update()
wn.mainloop()
通常,我会说使用 turtle.distance()
函数。但是由于你的两只乌龟形状不同,你需要一个自定义碰撞函数来考虑两者的形状。我在下面重新编写了您的代码,包括并修复它以使用 turtle timer 事件而不是 while True
和 sleep()
以及其他更改:
from turtle import Screen, Turtle
from random import randint
WIDTH, HEIGHT = 650, 400
MAX_HEIGHT = 180
BASELINE = -60
NUMBER_CACTI = 3
FONT = ('Courier', 24, 'normal')
CURSOR_SIZE = 20
CACTUS_WIDTH, CACTUS_HEIGHT = 10, 60
def steady():
return dino.ycor() == BASELINE + CURSOR_SIZE/2
def jump():
y = dino.ycor()
if steady():
dino.sety(y + 7 * CURSOR_SIZE)
elif y < MAX_HEIGHT:
dino.sety(y + 2 * CURSOR_SIZE)
def cactus_move(cactus):
cactus.setx(cactus.xcor() - CACTUS_WIDTH)
def check_rect_collision(a, b):
return abs(a.xcor() - b.xcor()) < CURSOR_SIZE/2 + CACTUS_WIDTH/2 and abs(a.ycor() - b.ycor()) < CURSOR_SIZE/2 + CACTUS_HEIGHT/2
def place_cactus(cactus):
cactus.setx(randint(WIDTH//2, WIDTH))
while True:
for other in cacti:
if other is cactus:
continue
if other.distance(cactus) < 5 * CACTUS_WIDTH:
cactus.setx(randint(0, WIDTH//2))
break # for
else: # no break
break # while
# scoring system
score = 0
def run():
global score
score += 1
pen.clear()
pen.write("Score: {} ".format(score), align='center', font=FONT)
for cactus in cacti:
cactus_move(cactus)
if check_rect_collision(dino, cactus):
screen.onkeypress(None, 'space') # Game Over
screen.tracer(True)
return
if cactus.xcor() < -WIDTH/2:
place_cactus(cactus)
if not steady():
dino.sety(dino.ycor() - CURSOR_SIZE)
screen.update()
screen.ontimer(run, 50) # repeat in 50 milliseconds
screen = Screen()
screen.title("Dino game in turtle")
screen.bgcolor('white')
screen.setup(width=WIDTH, height=HEIGHT)
screen.tracer(False)
# ground
ground = Turtle()
ground.hideturtle()
ground.penup()
ground.sety(BASELINE)
ground.pendown()
ground.forward(WIDTH/2)
ground.backward(WIDTH)
# dino
dino = Turtle()
dino.shape('square')
dino.penup()
dino.goto(-WIDTH/3, BASELINE + CURSOR_SIZE/2)
# cacti
cacti = []
for _ in range(NUMBER_CACTI):
cactus = Turtle()
cactus.shape('square')
cactus.shapesize(CACTUS_HEIGHT / CURSOR_SIZE, CACTUS_WIDTH / CURSOR_SIZE)
cactus.color('green')
cactus.penup()
cactus.sety(BASELINE + CACTUS_HEIGHT/2)
place_cactus(cactus)
cacti.append(cactus)
# score pen
pen = Turtle()
pen.hideturtle()
pen.penup()
pen.sety(175)
pen.write("Score: 0 High Score: 0", align='center', font=FONT)
screen.onkeypress(jump, 'space')
screen.listen()
run()
screen.mainloop()
我相信它现在基本上可以玩了,但您可能想调整一些常量来品尝。
你可以像游戏引擎一样,在物体上放置形状并应用碰撞检测算法,有些算法非常简单,例如球体 vs 球体,这就是它的工作原理。
在你想要检测碰撞的物体上画一个圆圈,这可以通过制作一个 class CircleCollider 来完成,例如让它成为你的乌龟的 属性。这个对撞机有一个ID,半径和位置,和乌龟一样
制作另一个class来管理碰撞器和碰撞,将碰撞保存在数组或列表中
每次迭代(我想你的游戏代码都在循环中),应用球体对球体算法来检测碰撞。您必须在所有对象之间执行此操作。 (不要忘记更新对撞机位置)
Sphere vs sphere algorithm (between 2 spheres): 只计算两个碰撞器之间的距离,它必须小于半径,你可以用公式 d=sqrt((x1-x2)^2 + (y1-y2) ^2), 如果不是,则发生碰撞。
我知道这个解决方案可能有点长,但值得,你还必须考虑圆形是否适合你的角色,你也可以使用盒子和胶囊,但算法有点多复杂的。最后,如果您只有 2 种类型的对象(角色和障碍物)而不是使用 id,您可以使用标签(角色或障碍物)代替每个对象的不同 ID。
所以我正在 python 乌龟中为 chrome 的恐龙游戏制作一个克隆。我已经对仙人掌进行了随机化(这是非常骇人听闻的,是的,如果有什么比我的 aaproach 更好,请帮助!)并且如标题所述,跳跃是 working.But,我无法正确检测碰撞。我试了这么多:
import turtle
import time
import random
print("dino game in turtle")
wn = turtle.Screen()
wn.bgcolor("white")
wn.setup(width=650, height=400)
wn.tracer(0)
delay = 0.1
#scoring system
score = 0
w = 1
h = 1
#dino
dino = turtle.Turtle()
dino.shape("square")
dino.shapesize(w, h)
dino.color("black")
dino.penup()
dino.goto(-200, -50)
#ground
g = turtle.Turtle()
g.penup()
g.goto(0, -60)
g.pendown()
g.lt(180)
g.fd(500)
g.rt(180)
g.fd(1000)
g.hideturtle()
#cactus
#y = random.randint(2, 4)
cactus = turtle.Turtle()
cactus.penup()
cactus.shape("square")
cactus.color("green")
cactus.shapesize(3, 0.5)
cactus.goto(-50, -30)
cactus2 = turtle.Turtle()
cactus2.penup()
cactus2.shape("square")
cactus2.color("green")
cactus2.shapesize(3, 0.5)
cactus2.goto(600, -30)
cactus3 = turtle.Turtle()
cactus3.penup()
cactus3.shape("square")
cactus3.color("green")
cactus3.shapesize(3, 0.5)
cactus3.goto(600, -30)
#score_pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Score: 0 High Score: 0", align="center", font=("Courier", 24, "normal"))
max_height = 150
def steady():
y = dino.ycor()
if y == -50:
return True
else:
return False
def jump():
y = dino.ycor()
if y != -50:
return True
else:
return False
def jumping():
y = dino.ycor()
y += 200
dino.sety(y)
def cactus_move():
x = cactus.xcor()
x -= 20
cactus.setx(x)
def cactus_move2():
x = cactus2.xcor()
x -= 20
cactus2.setx(x)
def cactus_move3():
x = cactus3.xcor()
x -= 20
cactus3.setx(x)
x = dino.xcor()
y = dino.ycor()
def check_rect_collision(dino, x, y, w, h):
if p.x >= x and p.x <= x+w and p.y >= y and p.y <= y+h:
# collision between p and rectangle
return True
return False
wn.listen()
wn.onkeypress(jumping, "space")
while True:
score += 1
check_rect_collision()
#print(score)
#pen.clear()
#pen.clear()
#pen.write("Score: {} ".format(score), align="center", font=("Courier", 24, "normal"))
x = random.randint(200, 300)
xm = random.randint(300, 500)
xms = random.randint(500, 550)
cactus_move()
cactus_move2()
cactus_move3()
y = dino.ycor()
if steady() == True and dino.distance(cactus) < 25:
print("Hello")
break
if steady() == True and dino.distance(cactus2) < 25:
print("Hello")
break
if steady() == True and dino.distance(cactus3) < 25:
print("Hello")
break
if jump() == True and dino.ycor() <= cactus.ycor():
print("Ycor")
break
if jump() == True and dino.ycor() <= cactus2.ycor():
print("Ycor")
break
if jump() == True and dino.ycor() <= cactus3.ycor():
print("Ycor")
break
if steady() == False:
y -= 25
dino.sety(y)
if y >= max_height:
y -= 200
dino.sety(y)
if cactus.xcor() < -400:
cactus.goto(x, -30)
if cactus2.xcor() < -400:
cactus2.goto(xm, -30)
if cactus3.xcor() < -400:
cactus3.goto(xms, -30)
time.sleep(delay)
wn.update()
wn.mainloop()
通常,我会说使用 turtle.distance()
函数。但是由于你的两只乌龟形状不同,你需要一个自定义碰撞函数来考虑两者的形状。我在下面重新编写了您的代码,包括并修复它以使用 turtle timer 事件而不是 while True
和 sleep()
以及其他更改:
from turtle import Screen, Turtle
from random import randint
WIDTH, HEIGHT = 650, 400
MAX_HEIGHT = 180
BASELINE = -60
NUMBER_CACTI = 3
FONT = ('Courier', 24, 'normal')
CURSOR_SIZE = 20
CACTUS_WIDTH, CACTUS_HEIGHT = 10, 60
def steady():
return dino.ycor() == BASELINE + CURSOR_SIZE/2
def jump():
y = dino.ycor()
if steady():
dino.sety(y + 7 * CURSOR_SIZE)
elif y < MAX_HEIGHT:
dino.sety(y + 2 * CURSOR_SIZE)
def cactus_move(cactus):
cactus.setx(cactus.xcor() - CACTUS_WIDTH)
def check_rect_collision(a, b):
return abs(a.xcor() - b.xcor()) < CURSOR_SIZE/2 + CACTUS_WIDTH/2 and abs(a.ycor() - b.ycor()) < CURSOR_SIZE/2 + CACTUS_HEIGHT/2
def place_cactus(cactus):
cactus.setx(randint(WIDTH//2, WIDTH))
while True:
for other in cacti:
if other is cactus:
continue
if other.distance(cactus) < 5 * CACTUS_WIDTH:
cactus.setx(randint(0, WIDTH//2))
break # for
else: # no break
break # while
# scoring system
score = 0
def run():
global score
score += 1
pen.clear()
pen.write("Score: {} ".format(score), align='center', font=FONT)
for cactus in cacti:
cactus_move(cactus)
if check_rect_collision(dino, cactus):
screen.onkeypress(None, 'space') # Game Over
screen.tracer(True)
return
if cactus.xcor() < -WIDTH/2:
place_cactus(cactus)
if not steady():
dino.sety(dino.ycor() - CURSOR_SIZE)
screen.update()
screen.ontimer(run, 50) # repeat in 50 milliseconds
screen = Screen()
screen.title("Dino game in turtle")
screen.bgcolor('white')
screen.setup(width=WIDTH, height=HEIGHT)
screen.tracer(False)
# ground
ground = Turtle()
ground.hideturtle()
ground.penup()
ground.sety(BASELINE)
ground.pendown()
ground.forward(WIDTH/2)
ground.backward(WIDTH)
# dino
dino = Turtle()
dino.shape('square')
dino.penup()
dino.goto(-WIDTH/3, BASELINE + CURSOR_SIZE/2)
# cacti
cacti = []
for _ in range(NUMBER_CACTI):
cactus = Turtle()
cactus.shape('square')
cactus.shapesize(CACTUS_HEIGHT / CURSOR_SIZE, CACTUS_WIDTH / CURSOR_SIZE)
cactus.color('green')
cactus.penup()
cactus.sety(BASELINE + CACTUS_HEIGHT/2)
place_cactus(cactus)
cacti.append(cactus)
# score pen
pen = Turtle()
pen.hideturtle()
pen.penup()
pen.sety(175)
pen.write("Score: 0 High Score: 0", align='center', font=FONT)
screen.onkeypress(jump, 'space')
screen.listen()
run()
screen.mainloop()
我相信它现在基本上可以玩了,但您可能想调整一些常量来品尝。
你可以像游戏引擎一样,在物体上放置形状并应用碰撞检测算法,有些算法非常简单,例如球体 vs 球体,这就是它的工作原理。
在你想要检测碰撞的物体上画一个圆圈,这可以通过制作一个 class CircleCollider 来完成,例如让它成为你的乌龟的 属性。这个对撞机有一个ID,半径和位置,和乌龟一样
制作另一个class来管理碰撞器和碰撞,将碰撞保存在数组或列表中
每次迭代(我想你的游戏代码都在循环中),应用球体对球体算法来检测碰撞。您必须在所有对象之间执行此操作。 (不要忘记更新对撞机位置)
Sphere vs sphere algorithm (between 2 spheres): 只计算两个碰撞器之间的距离,它必须小于半径,你可以用公式 d=sqrt((x1-x2)^2 + (y1-y2) ^2), 如果不是,则发生碰撞。
我知道这个解决方案可能有点长,但值得,你还必须考虑圆形是否适合你的角色,你也可以使用盒子和胶囊,但算法有点多复杂的。最后,如果您只有 2 种类型的对象(角色和障碍物)而不是使用 id,您可以使用标签(角色或障碍物)代替每个对象的不同 ID。