Search code examples
pythonpygamesprite

How to spawn enemy blocks continuously without manually creating them?


I am creating a game similar to the "Internet T-rex Game", Right now my game creates enemy blocks according to how many I manually create. I want it to be created by itself. My game is not fully completed yet, so please ignore the empty functions.

Heres my main.py

import pygame as pg
import random
from settings import *
from sprites import *
from os import path


class Game(object):
    """docstring for Game"""
    def __init__(self):
        # initialise game
        global points , game_speed
        pg.init()
        self.screen = pg.display.set_mode((s_HEIGHT , s_WIDTH))
        pg.display.set_caption(TITLE)
        self.icon = pg.image.load("C:/Users/DELL/Documents/Jump Cube/Img/cube.png")
        pg.display.set_icon(self.icon)
        self.clock = pg.time.Clock()
        self.running = True
        self.game_speed = 14
        points = 0
        font = pygame.font.Font('freesansbold.ttf', 20)

        self.load_data()



    def load_data(self):
        self.dir = path.dirname(__file__)
        img_dir = path.join(self.dir, "Img")
        #load spritesheet image
        self.spritesheet = Spritesheet(path.join(img_dir, SPRITESHEET))


    def new(self):
        # Stars a new game
        self.all_sprites = pg.sprite.Group()
        self.platforms = pg.sprite.Group()
        self.ene = pg.sprite.Group()
        self.player = Player(self)
        self.all_sprites.add(self.player)
        pl = Platform(0, s_HEIGHT - 230, 800, 40)

        en1 = Enemy(700, 517, 50, 50)
        en2 = Enemy(600, 517, 50, 50)
        en3 = Enemy(500, 517, 50, 50)

        self.all_sprites.add(pl)
        self.platforms.add(pl)
        self.all_sprites.add([en1, en2, en3])
        self.ene.add([en1, en2, en3])
        self.Run()

    def Run(self):
        # Game Loop
        self.playing = True
        while self.playing:
            self.clock.tick(FPS)
            self.Events()
            self.Update()
            self.Draw()
            self.score()

    def Update(self):
        # Game Loop - Update
        self.all_sprites.update()
        hits = pg.sprite.spritecollide(self.player, self.platforms, False)
        if hits:
            self.player.pos.y = hits[0].rect.top
            self.player.vel.y = 0
        pass

    def score(self):
        global points , game_speed
        points += 1
        if points % 100 == 0:
            game_speed += 1

        text = font.render("Points : " + str(points), True, WHITE)
        textrec = text.get_rect()
        textrec.center = (700, 50)
        self.screen.blit(text, textrec)

    def Events(self):
        # Game Loop - Events
        for event in pg.event.get():
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    self.player.jump()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_RIGHT:
                    self.player.mover()
                elif event.key == pg.K_LEFT:
                    self.player.movel()
    def Draw(self):
        # Game Loop - Draw
        self.screen.fill(BLACK)
        self.score()
        self.all_sprites.draw(self.screen)
        pg.display.update()
        pass

    def start_screen(self):
        # shows the start screen
        pass

    def end_screen(self):
        # shows the end screen
        pass

g = Game()
g.start_screen()

while g.running:
    g.new()
    g.end_screen()

pg.quit()

sprites.py

import pygame as pg
from settings import *
vec = pg.math.Vector2

class Spritesheet():
    # utility class for laoding and parsing spritesheets
    def __init__(self, filename):
        self.spritesheet = pg.image.load(filename).convert()

    def get_image(self, x, y, width, height):
        # grabs images from large spritesheets
        image = pg.Surface((width, height))
        image.blit(self.spritesheet, (0,0), (x, y, width, height))
        image = pg.transform.scale(image , (50, 85))
        return image

class Player(pg.sprite.Sprite):

    def __init__(self, game):
        pg.sprite.Sprite.__init__(self)
        self.game = game
        self.image = self.game.spritesheet.get_image(614, 1063, 120, 191)
        self.image.set_colorkey(BLACK1)
        self.rect = self.image.get_rect()
        self.rect.center = (s_WIDTH / 2, s_HEIGHT / 2)
        self.pos = vec(100, 600)
        self.vel = (0, 0)
        self.acc = (0, 0)

    def jump(self):
        #jump only if standing on plat
        self.rect.y += 1
        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        self.rect.y -= 1
        if hits:
            self.vel.y = -8

    def mover(self):
        #move right
        self.vel.x = 5

    def movel(self):
        #move right
        self.vel.x = -5

    def update(self):
        self.acc = vec(0, PLAYER_GRAV)
        self.vel += self.acc
        self.pos += self.vel + 0.5 * self.acc

        self.rect.midbottom = self.pos

class Platform(pg.sprite.Sprite):

    def __init__(self, x, y, w, h):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((w, h))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

class Enemy(pg.sprite.Sprite):
    def __init__(self, x, y, w1, h1):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((w1, h1))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def update(self):
        self.rect.x -= game_speed

settings.py

import pygame
pygame.init()

#game options
TITLE = "Ninja Jump"
s_WIDTH = 600
s_HEIGHT = 800
FPS = 60
game_speed = 14
points = 0
font = pygame.font.Font('freesansbold.ttf', 20)

SPRITESHEET = "spritesheet_jumper.png"

#player properties
PLAYER_ACC = 0.5
PLAYER_GRAV = 0.3

#colors
WHITE = (199, 198, 196)
BLACK = (23, 23, 23)
GRAY = (121, 121, 120)
GREEN = (72, 161, 77)
BLACK1 = (0,0,0)
GRAY1 = (162, 162, 162)

Thanks for any help and let me know if the problem needs more clarification.


Solution

  • Spawn the enemies by a time interval. In pygame the system time can be obtained by calling pygame.time.get_ticks(), which returns the number of milliseconds since pygame.init() was called. Define a time interval to spawn enemies. Continuously compare the current time with the time when the next enemy must appear. When the time comes, spawn an enemy and set the time the next enemy must spawn:

    class Game(object):
        # [...]
    
        def Run(self):
      
            self.next_enemy_time = 0
            self.enemy_time_interval = 1000 # 1000 milliseconds == 1 second
    
            # Game Loop
            self.playing = True
            while self.playing:
    
                current_time = pygame.time.get_ticks()
                if current_time > self.next_enemy_time:
                    self.next_enemy_time += self.enemy_time_interval
                    new_enemy = Enemy(700, 517, 50, 50)
                    self.all_sprites.add(new_enemy)
                    self.ene.add(new_enemy)
    
                self.clock.tick(FPS)
                self.Events()
                self.Update()
                self.Draw()
                self.score()