【问题标题】:Python Turtle Space Invaders bullets not hitting invadersPython Turtle Space Invaders 子弹没有击中入侵者
【发布时间】:2018-09-21 00:35:51
【问题描述】:

我对 turtle 和 python 很陌生,所以如果我的代码看起来很混乱,我很抱歉。

我目前正在编写海龟版的太空入侵者,但我无法弄清楚为什么我的入侵者在击中海龟时没有死亡。该代码似乎与我能找到的所有其他太空入侵者海龟程序相同。任何帮助将不胜感激。

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

【问题讨论】:

    标签: python turtle-graphics


    【解决方案1】:

    我相信您的问题在于您将子弹运动与入侵者运动交织在一起的方式。在您的while True: 循环中(它不应该存在于像turtle 这样的事件驱动的世界中)您在顶层调用bullet_movement(),然后在for 循环中并再次在嵌套的for 循环中调用。所以你看到子弹的位置和它相对于入侵者的位置不一定相同。

    我重新编写了您的代码,并且出于举例目的,在某些地方对其进行了简化。除了上述问题,我还修改了代码以使用海龟 tilt,它非常适合这种海龟面向一个方向但向另一个方向移动的游戏。而且我已经完全破坏了你的 isCollision() 函数,因为海龟已经知道如何计算它们与另一只海龟的距离。

    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()

    【讨论】:

    • 感谢您的帮助!
    • 我推荐你使用 pygame 来玩这类游戏,因为它让你的工作更轻松。我自己使用 pygame 制作了同样的游戏
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多