Home > database >  Check if collisions detected on one background were the same collisions on the second background
Check if collisions detected on one background were the same collisions on the second background

Time:10-07

I am having difficulty comparing two collisions that take place on different backgrounds. ‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

I am attempting to make a "memory" game in Pygame. Basically, you have to hit a balloon(s) on the first background, and then hit the same balloon(s) on the second background. If you hit the same balloon(s), you get 1 point added to your score, if you don't, some text - "you lost!"(Calls a function to display text) should appear and the game should end. The number of balloons hit also gets updated after each iteration - First you hit 1 balloon(on first background), then 1(on second background), then 2(on first background), then 2(on second background) and so on, until you hit all 7 balloons. You can refer to here if you're still confused. Essentially, I am trying to compare if the balloons hit on the first background were the same on the second background. You can refer to here.

I made a list for each background, that appends the balloons that were hit each time. Then, I am comparing the 2 lists (scene_1_balloons_popped, and scene_2_balloons_popped), to see if the contents were the same. My problem is that if I am hitting different balloons on the first background, it is displaying the "you lost!" text, and I don't understand why.

The "you lost!" text can only show up on the second background if you don't hit the same balloons as the previous background. You can hit different balloons on the first background, as long as you hit the same balloons on the second.

This takes place in my game loop

        for b in range(min(len(scene_1_balloons_popped), len(scene_2_balloons_popped))):
            if scene_1_balloons_popped[b] != scene_2_balloons_popped[b]:
                number_incorrect  = 1
        if number_incorrect > 0:
            number_incorrect = 0
            you_lost()
        elif len(scene_1_balloons_popped) == len(scene_2_balloons_popped):
            score  = 1
            scene_1_balloons_popped = []
            scene_2_balloons_popped = []
 

Essentially, I am checking if the length of the two lists are the same. By the way, the collisions itself are detected correctly.

Here is my full program - pay attention to the check_collisions function and the game loop (while running:).

import pygame
import random as r
import sys


pg.init()

myfont = pg.font.SysFont('arial black', 30)

bg = pg.image.load('bg.jpg')# Background Image #
bg = pg.transform.scale(bg, (688,387))
new_bg = pg.image.load('new_bg.jpg')
new_bg = pg.transform.scale(new_bg, (688,387))

radius = 30
diameter = 2 * radius

num_balloons = 7
num_hits = 0
iterator = -1

num_balloon_list = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7]
balloon_list_index = 0
scene_1_balloons_popped = []
scene_2_balloons_popped = []
number_of_balloons_popped = 0

def create_balloons():
    global balloon_list
    global colors

    for i in range(num_balloons):
        while True:
            candidate = r.randint(0, 500)
            if all(abs(candidate-x) >= diameter for x in balloon_list):
                break
        balloon_list.append(candidate)

def draw_balloons(y):
    for i in range(num_balloons):
        screen.blit(colors[i], (balloon_list[i] , y-50))


def check_collisions(x, y):
    global hit_var, hit, score, scoretext, bg_bool
    global num_balloon_list, balloon_list_index, num_hits
    global num_balloons, new_hit_var
    global balloon_hit, game_over, number_of_balloons_popped 
    
    for i in range(num_balloons):
        gun_rect = gun.get_rect(topleft = (x,y))
        gun_mask = pg.mask.from_surface(gun)

        balloon_rect = colors[i].get_rect(topleft = (balloon_list[i], y-100))
        balloon_mask = pg.mask.from_surface(colors[i])

        offset = (balloon_rect.x - gun_rect.x), (balloon_rect.y - gun_rect.y)
        if gun_mask.overlap(balloon_mask, offset):
            hit = True
            num_balloons -= 1
            num_hits  = 1
            number_of_balloons_popped  = 1
            num_hits_needed = num_balloon_list[balloon_list_index]
            game_end = balloon_list_index == len(num_balloon_list) - 1
            if num_hits == num_hits_needed and not game_end:
                num_balloons  = num_hits
                num_hits = 0
                balloon_list_index  = 1
                bg_bool = not bg_bool
            if bg_bool == True:
                scene_1_balloons_popped.append(i)
            elif bg_bool == False:
                scene_2_balloons_popped.append(i)
                
            break

            


            
def you_lost():
    youlost = myfont.render("YOU LOST!", 1, (0,0,0))
    message = myfont.render("Improve your memory", 1, (0,0,0))
    screen.blit(youlost, (300, 300))
    screen.blit(message, (300, 500))

        
# Vars #
x = 0
y = 250
velocity = 5
score = 0
hit = False
bg_bool = False
testvar1 = True
clock = pg.time.Clock()


screen = pg.display.set_mode((688 ,387)) # Size of the screen #
caption = pg.display.set_caption("Remember") # Title of the window #

balloon_list = []
b1 = pg.image.load('balloons/1.png').convert_alpha()
b1 = pg.transform.scale(b1, (63,131))
b2 = pg.image.load('balloons/2.png').convert_alpha()
b2 = pg.transform.scale(b2, (63,131))
b3 = pg.image.load('balloons/3.png').convert_alpha()
b3 = pg.transform.scale(b3, (63,131))
b4 = pg.image.load('balloons/4.png').convert_alpha()
b4 = pg.transform.scale(b4, (63,131))
b5 = pg.image.load('balloons/5.png').convert_alpha()
b5 = pg.transform.scale(b5, (63,131))
b6 = pg.image.load('balloons/6.png').convert_alpha()
b6 = pg.transform.scale( b6, (63,131))
b7 = pg.image.load('balloons/7.png').convert_alpha()
b7 = pg.transform.scale(b7, (63,131))
colors = [b1, b2, b3, b4, b5, b6, b7]




gun = pg.image.load('game-gun.png').convert_alpha()
gun = pg.transform.scale(gun, (150,150))

create_balloons()


pg.display.flip() # Updating #

running = True # Game loop bool #

while running: # Game loop #
    clock.tick(60)
    scoretext = myfont.render("SCORE: " str(score), 1, (0,0,0))
    if bg_bool == False:
        screen.blit(bg, (0, 0))
        screen.blit(scoretext, (5, 10))

      
    elif bg_bool == True:
        screen.blit(new_bg, (0,0))
        screen.blit(scoretext, (5, 10))

            
    if hit == True:
        r.shuffle(balloon_list)
        hit = False

    if len(scene_1_balloons_popped) > 0 and len(scene_2_balloons_popped) > 0:
        for b in range(min(len(scene_1_balloons_popped), len(scene_2_balloons_popped))):
            if scene_1_balloons_popped[b] != scene_2_balloons_popped[b]:
                you_lost()
            else:
                score  = 1
                   
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            sys.exit()
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                running = False
        
            if event.key == pg.K_SPACE:
                bullets_colors()
                make_bullets() 
                check_collisions(x, y)

    draw_balloons(y)
    
    keys = pg.key.get_pressed()
    x  = keys[pg.K_RIGHT] - keys[pg.K_LEFT] * velocity
    x -= keys[pg.K_LEFT] - keys[pg.K_RIGHT] * velocity

    
        
     
    screen.blit(gun, (x, y))
    pg.display.update()
    

You can download the images here: See images on REPL


Here are some examples of what should happen:

Scenario 1: If I first hit a red balloon and it goes to the next background, I should hit the red balloon again. If I do that correctly, I get 1 point. I am now back on the first background and I have two hits. I hit the orange balloon, then the blue balloon, and the background changes. Now, on the second screen, I hit the orange balloon and then the red balloon. The "you lost" text shows up because I didn't hit the same balloons as before.

Scenario 2: I hit the blue balloon first, then the blue balloon again on the next background. I get 1 point. Then on the first background again, I hit the red balloon, then the green balloon. On the next background I hit the red balloon and the green balloon again. My score goes up 1 again. I keep on hitting the same balloons as before. My final score is 7.

Scenario 3: I hit the blue balloon, then the red balloon. The "you lost" text shows up. I play again, this time I hit the red balloon, then the red balloon again. Then I hit the red balloon and the orange balloon on the first background, and on the second background I hit the blue balloon instead of the red balloon. The game ends(The "you lost" text is shown).


How can I properly check between two lists appended with collisions to see if the same balloon(s) was hit on both backgrounds?

CodePudding user response:

How can I properly check between two lists appended with collisions to see if the same balloon(s) was hit on both backgrounds?

You are appending the balloon that is hit just before each background change to the wrong list.

Append to balloons_popped based on bg_bool before changing bg_bool.

if gun_mask.overlap(balloon_mask, offset):
    hit = True
    # Append to balloons_popped based on bg_bool...
    if bg_bool == False:                   # Add this
        scene_1_balloons_popped.append(i)  # Add this
    elif bg_bool == True:                  # Add this
        scene_2_balloons_popped.append(i)  # Add this
    # ...and then change bg_bool if reached num_hits_needed
    num_balloons -= 1
    num_hits  = 1
    number_of_balloons_popped  = 1
    num_hits_needed = num_balloon_list[balloon_list_index]
    game_end = balloon_list_index == len(num_balloon_list) - 1
    if num_hits == num_hits_needed and not game_end:
        num_balloons  = num_hits
        num_hits = 0
        balloon_list_index  = 1
        bg_bool = not bg_bool
    # if bg_bool == True:                    # Remove this
    #     scene_1_balloons_popped.append(i)  # Remove this
    # elif bg_bool == False:                 # Remove this
    #     scene_2_balloons_popped.append(i)  # Remove this

Fix score increment

First, you need a global variable to track whether the player has lost.

running = True
lost = False  # Add this

When hit, determine whether the player has lost and increment the score.

Then, show the "you lost" text based on the global variable (across frames).

if hit == True:
    r.shuffle(balloon_list)
    hit = False

    # Notice that the following block has been indented into `if hit == True`
    if len(scene_1_balloons_popped) > 0 and len(scene_2_balloons_popped) > 0:
        for b in range(min(len(scene_1_balloons_popped), len(scene_2_balloons_popped))):
            if scene_1_balloons_popped[b] != scene_2_balloons_popped[b]:
                # you_lost()  # Replace this
                lost = True   # with this
                break         #
            # else:                                                                    # Replace this
            #     score  = 1                                                           #
        if not lost and len(scene_1_balloons_popped) == len(scene_2_balloons_popped):  # with this
            score  = 1                                                                 #

if lost:        # Add this
    you_lost()  # Add this
  • Related