Break Into Program – CodeDrop #36

Codedrop for CoderDojo #36 (September 21st 2019)

This is written in Python, and uses the excellent PyGame engine.

For installation instructions, go here:

# Import the libraries
#
import pygame
import random

# Initialise PyGame
# 
pygame.init()

# Some global variables
#
win_w = 1024              # Window width
win_h = 768               # Window height

image_files = [                # List of images to load
    "robot.jpg",
    "space_invader.png"
]               

# Variables used by this game engine we're writing
#
sprites = []              # List of sprites
images = {}               # Hashtable of images

# Create a screen surface to draw on, and a clock
#
screen = pygame.display.set_mode((win_w, win_h))
clock = pygame.time.Clock()

# Set the key repeat to 1ms delay, 1ms repeat
#
pygame.key.set_repeat(1,1)

# Load some images -------------------------------------------------------------

for image_file in image_files:
    image = pygame.image.load("../Graphics/" + image_file).convert()
    image.set_colorkey((255,255,255))
    images[image_file] = image

# The Sprite class -------------------------------------------------------------

class Sprite:
    #
    # Some basic variables, just for this sprite
    #
    active = None   # Whether the sprite is active or off
    xp = None       # X position of the sprite
    yp = None       # Y position of the sprite
    image = None    # Sprite image
    type = None     # Sprite type (string)
    fn_move = None  # Function to move the sprite
    
    #
    # This is called when we initialise the Sprite class
    #
    def __init__(self):
        self.active = False

    #
    # A class function to move the sprite
    #
    def move(self):
        if(self.active and self.fn_move is not None):
            self.fn_move(self)
            return

    #
    # A class function to draw the sprite
    #
    def draw(self):
        if(self.active):
            screen.blit(self.image, (self.xp, self.yp))

# Set up a list of Sprites
#
max_sprites = 200                                   # Number of sprites we want to create
sprites = [Sprite() for i in range(max_sprites)]    # Create a list of Sprites

# Helper functions ------------------------------------------------------------

# Find index of next available free sprite slot in list
# Returns sprite object, or None if no slots left
# Start from 2, as 0 and 1 are reserved for player and player missile
#
def find_next_available_sprite():
    for sprite in sprites:
        if sprite.active == False:
            return sprite
    return None

# Movement functions ----------------------------------------------------------

# Move the player
#
def move_player(self):
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        self.xp -= 4
    if keys[pygame.K_RIGHT]:
        self.xp += 4
    if keys[pygame.K_UP]:
        self.yp -= 4
    if keys[pygame.K_DOWN]:
        self.yp += 4

# Move the invader
#
def move_invader_1(self):
    px = sprites[0].xp                  # The player's X position    
    py = sprites[0].yp                  # The player's Y position

    if px < self.xp:                    # If the player is to the left of this sprite
        self.xp -= 1                    # Move this sprite left 
    if px > self.xp:                    # Similarly, move the sprite right if the player is to the right
        self.xp += 1
        
    if py < self.yp:                    # And up..
        self.yp -= 1
    if py > self.yp:                    # And down..
        self.yp += 1

    if px == self.xp and py == self.yp:
        self.xp = random.randint(0, win_w)
        self.yp = random.randint(0, win_h)

    self.counter -=1
    if self.counter < 0:
        self.counter = random.randint(60, 120)
        self.fn_move = move_invader_2
        
    return

def move_invader_2(self):
    self.counter -=1
    if self.counter < 0:
        self.counter = random.randint(60, 120)
        self.fn_move = move_invader_1
    return

# Stubbed functions ------------------------------------------------------------

# Called when the game initialises
#
def Initialise_Game():
    # Create the player sprite
    #
    s = find_next_available_sprite()
    s.sprite_type = "player"            # This is the sprite type
    s.active = True                     # Set the sprite to be active
    s.xp = win_w//2                     # Set X position to centre of screen
    s.yp = win_h//2                     # Set Y position to centre of screen
    s.image = images["robot.jpg"]       # Set image (loaded previously)
    s.fn_move = move_player             # Set function to move sprite
    return

# Called when the level initialises
#
def Initialise_Level():
    for c in range(10):                             # Do this 10 times!
        s = find_next_available_sprite()            # Get next available slot for the sprite
        if(s != None):
            s.sprite_type = "invader"               # This is the sprite type
            s.active = True                         # Set the sprite to be active
            s.xp = random.randint(0, win_w)         # Set X position to centre of screen
            s.yp = random.randint(0, win_h)         # Set Y position to centre of screen
            s.image = images["space_invader.png"]   # Set image (loaded previously)
            s.counter = random.randint(60, 120)
            s.fn_move = move_invader_1   # Set function to move sprite    
    return

# Called when the level ends
#
def End_Level():
    return

# Called when the game ends
#
def End_Game():
    return

# Main Game Loop ---------------------------------------------------------------

Initialise_Game()

# This outer loop keeps going until end_game is True
#
end_game = False
while not end_game:

    Initialise_Level()

    # This outer loop keeps going until end_level is True
    #
    end_level = False
    while not end_level:
        
        #
        # Pygame event handler
        #
        for event in pygame.event.get():
            # Check for window close
            if event.type == pygame.QUIT:
                end_level = True
                end_game = True

        # Move everything by calling the Sprite's move function
        #
        for sprite in sprites:
            sprite.move()
                
        # Clear the screen
        #
        screen.fill((255,255,255))

        # Draw the Sprites by calling their draw function
        #
        for sprite in sprites:
            sprite.draw()

        # Update the surface to the screen and lock at 60fps
        #
        pygame.display.flip()
        clock.tick(60)

    # Level over
    #
    End_Level()

# Game over!
#
End_Game()
pygame.quit()