Search code examples
pythonloopspygamebulletcurrent-time

Code does not print colision moment as expected


Just to clarify the context:

I am not sure what error is happening. My code was built to display a window using pygame containing an image of a player and a enemy image, in addition to a red surface that automatically slides down the screen. Note: This code contains parts of codes in http://programarcadegames.com/.

Now my question:

But I wanted to add an impression of the time exactly when the enemy is hit by the bullet launched by the player. The question arises from the fact that its use print (currentTime) the moment it is printed is different from the moment when the enemy is hit. But if you use print(time.time () - startTime) the moment is marked as expected. To check for this divergence I used a stopwatch and starting from the beginning of the code execution on my terminal until approximately 7 seconds (when I hit and eliminate the enemy from the screen) I got two different results that confirm the existence of this question.

Case 1 (using print (currentTime)): start the code execution and simultaneously start the timer somewhere outside (your smartphone for example). Hit the enemy and eliminate him from the screen in approximately 7 seconds and also simultaneously stop the external timer. Result: terminal receives the impression by marking something like 0.5645756721496582.

Case 2 (used print(time.time () - startTime)): start the code execution and simultaneously start the timer somewhere outside (your smartphone for example). Hit the enemy and eliminate him from the screen in approximately 7 seconds and also simultaneously stop the external timer. Result: terminal receives the impression marking something like 7.940780162811279.

I want to know what is the cause of divergence when I use print(time.time () - startTime) and when I use print(currentTime).

As I am not a python expert, I ended up not using "good practices" on how to write the relationship logic between the player, bullet and the enemy and their respective renderings on the screen. But I believe that this does not interfere with the legitimacy of my question in itself.

Here my code that works:

import pygame
import random
from pynput.keyboard import Listener, Key
import time

#store start timestamp
startTime = time.time()

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

#create window

size = (700, 500)
screen = pygame.display.set_mode(size) 


#class 

currentTime = time.time() - startTime



class Block(pygame.sprite.Sprite):
    """ This class represents the block. """
    def __init__(self, color):
        # Call the parent class (Sprite) constructor
        super().__init__()

        self.image = pygame.Surface([20, 15])
        self.image.fill(color)
        self.image.set_colorkey(BLACK) 
        self.rect = self.image.get_rect()

class Diego(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.image.load("player.png").convert()
          self.rect = self.image.get_rect()
class Apple(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.image.load("spr11.png").convert()
          self.rect = self.image.get_rect()
          self.image.set_colorkey(BLACK) 
class Bala(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.Surface([4, 10])
          self.image.fill(BLACK)
          self.rect = self.image.get_rect()
      def update(self):
         self.rect.y += -3

# Setup
pygame.init()
block_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])

bullet_list = pygame.sprite.Group() 

#def block and include and track in the class Block

#for i in range(50):
#    # This represents a block
#    block = Block(BLUE)

#    # Set a random location for the block
#    block.rect.x = random.randrange(screen_width)
#    block.rect.y = random.randrange(350)

#    # Add the block to the list of objects
#    block_list.add(block)
#    all_sprites_list.add(block)

apple = pygame.image.load("spr11.png").convert()
block = Apple()
player_image = pygame.image.load("player.png").convert()
player = Diego()


block.rect.x = 200
block.rect.y = 200

block_list.add(block)
all_sprites_list.add(block)

# Loop until the user clicks the close button.
done = False

# Used to manage how fast the screen updates
clock = pygame.time.Clock()

# Hide the mouse cursor
x_speed = 0
y_speed = 0

rect_x = 50
rect_y = 50
rect_change_x = 1
rect_change_y = 1
x = 0
y = 0
#player.rect.y = rect_x
#player.rect.y = rect_y
score = 0
# -------- Main Program Loop -----------
while not done:
    x += x_speed
    y += y_speed

    # --- Event Processing
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
#bullet  
        elif event.type == pygame.MOUSEBUTTONDOWN:
            # Fire a bullet if the user clicks the mouse button
            bullet = Bala()
            # Set the bullet so it is where the player is
            bullet.rect.x = x
            bullet.rect.y = y
            # Add the bullet to the lists
            all_sprites_list.add(bullet)
            bullet_list.add(bullet)



            # User pressed down on a key
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x_speed = -3
            elif event.key == pygame.K_RIGHT:
                x_speed = 3
            elif event.key == pygame.K_UP:
                y_speed = -3
            elif event.key == pygame.K_DOWN:
                y_speed = 3 

        elif event.type == pygame.KEYUP:
            # If it is an arrow key, reset vector back to zero
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                x_speed = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                y_speed = 0


    for bullet in bullet_list:
        block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
        for block in block_hit_list:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
            score += 1
            print(score)
            print("BLUE")
            print(time.time() - startTime)
        if bullet.rect.y < -10:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
    all_sprites_list.update()
    # --- Game Logic


    # --- Drawing Code



    # First, clear the screen to WHITE. Don't put other drawing commands
    # above this, or they will be erased with this command.
    screen.fill(WHITE)

#    x += x_speed
#    y += y_speed
    all_sprites_list.draw(screen)
    player_image.set_colorkey(BLACK)
    apple.set_colorkey(BLACK)
    screen.blit(player_image, [x, y])   
    pygame.draw.rect(screen, RED, [rect_x, rect_y, 10, 10]) 
    rect_x += rect_change_x
    rect_y += rect_change_y
    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()

    # Limit frames per second
    clock.tick(60)

# Close the window and quit.
pygame.quit()

Here my code that doesn't work as expected

import pygame
import random
from pynput.keyboard import Listener, Key
import time

#store start timestamp
startTime = time.time()

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

#create window

size = (700, 500)
screen = pygame.display.set_mode(size) 


#class 

currentTime = time.time() - startTime



class Block(pygame.sprite.Sprite):
    """ This class represents the block. """
    def __init__(self, color):
        # Call the parent class (Sprite) constructor
        super().__init__()

        self.image = pygame.Surface([20, 15])
        self.image.fill(color)
        self.image.set_colorkey(BLACK) 
        self.rect = self.image.get_rect()

class Diego(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.image.load("player.png").convert()
          self.rect = self.image.get_rect()
class Apple(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.image.load("spr11.png").convert()
          self.rect = self.image.get_rect()
          self.image.set_colorkey(BLACK) 
class Bala(pygame.sprite.Sprite):
      def __init__(self):
          super().__init__()
          self.image = pygame.Surface([4, 10])
          self.image.fill(BLACK)
          self.rect = self.image.get_rect()
      def update(self):
         self.rect.y += -3

# Setup
pygame.init()
block_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])

bullet_list = pygame.sprite.Group() 

#def block and include and track in the class Block

#for i in range(50):
#    # This represents a block
#    block = Block(BLUE)

#    # Set a random location for the block
#    block.rect.x = random.randrange(screen_width)
#    block.rect.y = random.randrange(350)

#    # Add the block to the list of objects
#    block_list.add(block)
#    all_sprites_list.add(block)

apple = pygame.image.load("spr11.png").convert()
block = Apple()
player_image = pygame.image.load("player.png").convert()
player = Diego()


block.rect.x = 200
block.rect.y = 200

block_list.add(block)
all_sprites_list.add(block)

# Loop until the user clicks the close button.
done = False

# Used to manage how fast the screen updates
clock = pygame.time.Clock()

# Hide the mouse cursor
x_speed = 0
y_speed = 0

rect_x = 50
rect_y = 50
rect_change_x = 1
rect_change_y = 1
x = 0
y = 0
#player.rect.y = rect_x
#player.rect.y = rect_y
score = 0
# -------- Main Program Loop -----------
while not done:
    x += x_speed
    y += y_speed

    # --- Event Processing
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
#bullet  
        elif event.type == pygame.MOUSEBUTTONDOWN:
            # Fire a bullet if the user clicks the mouse button
            bullet = Bala()
            # Set the bullet so it is where the player is
            bullet.rect.x = x
            bullet.rect.y = y
            # Add the bullet to the lists
            all_sprites_list.add(bullet)
            bullet_list.add(bullet)



            # User pressed down on a key
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x_speed = -3
            elif event.key == pygame.K_RIGHT:
                x_speed = 3
            elif event.key == pygame.K_UP:
                y_speed = -3
            elif event.key == pygame.K_DOWN:
                y_speed = 3 

        elif event.type == pygame.KEYUP:
            # If it is an arrow key, reset vector back to zero
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                x_speed = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                y_speed = 0


    for bullet in bullet_list:
        block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
        for block in block_hit_list:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
            score += 1
            print(score)
            print("BLUE")
            print(currentTime)
        if bullet.rect.y < -10:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
    all_sprites_list.update()
    # --- Game Logic


    # --- Drawing Code



    # First, clear the screen to WHITE. Don't put other drawing commands
    # above this, or they will be erased with this command.
    screen.fill(WHITE)

#    x += x_speed
#    y += y_speed
    all_sprites_list.draw(screen)
    player_image.set_colorkey(BLACK)
    apple.set_colorkey(BLACK)
    screen.blit(player_image, [x, y])   
    pygame.draw.rect(screen, RED, [rect_x, rect_y, 10, 10]) 
    rect_x += rect_change_x
    rect_y += rect_change_y
    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()

    # Limit frames per second
    clock.tick(60)

# Close the window and quit.
pygame.quit()

Solution

  • as far as I can tell you're never updating your currenttime variable. so simply add

     currentTime = time.time() - startTime
    

    inside your mainloop and it should work.