SOLVED - Collision detection - TURTLE - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: SOLVED - Collision detection - TURTLE (/thread-30979.html) |
SOLVED - Collision detection - TURTLE - OuateDePhoque - Nov-16-2020 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 RE: HELP - Collision detection - TURTLE - DPaul - Nov-16-2020 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 RE: HELP - Collision detection - TURTLE - OuateDePhoque - Nov-17-2020 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() RE: HELP - Collision detection - TURTLE - DPaul - Nov-17-2020 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 RE: HELP - Collision detection - TURTLE - OuateDePhoque - Nov-17-2020 (Nov-17-2020, 07:35 AM)DPaul Wrote: Nice piece of work so far! 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) breakI'm REALLY thankful for any help! THX again! RE: HELP - Collision detection - TURTLE - DPaul - Nov-17-2020 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 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 RE: HELP - Collision detection - TURTLE - OuateDePhoque - Nov-18-2020 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 -= 1all_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 Hope we/I could help someone else have the same issue with the collider ^^ RE: SOLVED - Collision detection - TURTLE - DPaul - Nov-18-2020 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 RE: SOLVED - Collision detection - TURTLE - OuateDePhoque - Nov-18-2020 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! on to the next project! Thx again for the help! Niko RE: SOLVED - Collision detection - TURTLE - OuateDePhoque - Nov-18-2020 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() |