Collisions arent registering with Python Turtles

2024/11/24 10:31:07

I'm creating a simple 2D shooter following an online tutorial, and the enemy sprites (except 1, there are 5 total) are not abiding by my collision code. Everything works except the bullet object that the player controls simply passes right through the enemy sprites. Error messages I received:

Traceback (most recent call last):File "C:\Python\Python36\pygame projects\space invaders.py", line 163, in <module>bullet.hideturtle()File "C:\Python\Python36\lib\turtle.py", line 2322, in hideturtleself.pen(shown=False)File "C:\Python\Python36\lib\turtle.py", line 2459, in penself._update()File "C:\Python\Python36\lib\turtle.py", line 2660, in _updateself._update_data()File "C:\Python\Python36\lib\turtle.py", line 2646, in _update_dataself.screen._incrementudc()File "C:\Python\Python36\lib\turtle.py", line 1292, in _incrementudcraise Terminatorturtle.Terminator

If you skim through the code half way you'll find the Pythagoras theory I used for the collision math, unsure if it's correct or not:

enemies = []
number_of_enemies = 5
for i in range(number_of_enemies):enemies.append(turtle.Turtle())for enemy in enemies:enemy.color("green")enemy.shape("circle")enemy.penup()enemy.speed(0)x = random.randint(-200, 200)y = random.randint(100, 250)enemy.setposition(x, y)enemyspeed = 2def isCollision(t1, t2):distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2)+ math.pow(t1.ycor() - t2.ycor(), 2))if distance < 15:return Trueelse:return Falsewhile True:for enemy in enemies:x = enemy.xcor()x += enemyspeedenemy.setx(x)if enemy.xcor() > 280:for e in enemies:y = enemy.ycor()y -= 40enemy.sety(y)enemyspeed *= -1if enemy.xcor() < -280:for e in enemies:y = enemy.ycor()y -= 40enemy.sety(y)enemyspeed *= -1if bulletstate == "fire":y = bullet.ycor()y += bulletspeedbullet.sety(y)if isCollision(bullet, enemy):#reset the bulletbullet.hideturtle()bulletstate = "ready"bullet.setposition(0, -400)#reset the enemyx = random.randint(-200, 200)y = random.randint(100, 250)enemy.setposition(x, y)if isCollision(player, enemy):player.hideturtle()enemy.hideturtle()print ("Get To The Doctors! You're Riddled!")break

Apologies if the answer is blatantly obvious. I would be grateful for the time anyone spends explaining the error. Others have posted similar questions, but every one has examples which apply to them and I'm still at the stage where it is tricky for me to visualise others' examples. Any help would greatly be appreciated.

Answer

I think your primary issue is you're updating the bullet between every enemy update instead of once for all the the enemy updates. This creates a skew between the visual and what's really happening. Also, you don't need to define the Pythagorean formula, turtles already know it! Below is my rework of your code to address the above and rework the the coding style and efficiency a bit:

from turtle import Turtle, Screen
from random import randintNUMBER_OF_ENEMIES = 5
ENEMY_JUMP = 40BULLET_SPEED = 20
PLAYER_SPEED = 15SAFETY_DISTANCE = 15GALLERY_WIDTH, GALLERY_HEIGHT = 560, 550
GALLERY_BORDER = 80# player movement
def move_left():x = player.xcor() - PLAYER_SPEEDif x < -GALLERY_WIDTH / 2:x = -GALLERY_WIDTH / 2player.setx(x)def move_right():x = player.xcor() + PLAYER_SPEEDif x > GALLERY_WIDTH / 2:x = GALLERY_WIDTH / 2player.setx(x)def fire_bullet():global bulletstateif bulletstate == 'ready':bulletstate = 'fire'bullet.setposition(player.position())bullet.forward(BULLET_SPEED / 2)bullet.showturtle()def isCollision(t1, t2):return t1.distance(t2) < SAFETY_DISTANCEdef move():global enemy_speed, bulletstatescreen.tracer(False)for enemy in enemies:x = enemy.xcor() + enemy_speedenemy.setx(x)if x > GALLERY_WIDTH / 2:for e in enemies:y = e.ycor() - ENEMY_JUMPe.sety(y)enemy_speed *= -1elif x < -GALLERY_WIDTH / 2:for e in enemies:y = e.ycor() - ENEMY_JUMPe.sety(y)enemy_speed *= -1if isCollision(player, enemy):player.hideturtle()enemy.hideturtle()print("Get To The Doctors! You're Riddled!")screen.update()returnif isCollision(bullet, enemy):# reset the bulletbullet.hideturtle()bullet.setposition(0, -GALLERY_HEIGHT)bulletstate = 'ready'# reset the enemyenemy.hideturtle()x = randint(GALLERY_BORDER - GALLERY_WIDTH / 2, GALLERY_WIDTH / 2 - GALLERY_BORDER)y = randint(GALLERY_HEIGHT / 2 - 175, GALLERY_HEIGHT / 2 - 25)enemy.setposition(x, y)enemy.showturtle()if bulletstate == 'fire':bullet.forward(BULLET_SPEED)# check to see if the bullets has gone to the topif bullet.ycor() > GALLERY_HEIGHT / 2:bullet.hideturtle()bulletstate = 'ready'screen.tracer(True)screen.ontimer(move, 25)screen = Screen()
screen.setup(GALLERY_WIDTH + GALLERY_BORDER, GALLERY_HEIGHT + GALLERY_BORDER)
screen.bgcolor('black')player = Turtle('turtle', visible=False)
player.speed('fastest')
player.color('red')
player.penup()
player.setheading(90)
player.sety(-250)  # need to define this
player.showturtle()enemies = []enemy_speed = 1for _ in range(NUMBER_OF_ENEMIES):enemy = Turtle('circle', visible=False)enemy.speed('fastest')enemy.color('green')enemy.penup()x = randint(GALLERY_BORDER - GALLERY_WIDTH / 2, GALLERY_WIDTH / 2 - GALLERY_BORDER)y = randint(GALLERY_HEIGHT / 2 - 175, GALLERY_HEIGHT / 2 - 25)  # define these!enemy.setposition(x, y)enemy.showturtle()enemies.append(enemy)# create the player's spunk shots
bullet = Turtle('triangle', visible=False)
bullet.speed('fastest')
bullet.shapesize(0.5)
bullet.color('white')
bullet.penup()
bullet.setheading(90)# define bullet state
# ready - ready to fire
# fire - bullet is firing
bulletstate = 'ready'screen.onkey(move_left, 'Left')
screen.onkey(move_right, 'Right')
screen.onkey(fire_bullet, 'space')screen.listen()move()screen.mainloop()

I guessed at the missing pieces. See how this plays for you.

https://en.xdnf.cn/q/120547.html

Related Q&A

Function should clean data to half the size, instead it enlarges it by an order of magnitude

This has been driving me nuts all week weekend. I am trying merge data for different assets around a common timestamp. Each assets data is a value in dictionary. The data of interest is stored in lists…

is it possible to add colors to python output? [duplicate]

This question already has answers here:How do I print colored text to the terminal?(66 answers)Closed 10 years ago.so i made a small password strength tester for me, my friends and my family, as seen …

Tkinter Function attached to Button executed immediately [duplicate]

This question already has answers here:How can I pass arguments to Tkinter buttons callback command?(2 answers)Closed 8 years ago.What I need is to attach a function to a button that is called with a …

Error!!! cant concatenate the tuple to non float

stack = []closed = []currNode = problem.getStartState()stack.append(currNode)while (len(stack) != 0):node = stack.pop()if problem.isGoalState(node):print "true"closed.append(node)else:child =…

Using R to fit data from a csv with a gamma function?

Using the following data: time_stamp,secs,count 2013-04-30 23:58:55,1367366335,32 2013-04-30 23:58:56,1367366336,281 2013-04-30 23:58:57,1367366337,664 2013-04-30 23:58:58,1367366338,1255 2013-04-30…

regex multiple string match in a python list

I have a list of strings like this:["ra", "dec", "ra-error", "dec-error", "glat", "glon", "flux", "l", "b"]I ne…

python IndentationError: expected an indented block [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.This question was caused by a typo or a problem that can no longer be reproduced. While similar q…

how to tell an infinite loop to end once one number repeats twice in a row (in python 3.4)

The title says it all. I have an infinite loop of randomly generated numbers from one to six that I need to end when 6 occurs twice in a row.

Is it possible to customize the random function to avoid too much repetition of words? [duplicate]

This question already exists:Customizing the random function without using append, or list, or other container?Closed last year.Theoretically, when randomization is used, the same word may be printed …

country convert to continent

def country_to_continent(country_name):country_alpha2 = pc.country_name_to_country_alpha2(country_name)country_continent_code = pc.country_alpha2_to_continent_code(country_alpha2)country_continent_name…