问题描述
总的来说,我对乌龟和 python 很陌生,所以如果我的代码看起来很乱,我深表歉意.
I'm very new to turtle and python in general, so I apologize if my code seems messy.
我目前正在编写太空入侵者的海龟版本,但我不明白为什么我的入侵者在击中海龟时没有死亡.该代码似乎与我能找到的所有其他太空入侵者海龟程序相同.任何帮助将不胜感激.
I'm currently coding a turtle version of space invaders and I can't figure out why my invaders aren't dying when they hit the turtles. The code seems to be the same as all the other space invader turtle programs I can find. Any help would be greatly appreciated.
import turtle
import random
import math
#### Player ####
player1 = turtle.Turtle()
player1.shape("arrow")
player1.color("white")
player1.speed(0)
player1.penup()
player1.setheading(90)
player1.setposition(0, -175)
player1.speed(4)
def move_right():
x = player1.xcor()
x += playerspeed
if x > 210:
x = 210
player1.setx(x)
def move_left():
x = player1.xcor()
x -= playerspeed
if x < -210:
x = -210
player1.setx(x)
bulletlist = []
def fire():
if len(bulletlist) < 5:
bulletlist.append(Bullet())
#### Window ####
win = turtle.Screen()
win.bgcolor("black")
win.tracer(2)
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-225, -225)
border_pen.pensize(3)
border_pen.pendown()
for side in range(4):
border_pen.fd(450)
border_pen.lt(90)
border_pen.hideturtle()
### Invader ###
class Invader(turtle.Turtle):
def __init__(self, xcor, ycor):
turtle.Turtle.__init__(self)
self.color("red")
self.shape("turtle")
self.penup()
self.speed(0)
self.setposition(xcor, ycor)
self.setheading(270)
self.speed(1)
self.hit = 0
### Bullet ###
bulletstate = 1
class Bullet(turtle.Turtle):
def __init__(self):
turtle.Turtle.__init__(self)
self.color("yellow")
self.shape("arrow")
self.shapesize(.5, 1)
self.penup()
self.speed(0)
self.setheading(90)
self.hideturtle()
self.bulletspeed = 20
fire()
def bullet_movement():
global firedb
firedb = bulletlist[-1]
firedb.speed(0)
ybul = firedb.ycor()
ybul += 10
firedb.sety(ybul)
if ybul > 195:
firedb.hideturtle()
def fire_bullet():
print("fire!")
firedb = bulletlist[-1]
firedb.hideturtle()
x = player1.xcor()
y = player1.ycor() + 20
firedb.setpos(x, y)
firedb.showturtle()
if firedb.ycor() > 200:
firedb.hideturtle()
bulletlist.remove(firedb)
def bulletmake():
bulletfire = Bullet()
def bulletmechanics():
fire()
fire_bullet()
win.listen()
win.onkey(move_left, "Left")
win.onkey(move_right, "Right")
win.onkey(fire_bullet, "space")
enemies = []
xx = -175
xxxx = -175
for invader in range(19):
if invader <= 9:
enemies.append(Invader(xx, 200))
xx += 30
if invader >= 9:
enemies.append(Invader(xxxx, 175))
xxxx += 30
playerspeed = 7
enemyspeed = 8
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 15:
return True
else:
return False
dead = []
while True:
global firedb
firedb = bulletlist[-1]
fire()
bullet_movement()
for Invader in enemies:
bullet_movement()
# if Invader.distance(firedb.xcor()+200, firedb.ycor()+200) < 1:
if isCollision(bulletlist[-1], Invader) == True:
print("AAAAAAAAGH")
isCollision(firedb, Invader)
Invader.hit += 1
if Invader.hit == 1:
Invader.color("orange")
if Invader.hit == 2:
Invader.color("yellow")
if Invader.hit == 3:
Invader.speed(0)
Invader.setpos(1000, 1000)
dead.append(Invader)
Invader.hideturtle()
for invader in enemies:
bullet_movement()
xpos = invader.xcor()
invader.speed(0)
xpos += enemyspeed
invader.setx(xpos)
if invader.xcor() > 200:
for invader in enemies:
ypos = invader.ycor()
ypos -= 40
invader.sety(ypos)
enemyspeed *= -1
if invader.xcor() < -200:
for invader in enemies:
y = invader.ycor()
y -= 40
invader.sety(y)
enemyspeed *= -1
推荐答案
我相信您的问题是您将子弹运动与入侵者运动交织在一起的方式.在你的 while True:
循环中(它不应该存在于像乌龟这样的事件驱动的世界中)你在顶层调用 bullet_movement()
,然后在 for
循环,然后在嵌套的 for
循环中再次循环.所以你看到子弹的位置和它相对于入侵者的位置不一定相同.
I belive your problem is the way you interlace bullet movements with invader movements. In your while True:
loop (which shouldn't exist in an event-driven world like turtle) you call bullet_movement()
at the top level, then in a for
loop and again within a nested for
loop. So where you see the bullet and where it is relative to invaders aren't necessarily the same.
我已经重新编写了您的代码,并且出于示例目的,在某些地方对其进行了简化.除了上述问题,我还修改了代码以使用海龟 tilt,这非常适合海龟面向一个方向但向另一个方向移动的游戏.我已经完全抛弃了你的 isCollision()
函数,因为海龟已经知道如何计算它们与另一只海龟的距离.
I've reworked your code, and for example purposes, simplified it in places. Along with the above issues, I've also modified the code to use turtle tilt which is perfect for this sort of game where the turtles face in one direction but move in another. And I've completely trashed your isCollision()
function as turtles already know how to compute their distance from another turtle.
from turtle import Screen, Turtle
class Invader(Turtle):
def __init__(self, xcor, ycor):
super().__init__(shape="turtle")
self.color("red")
self.penup()
self.setposition(xcor, ycor)
self.tilt(-90)
self.speed('slow')
self.hit = 0
class Bullet(Turtle):
def __init__(self):
super().__init__(shape="arrow", visible=False)
self.shapesize(.5, 1)
self.color("yellow")
self.penup()
self.setheading(90)
self.speed('fastest')
self.bulletspeed = 20
def move_right():
if player.xcor() + playerspeed < 210:
player.forward(playerspeed)
def move_left():
if player.xcor() - playerspeed > -210:
player.backward(playerspeed)
def bullet_movement():
firedb.forward(10)
if firedb.ycor() > 195:
firedb.hideturtle()
def fire_bullet():
if not firedb.isvisible():
x, y = player.position()
firedb.setposition(x, y + 20)
firedb.showturtle()
def isCollision(t1, t2):
return t1.distance(t2) < 20
def move():
global enemyspeed
if firedb.isvisible():
bullet_movement()
for invader in enemies:
if firedb.isvisible() and isCollision(firedb, invader):
invader.hit += 1
if invader.hit == 1:
invader.color("orange")
elif invader.hit == 2:
invader.color("yellow")
elif invader.hit == 3:
invader.hideturtle()
enemies.remove(invader)
firedb.hideturtle() # only one hit per bullet!
invader.forward(enemyspeed)
if invader.xcor() < -200 or invader.xcor() > 200:
for invader in enemies:
y = invader.ycor() - 40
invader.sety(y)
enemyspeed *= -1
win.update()
win.ontimer(move, 50)
#### Player ####
player = Turtle("arrow")
player.color("white")
player.penup()
player.tilt(90)
player.sety(-175)
player.speed('fast')
#### Window ####
win = Screen()
win.bgcolor("black")
win.tracer(False)
border_pen = Turtle(visible=False)
border_pen.speed('fastest')
border_pen.color("white")
border_pen.pensize(3)
border_pen.penup()
border_pen.setposition(-225, -225)
border_pen.pendown()
for _ in range(4):
border_pen.forward(450)
border_pen.left(90)
### Bullet ###
firedb = Bullet()
enemies = []
xx = -175
xxxx = -190
for invader_count in range(19):
if invader_count < 9:
enemies.append(Invader(xx, 200))
xx += 30
else:
enemies.append(Invader(xxxx, 175))
xxxx += 30
playerspeed = 7
enemyspeed = 2
win.onkey(move_left, "Left")
win.onkey(move_right, "Right")
win.onkey(fire_bullet, "space")
win.listen()
move()
win.mainloop()
最后,要注意经常被误解的 Python global
和 turtle tracer()
.
Finally, be careful with Python global
and turtle tracer()
which are routinely misunderstood.
这篇关于Python Turtle Space Invaders 子弹没有击中入侵者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!