Python Forum
SOLVED - Collision detection - TURTLE
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SOLVED - Collision detection - TURTLE
#1
Hello y'all!

I'm new here, so I hope my question will be clear enough!

I'm trying to create a Breakout game using Python n Turtle.
I created my lists of blocks and my main block to .clone() but
wenn the ball reaches the top of the game, where the blocks are, it only erases the first block...

I tried to solve this issue with different kind of loops, but the proble is still present...

I hope someone can help me!
THX in advence!

CODE:

# CREATING BLOCKS

block1 = turtle.Turtle()
block1.shape("square")
block1.speed(0)
block1.shapesize(2, 4) # Size of block 40x80

# BLOCKS ROW Nr.1 (10 Blocks)
blocks_row1 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(),
block1.clone(), block1.clone(), block1.clone(), block1.clone()]
# BLOCKS ROW Nr.2 (10 Blocks)
blocks_row2 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(),
block1.clone(), block1.clone(), block1.clone(), block1.clone()]
# BLOCKS ROW Nr.3 (10 Blocks)
blocks_row3 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(),
block1.clone(), block1.clone(), block1.clone(), block1.clone()]

all_blocks = [blocks_row1, blocks_row2, blocks_row3]

def starting_block_positions():
for i in range(len(blocks_row1)):
blocks_row1[i].penup()
blocks_row2[i].penup()
blocks_row3[i].penup()

blocks_row1[i].color(random.choice(colors)) # ROW Nr1
blocks_row1[i].goto((-400 + (82 * i)), 460)
blocks_row2[i].color(random.choice(colors)) # ROW Nr2
blocks_row2[i].goto((-400 + (82 * i)), 418)
blocks_row3[i].color(random.choice(colors)) # ROW Nr2
blocks_row3[i].goto((-400 + (82 * i)), 376)

# COLLISION WITH BLOCKS
elif ball.ycor() > 356: # COLLISION WITH BLOCKS
while counter_collision < len(blocks_row1):
if (abs(ball.xcor()) - abs(blocks_row3[counter_collision].xcor()) < 20) and (abs(ball.ycor()) - abs(blocks_row3[counter_collision].ycor()) < 40):
blocks_row3[counter_collision].hideturtle()
ball.setheading(270)
ball.forward(BALL_SPEED_STANDARD)
break
elif (abs(ball.xcor()) - abs(blocks_row2[counter_collision].xcor()) < 80) and (abs(ball.ycor()) - abs(blocks_row2[counter_collision].ycor()) < 40):
blocks_row2[counter_collision].hideturtle()
ball.setheading(270)
ball.forward(BALL_SPEED_STANDARD)
break
elif (abs(ball.xcor()) - abs(blocks_row1[counter_collision].xcor()) < 80) and (abs(ball.ycor()) -
abs(blocks_row1[counter_collision].ycor()) < 40):
blocks_row1[counter_collision].hideturtle()
ball.setheading(270)
ball.forward(BALL_SPEED_STANDARD)
break
counter_collision += 1
Reply
#2
There seem to be missing pieces of code:
- Import turtle ?
- Elif before if ?

Pls show indentation (python tags) because it is impossible to
see what piece of code is dependent on what.

Paul
Reply
#3
Hi Paul,

Yeah, it's only a part of the code.
Here's the complete one.

Niko

import turtle import random import time ######################################################### # VARIABLES && CONSTANTS FOR GAME # ######################################################### # Color List colors = ["red", "blue", "yellow", "pink", "green", "DeepSkyBlue", "chartreuse", "DarkMagenta"] # Constants ball_speed = 10 WINDOW_MAIN_GAME_SIZE = 1000 # Start Variables: life = 3 ########################################## # CREATING WINDOW # ########################################## wn = turtle.Screen() wn.title("BREAKOUT") wn.bgcolor("black") wn.setup(WINDOW_MAIN_GAME_SIZE, WINDOW_MAIN_GAME_SIZE) ######################################### # GAME BLOCKS... # ######################################### # CREATING BLOCKS block1 = turtle.Turtle() block1.shape("square") block1.speed(0) block1.shapesize(2, 4) # Size of block 40x80 # BLOCKS ROW Nr.1 (10 Blocks) blocks_row1 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] # BLOCKS ROW Nr.2 (10 Blocks) blocks_row2 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] # BLOCKS ROW Nr.3 (10 Blocks) blocks_row3 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] all_blocks = [blocks_row1, blocks_row2, blocks_row3] def starting_block_positions(): for i in range(len(blocks_row1)): blocks_row1[i].penup() blocks_row2[i].penup() blocks_row3[i].penup() blocks_row1[i].color(random.choice(colors)) # ROW Nr1 blocks_row1[i].goto((-400 + (82 * i)), 460) blocks_row2[i].color(random.choice(colors)) # ROW Nr2 blocks_row2[i].goto((-400 + (82 * i)), 418) blocks_row3[i].color(random.choice(colors)) # ROW Nr2 blocks_row3[i].goto((-400 + (82 * i)), 376) ######################################## # PLAYER'S PADDLE # ######################################## paddle = turtle.Turtle() paddle.shape("square") paddle.color("white") paddle.speed(0) paddle.shapesize(2, 8) # Size of paddle = 40*160 paddle_position_x = paddle.xcor() paddle_position_y = paddle.ycor() def starting_paddle_position(): paddle.penup() paddle.goto(0, -470) def move_left(): if paddle.xcor() > -480: paddle.setx(paddle.xcor() - 10) def move_right(): if paddle.xcor() < 480: paddle.setx(paddle.xcor() + 10) ######################################## # PLAYER'S BALL # ######################################## ball = turtle.Turtle() ball.shape("circle") ball.color("white") ball.fillcolor("white") ball.speed(0) ball_pos_y = 0 ball_pos_x = 0 def time_ball_speed(ball_speed): global timer if (time.perf_counter() - timer) % 15 == 0: ball_speed *= 2 return ball_speed def starting_ball_position(): ball.hideturtle() ball.penup() ball.goto(0, 0) ball.setheading(270) def moving_ball(): global life counter_collision = 0 # TOUCHING PADDLE if (abs((abs(ball.xcor()) - abs(paddle.xcor()))) < (160/life)) and (ball.ycor() <= (paddle.ycor() + 20)): if ball.heading() == 270 or -270: ball.setheading(random.randint(45, 135)) ball.forward(ball_speed) else: ball.setheading((ball.heading() * -1)) ball.forward(ball_speed) # COLLISION WITH BLOCKS elif ball.ycor() > 356: # COLLISION WITH BLOCKS while counter_collision < len(blocks_row1): if (abs(ball.xcor()) - abs(blocks_row3[counter_collision].xcor()) < 20) and (abs(ball.ycor()) - abs(blocks_row3[counter_collision].ycor()) < 40): blocks_row3[counter_collision].hideturtle() ball.setheading(270) ball.forward(ball_speed) break elif (abs(ball.xcor()) - abs(blocks_row2[counter_collision].xcor()) < 80) and (abs(ball.ycor()) - abs(blocks_row2[counter_collision].ycor()) < 40): blocks_row2[counter_collision].hideturtle() ball.setheading(270) ball.forward(ball_speed) break elif (abs(ball.xcor()) - abs(blocks_row1[counter_collision].xcor()) < 80) and (abs(ball.ycor()) - abs(blocks_row1[counter_collision].ycor()) < 40): blocks_row1[counter_collision].hideturtle() ball.setheading(270) ball.forward(ball_speed) break counter_collision += 1 # WN LEFT SIDE LIMIT elif ball.xcor() <= -490: ball.setheading(ball.heading() * 0.5) ball.forward(ball_speed) # WN RIGHT SIDE LIMIT elif ball.xcor() >= 490: ball.setheading(ball.heading() * 1.5) ball.forward(ball_speed) # BALL STILL IN WN elif (ball.ycor() >= -500) and (ball.xcor() <= 500) and (ball.xcor() >= -500) and (ball.ycor() <= 500): ball.forward(ball_speed) # LIFE -1 else: life -= 1 show_life.clear() starting_ball_position() return life ####################################### # DRAW TIMER # ####################################### timer = 0 show_timer = turtle.Turtle() show_timer.penup() show_timer.pencolor("black") show_timer.speed(0) show_timer.goto(410, -480) show_timer.color("white") def draw_timer(): global game_time_total show_timer.clear() show_timer.write(game_time_total, font=("Arial", 10, "bold")) ####################################### # DRAW LIFE # ####################################### show_life = turtle.Turtle() show_life.penup() show_life.pencolor("black") show_life.speed(0) show_life.goto(-480, -480) show_life.color("white") def draw_life(): global life show_life.write("Lives: " + str(life), font=("Arial", 20, "bold")) def life_control(): global timer if life == 3: timer = time.perf_counter() weidth_paddle = 8 / life paddle.shapesize(2, weidth_paddle) return timer elif life == 2: timer = time.perf_counter() weidth_paddle = 8 / life paddle.shapesize(2, weidth_paddle) return timer elif life == 1: timer = time.perf_counter() weidth_paddle = 8 paddle.shapesize(2, weidth_paddle / life) return timer else: wn.clear() game_over = turtle.Turtle() game_over.penup() game_over.pencolor("black") game_over.speed(0) game_over.write("GAME OVER!", font=("Arial", 50, "bold")) time.sleep(5) ####################################### # MAIN CODE... # ####################################### # Starting position for Blocks & Paddle starting_block_positions() starting_paddle_position() starting_ball_position() while 1 == 1: game_time_total = time.perf_counter() life_control() time_ball_speed(ball_speed) ball.showturtle() draw_life() #draw_timer() moving_ball() wn.onkeypress(move_left, "a") wn.onkeypress(move_left, "Left") wn.onkeypress(move_right, "Right") wn.onkeypress(move_right, "d") wn.listen()
Reply
#4
Nice piece of work so far!
I had a quick look, and i suspect the problem starts with
your counter_collision +=1.
because of your break statements, it does not get updated as planned.

Paul
Reply
#5
(Nov-17-2020, 07:35 AM)DPaul Wrote: Nice piece of work so far!
I had a quick look, and i suspect the problem starts with
your counter_collision +=1.
because of your break statements, it does not get updated as planned.

Paul

Thank you Paul!
Was a big help, I a step closer to finishing this project!

I changed my code, Breaks were def. a problem.
now it works better, but when my ball touches the first box of a row, the whole row "hides"...
And if the ball goes back to the, now, empty row, it still thinks there is something...

Do you have a clue?
I tried to box[n][i].clear() but it doesn't accept the command?!

 # COLLISION WITH BLOCKS elif ball.ycor() > 356: for n in range(len(all_blocks)): for i in range(len(blocks_row1)): if (ball.xcor() - all_blocks[n][i].xcor() < 20) and \ (ball.ycor() - all_blocks[n][i].ycor() < 40): all_blocks[n][i].hideturtle() ball.setheading(360 - ball.heading()) ball.forward(ball_speed) break
I'm REALLY thankful for any help!
THX again!
Reply
#6
I found it clever that you draw the boxes as turtle-shapes, so you can hide them when hit.
It's difficult to identify with your logic in a few minutes Smile
but probably the problem is in lines 5-6-7.
You hide the turtle, but how does the block vector know the turtle has gone?
but how do you check that the turtle has gone?
If it remains a problem, maybe another approach is helpful.
Draw the rectangles not as turtle-shapes but as simple rectangles in different colors.
Hiding is than simply redrawing the box with the background color = invisible !
Your 3 horizontal vectors could contain [1,1,1,1,1..] at the start and when one
block is hit : [1,1,0,1,1,...]
Just an idea.
Paul
Reply
#7
Hi Paul,

Thx for the help!
Found the problem, it was indeed in line 5-6-7!
I forgot to une the abs()! ^^ (stupid mistake)

BTW:
an other mistake:

# COLLISION WITH BOX CHECK def collision_block_check(): global nr_blocks_left for n in range(len(all_blocks)): for i in range(len(blocks_row1)): if (abs(ball.xcor() - all_blocks[n][i].xcor()) < 40) and \ (abs(ball.ycor() - all_blocks[n][i].ycor()) < 20) and (all_blocks[n][i].isvisible() == True): all_blocks[n][i].hideturtle() ball.setheading(ball.heading() * -1) nr_blocks_left -= 1
all_blocks[n][i].isvisible() == True
looks if the block is still visible or not. if TRUE it will hide the .turtle and if FALSE it will move as it should.



Last problem to finishing the game are the boarder restrictions -_-
(... yeah, kind of stupid, but I have a brain F*** somewhere)

# WN SIDE LIMIT def side_limit_check(): if ball.xcor() <= (BORDER_LEFT + 10) or ball.xcor() >= (BORDER_RIGHT-10): ball.setheading(ball.heading() * -1)
doesn't work as it should and not sure why Sad

Hope we/I could help someone else have the same issue with the collider ^^
Reply
#8
Hi,

I saw that left and right there is a small problem.
Just a thought, but left : -500+10 = -490 is too far left.
Try +50 or something.
(And the same to the right of course.
Paul
Reply
#9
Hi Paul,

Yeah, at the end the "bounce off" solution was kind of obvious for the sides ^^

Solution:
ball.setheading(180 + -ball.heading())

Now i'm done! Big Grin
on to the next project! Smile

Thx again for the help!
Niko
Reply
#10
Final Code for the Breakout game:

################################################################################ # # # **** **** **** ***** * * **** * * ***** # # * * * * * * * * * * * * * * # # *** *** *** ***** * * * * * * # # * * * * * * * * * * * * * * # # **** * * **** * * * * **** **** * # # # # # # MADE FROM: OuateDePhoque # # # ################################################################################ import turtle import random import time ######################################################### # VARIABLES && CONSTANTS FOR GAME # ######################################################### # Color List colors = ["red", "blue", "yellow", "pink", "green", "DeepSkyBlue", "chartreuse", "DarkMagenta"] # Constants ball_speed = 10 WINDOW_MAIN_GAME_HIGHT = 1000 WINDOW_MAIN_GAME_WIDTH = 800 BORDER_LEFT = -400 BORDER_RIGHT = 400 BORDER_TOP = 500 BORDER_BOT = -500 # Start Variables: life = 3 ########################################## # CREATING WINDOW # ########################################## wn = turtle.Screen() wn.title("BREAKOUT - By: OuateDePhoque") wn.bgcolor("black") wn.setup(WINDOW_MAIN_GAME_WIDTH, WINDOW_MAIN_GAME_HIGHT) ######################################### # GAME BLOCKS... # ######################################### # CREATING BLOCK TO CLONE block1 = turtle.Turtle() block1.shape("square") block1.speed(0) block1.shapesize(2, 4) # Size of block 40x80 # BLOCKS ROW Nr.1 (9 Blocks) blocks_row1 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] # BLOCKS ROW Nr.2 (9 Blocks) blocks_row2 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] # BLOCKS ROW Nr.3 (9 Blocks) blocks_row3 = [block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone(), block1.clone()] # 2 DIMENSIONAL LIST TO ACCESS ALL BLOCKS all_blocks = [blocks_row1, blocks_row2, blocks_row3] def starting_block_positions(): for n in range(len(all_blocks)): for i in range(len(blocks_row1)): all_blocks[n][i].penup() all_blocks[n][i].color(random.choice(colors)) all_blocks[n][i].goto(((BORDER_LEFT + 50) + (85 * i)), ((BORDER_TOP - 40) - (n * 45))) ######################################## # PLAYER'S PADDLE # ######################################## paddle = turtle.Turtle() paddle.shape("square") paddle.color("white") paddle.speed(0) paddle.shapesize(2, 8) # Size of paddle = 40*160 paddle_position_x = paddle.xcor() paddle_position_y = paddle.ycor() def starting_paddle_position(): paddle.penup() paddle.goto(0, BORDER_BOT + 30) def move_left(): if paddle.xcor() > (BORDER_LEFT + 20): paddle.setx(paddle.xcor() - 10) def move_right(): if paddle.xcor() < (BORDER_RIGHT - 20): paddle.setx(paddle.xcor() + 10) ######################################## # PLAYER'S BALL # ######################################## ball = turtle.Turtle() ball.shape("circle") ball.color("white") ball.fillcolor("white") ball.speed(0) # NOT ACTIVE def time_ball_speed(): global ball_speed if (time.perf_counter() - timer) % 15 <= 1: ball_speed *= 2 return ball_speed def starting_ball_position(): ball.hideturtle() ball.penup() ball.goto(0, 0) ball.setheading(270) # BALL IS MOVING def moving_ball(): ball.forward(ball_speed) # WN SIDE LIMIT def side_limit_check(): if ball.xcor() <= (BORDER_LEFT + 10) or ball.xcor() >= (BORDER_RIGHT - 10): ball.setheading(180 + -ball.heading()) ball.forward(ball_speed) # WN CHECK LIMIT BOT def bot_limit_check(): global life if ball.ycor() <= BORDER_BOT: life -= 1 draw_life() starting_ball_position() return life # WN CHECK LIMIT TOP def top_limit_check(): if ball.ycor() >= BORDER_TOP: ball.setheading(-ball.heading()) ball.forward(ball_speed) # COLLISION WITH BOX CHECK def collision_block_check(): global game_score for n in range(len(all_blocks)): for i in range(len(blocks_row1)): if (abs(ball.xcor() - all_blocks[n][i].xcor()) < 40) and \ (abs(ball.ycor() - all_blocks[n][i].ycor()) < 20) and (all_blocks[n][i].isvisible() == True): all_blocks[n][i].hideturtle() ball.setheading(-ball.heading()) ball.forward(ball_speed) game_score += 1 # GAME SCORE +1 (FOR WIN = 27) draw_game_score() # COLLISION WITH PADDLE CHECK def collision_paddle_check(): if (abs((abs(ball.xcor()) - abs(paddle.xcor()))) < (160 / (life+1))) and (ball.ycor() <= (paddle.ycor() + 20)): if ball.heading() == 270 or -270: ball.setheading(random.randint(45, 135)) else: ball.setheading(-ball.heading()) ball.forward(ball_speed) ########################################## # DRAW SCORE # ########################################## game_score = 0 show_game_score = turtle.Turtle() show_game_score.penup() show_game_score.pencolor("DarkRed") show_game_score.speed(0) show_game_score.goto(300, -480) show_game_score.color("DarkRed") show_game_score.write("SCORE: " + str(game_score), font=("Arial", 10, "bold")) def draw_game_score(): global game_score show_game_score.clear() show_game_score.write("SCORE: " + str(game_score), font=("Arial", 10, "bold")) def score_control(): global game_score if game_score == 27: wn.clear() game_over = turtle.Turtle() game_over.penup() game_over.pencolor("black") game_over.speed(0) game_over.goto((BORDER_LEFT + 10), 0) game_over.write("YOU WON!", font=("Arial", 50, "bold")) time.sleep(5) ########################################## # DRAW TIMER # ########################################## # timer = 0 # show_timer = turtle.Turtle() # show_timer.penup() # show_timer.pencolor("black") # show_timer.speed(0) # show_timer.goto(410, -480) # show_timer.color("white") # def draw_timer(): # global game_time_total # show_timer.clear() # show_timer.write(game_time_total, font=("Arial", 10, "bold")) ####################################### # DRAW LIFE # ####################################### show_life = turtle.Turtle() show_life.penup() show_life.pencolor("black") show_life.speed(0) show_life.goto((BORDER_LEFT + 2), (BORDER_BOT + 10)) show_life.color("DarkRed") def draw_life(): global life show_life.clear() show_life.write("Lifes: " + str(life), font=("DarkRed", 20, "bold")) def life_control(): global life if life == 3: # timer = time.perf_counter() width_paddle = 8 / life paddle.shapesize(2, width_paddle) return elif life == 2: # timer = time.perf_counter() width_paddle = 8 / life paddle.shapesize(2, width_paddle) return elif life == 1: # timer = time.perf_counter() width_paddle = 8 paddle.shapesize(2, width_paddle / life) return else: wn.clear() game_over = turtle.Turtle() game_over.penup() game_over.pencolor("black") game_over.speed(0) game_over.goto((BORDER_LEFT + 10), 0) game_over.write("GAME OVER!", font=("Arial", 50, "bold")) time.sleep(5) ####################################### # MAIN CODE... # ####################################### # Starting position for Blocks & Paddle starting_block_positions() starting_paddle_position() starting_ball_position() draw_life() while 1 == 1: # game_time_total = time.perf_counter() life_control() score_control() ball.showturtle() side_limit_check() # if & elif to speed up code if ball.ycor() > 350: top_limit_check() collision_block_check() elif ball.ycor() < -350: collision_paddle_check() bot_limit_check() # time_ball_speed() # draw_timer() moving_ball() wn.onkeypress(move_left, "a") wn.onkeypress(move_left, "Left") wn.onkeypress(move_right, "Right") wn.onkeypress(move_right, "d") wn.listen()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Turtle Detection ChinaPlaneFlyer 1 1,660 Apr-17-2023, 02:49 PM
Last Post: deanhystad
Star I was making code for collision for my character izmamonke 2 3,274 Aug-06-2021, 04:30 PM
Last Post: izmamonke
  bouncing ball with variable collision points (in time) Zhaleh 1 3,874 Jul-24-2020, 02:54 PM
Last Post: Marbelous
  Player object wont recognize collision with other objects. Jan_97 3 4,535 Dec-22-2019, 04:08 PM
Last Post: joe_momma
  wn = turtle.screen() AttributeError: module 'turtle' has no attribute 'screen' Shadower 1 8,128 Feb-06-2019, 01:25 AM
Last Post: woooee
  Help! Turtle not working, even when we click the turtle demo in IDLE nothing happens. BertyBee 3 8,685 Jan-04-2019, 02:44 AM
Last Post: SheeppOSU
  Collision function problem jtstewart95 2 4,037 May-02-2018, 11:44 PM
Last Post: scidam
  Union of dictionaries (taking max value on collision) meee 5 5,630 Jan-17-2018, 09:14 PM
Last Post: Mekire
  Need help figuring out Sprite.Group Collision code PySam 3 4,802 Sep-15-2017, 03:00 AM
Last Post: PySam

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020
This forum uses Lukasz Tkacz MyBB addons.
Forum use Krzysztof "Supryk" Supryczynski addons.