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