How to not lose all of the hearts when you touch the box

Question:

import pygame         
from sys import exit
import random

pygame.init()

WIDTH, HEIGHT = 800, 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My game!")
fps = pygame.time.Clock()
active = True

test_font = pygame.font.Font("letters.ttf", 50)
text_surface = test_font.render("Samad ge mig ett A!", False, (64,64,64))
text_rect = text_surface.get_rect(center = (400,50))

#game over
game_over = pygame.image.load("game_over.png").convert()

#Heart
heart = pygame.image.load("heart.png").convert_alpha()
heart = pygame.transform.rotozoom(heart,0,0.6)

#Box
box = pygame.image.load("box.png").convert_alpha()
box = pygame.transform.rotozoom(box,0,0.3)
box_rect = box.get_rect(midbottom = (300,305))

#Background och Ground
background = pygame.image.load("sky.png").convert()
ground = pygame.image.load("ground.png").convert()

#player PNG 
player = pygame.image.load("player.png").convert_alpha()
player = pygame.transform.rotozoom(player,0,2.5)
player_rect = player.get_rect(midbottom = (400,325))

#pickaxe PNG
pickaxe = pygame.image.load("pickaxe.png").convert_alpha()
pickaxe = pygame.transform.rotozoom(pickaxe,0,3.5)
pickaxe_rect = pickaxe.get_rect(center = (400,325))

#Gravity
player_gravity = 0
pickaxe_gravity = 0

hearts = 4

while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit()
      exit()
  
    if active:
      if event.type == pygame.MOUSEBUTTONDOWN:
        if player_rect.collidepoint(event.pos) and player_rect.bottom >= 325: 
          player_gravity = -20
          pickaxe_gravity = -20
      
      if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT or event.key == pygame.K_a:
          player_rect.x -= 20
          pickaxe_rect.x -= 20

        if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
          player_rect.x += 20
          pickaxe_rect.x += 20
          
        if (event.key == pygame.K_SPACE or event.key == pygame.K_w or event.key == pygame.K_UP) and player_rect.bottom >= 325:
          player_gravity = -20
          pickaxe_gravity = -20
    else:
      if event.type == pygame.KEYDOWN and event.key == pygame.K_x:
        box_x = random.randint(10, 800)
        box_rect = box.get_rect(midbottom = (box_x,305))
        hearts = 4
        active = True
        
  if active:
    if player_rect.colliderect(box_rect): hearts-=1

    screen.blit(background,(0,0))
    screen.blit(ground,(0,300))
    
    if hearts == 0:
      active = False
    elif hearts == 1:
      screen.blit(heart, (35,35))
    elif hearts == 2:
      screen.blit(heart, (35,35))
      screen.blit(heart, (65,35))
    elif hearts == 3:
      screen.blit(heart, (35,35))
      screen.blit(heart, (65,35))
      screen.blit(heart, (95,35))
    else:
       screen.blit(heart, (35,35))
       screen.blit(heart, (65,35))
       screen.blit(heart, (95,35))
       screen.blit(heart, (125,35))
      
    screen.blit(box, box_rect)
    screen.blit(pickaxe, pickaxe_rect)
    screen.blit(player,player_rect)
    screen.blit(text_surface, text_rect)
    
    player_gravity += 1
    pickaxe_gravity += 1
    player_rect.y += player_gravity
    pickaxe_rect.y += pickaxe_gravity
    if pickaxe_rect.bottom >= 325: pickaxe_rect.bottom = 325
    if player_rect.bottom >= 325: player_rect.bottom = 325

    if player_rect.x <= -10 and pickaxe_rect.x <= -10:
      player_rect.x = -10
      pickaxe_rect.x = player_rect.x - 70

  else:
    screen.blit(game_over, (0,0))

  pygame.display.update()
  fps.tick(60)

Here is my whole code. I want it to whenever you touch the box you will use one heart only. But if i touch it now I loose all of the hearts imidiatelly. Pls help. I thinks it works correctly but whever I touch the box I lose 1 heart then another again and another without having time to get out of the box. Please help.

I tried to fix it but I was not able. I know what the problem is but im not able to fix it.

Asked By: Klajdi Fasho MUGR

||

Answers:

Add a state that indicates whether the player collided with the box in the previous frame and don’t decrease the number of hearts more than once if the player collides with the box in consecutive frames:

collided_in_the_last_frame = False
while True:
    # [...]

    if active:

        collides = player_rect.colliderect(box_rect)
        if collides and not collided_in_the_last_frame: 
            hearts -= 1
        collided_in_the_last_frame = collides

        # [...]
Answered By: Rabbid76
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.