Python Turtle Space Invaders bullets not hitting invaders

拥有回忆 提交于 2019-12-11 04:06:29

问题


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

回答1:


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.

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

Finally, be careful with Python global and turtle tracer() which are routinely misunderstood.



来源:https://stackoverflow.com/questions/52435052/python-turtle-space-invaders-bullets-not-hitting-invaders

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!