0
votes

I'm new to programming and this is the first real game I've made/making. Basically the game has you as a player shooting "bullets" at the enemy. With some objects moving around in the middle to try and stop all your bullets getting through.

I felt as though the speed at which the player could fire the bullet was too fast. So I did some research and found something that would help. The time.sleep(sec). When I used it though the whole game would stop and wait for the time delay to be over.

I used the time.sleep(sec) in main program loop when the player presses down the mouse button to fire a bullet. This in turn affects the whole game by making all of it to delay for 5 seconds.

So how would I have it wait without affecting the whole game?

Here is my game code:

import pygame
import random
import time

enemy_speed = 5
running = 1




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

# --- Classes
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("enemy.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update(self):
        self.rect.x += 7
        if self.rect.x >= 610:
            self.rect.x = random.randrange(50,610)

class Hand(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("hand.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update(self):
        self.rect.y = 300
        self.rect.x += 5
        if self.rect.x >= 610:
            self.rect.x = random.randrange(50,610)

class Hand2(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("hand2.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update (self):
        self.rect.y = 100
        self.rect.x -= 5
        if self.rect.x <= 90:
            self.rect.x = random.randrange(50,610)
class Hand3(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("hand3.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update (self):
        self.rect.y = 200
        self.rect.x += 3
        if self.rect.x >= 610:
            self.rect.x = random.randrange(50,610)

class Hand4(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("hand4.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update (self):
        self.rect.y = 50
        self.rect.x += 3
        if self.rect.x >= 610:
            self.rect.x = random.randrange(50,610)


class Hand5(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("hand5.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update (self):
        self.rect.y = 350
        self.rect.x -= 3
        if self.rect.x >= 610:
            self.rect.x = random.randrange(50,610)   




class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("player.png").convert()
        self.rect = self.image.get_rect()
        self.image.set_colorkey(WHITE)
    def update(self):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                self.rect.x -= 4
            if event.key == pygame.K_RIGHT:
                self.rect.x += 4
            if self.rect.x <= 50:
                self.rect.x = 60
            if self.rect.x >= 610:
                self.rect.x = 600

class Pellet(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([4,10])
        self.image.fill(RED)
        self.rect = self.image.get_rect()
    def update(self):
        speed_p = -3
        self.rect.y -= speed_p



class Bullet(pygame.sprite.Sprite):
    """ This class represents the bullet . """
    def __init__(self):
        # Call the parent class (Sprite) constructor
        super().__init__()

        self.image = pygame.Surface([4, 10])
        self.image.fill(BLUE)

        self.rect = self.image.get_rect()

    def update(self):
        """ Move the bullet. """
        speed_b = 3
        self.rect.y -= speed_b


# --- Create the window

# Initialize Pygame
pygame.init()

# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Cannon Battle")



all_sprites_list = pygame.sprite.Group()
enemy_list = pygame.sprite.Group()
player_list = pygame.sprite.Group()
hand_list = pygame.sprite.Group()
hand2_list = pygame.sprite.Group()
hand3_list = pygame.sprite.Group()
hand4_list = pygame.sprite.Group()
hand5_list = pygame.sprite.Group()


bullet_list = pygame.sprite.Group()
pellet_list = pygame.sprite.Group()
enemy = Enemy()
enemy_list.add(enemy)
all_sprites_list.add(enemy_list)

hand = Hand()
hand_list.add(hand)
all_sprites_list.add(hand_list)

hand2 = Hand2()
hand2_list.add(hand2)
all_sprites_list.add(hand2)

hand3 = Hand3()
hand3_list.add(hand3)
all_sprites_list.add(hand3)

hand4 = Hand4()
hand4_list.add(hand4)
all_sprites_list.add(hand4)

hand5 = Hand5()
hand5_list.add(hand5)
all_sprites_list.add(hand5)









player = Player()
player_list.add(player)
all_sprites_list.add(player_list)





done = False

clock = pygame.time.Clock()


player.rect.y = 370
behind = pygame.image.load("grassland.png").convert()

# -------- Main Program Loop 
while not done:
    screen.blit(behind, [0,0])
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.MOUSEBUTTONDOWN:
            bullet = Bullet()
            bullet.rect.x = player.rect.x
            bullet.rect.y = player.rect.y
            all_sprites_list.add(bullet)
            bullet_list.add(bullet)
            time.sleep(5)
        elif event.type == pygame.MOUSEBUTTONUP:
            pellet = Pellet()
            pellet.rect.x = enemy.rect.x
            pellet.rect.y = enemy.rect.y
            all_sprites_list.add(pellet)
            pellet_list.add(pellet)






    # --- Game logic

    # Call the update() method on all the sprites
    all_sprites_list.update()

    for pellet in pellet_list:
        player_hit_list = pygame.sprite.spritecollide(pellet,player_list,True)
        if pellet.rect.y >= 510:
            pellet_list.remove(pellet)
            all_sprites_list.remove(pellet)
        for player in player_hit_list:
            done = True
            print("You Lost!")
            print("But thanks for playing!")
            print("Made by Oankar Studios")

    for bullet in bullet_list:
        enemy_hit_list = pygame.sprite.spritecollide(bullet,enemy_list,True)
        if bullet.rect.y <= -10:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        if bullet.rect.x == hand.rect.x:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        if bullet.rect.x == hand2.rect.x:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        if bullet.rect.x == hand3.rect.x:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        if bullet.rect.x == hand4.rect.x:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        if bullet.rect.x == hand5.rect.x:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
        for enemy in enemy_hit_list:
            done = True
            print("You Won!")
            print("Made by Oankar Studios")




    # Clear the screen


    # Draw all the spites
    all_sprites_list.draw(screen)



    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()

    # --- Limit to 20 frames per second
    clock.tick(60)




pygame.quit()

Here is where I use the time.sleep(sec), it is in the main program loop:

elif event.type == pygame.MOUSEBUTTONDOWN:
    bullet = Bullet()
    bullet.rect.x = player.rect.x
    bullet.rect.y = player.rect.y
    all_sprites_list.add(bullet)
    bullet_list.add(bullet)
    time.sleep(5)
3

3 Answers

0
votes

You can store the time of the last shot bullet, and ignore all presses until 5 seconds pass. So, at the top

last_bullet_shot_time = None

Then

elif event.type == pygame.MOUSEBUTTONDOWN:
    if last_bullet_shot_time is None or 
        time.now() - last_bullet_shot_time > datetime.timedelta(seconds = 5):

        bullet = Bullet()
        bullet.rect.x = player.rect.x
        bullet.rect.y = player.rect.y
        all_sprites_list.add(bullet)
        bullet_list.add(bullet)
        last_bullet_shot_time = time.now()
0
votes

As you already found out time.sleep() halts the whole program(or thread to be exact) which usually isn't what you want. One possible solution is to compare the the times as @maniexx mentioned.

As you are using pygame I'd recommend using pygame.time.get_ticks() in basically the same way, as described in this answer.

0
votes

You can use pygame's ability to generate events on the basis of a timer along with a unique user-defined event to have it create an notification event after the desired amount of time has passed. Here's the changes you would need:

# globals
TIMEOUT_EXPIRED = pygame.USEREVENT+1
shooting_allowed = True

Then in the body of the game:

# in the event processing loop
elif event.type == pygame.MOUSEBUTTONDOWN:
    if shooting_allowed:
        bullet = Bullet()
        bullet.rect.x = player.rect.x
        bullet.rect.y = player.rect.y
        all_sprites_list.add(bullet)
        bullet_list.add(bullet)
        # disable shooting for 5 seconds
        shooting_allowed = False
        pygame.time.set_timer(TIMEOUT_EXPIRED, 5000)
elif event.type == TIMEOUT_EXPIRED:
    # re-enable shooting
    shooting_allowed = True
    pygame.time.set_timer(TIMEOUT_EXPIRED, 0)  # stop generation of event