Exemple #1
0
def game_setting_menu(interface, input_board, squareside):
    fenetre = None
    if interface != 1:
        if (input_board == []):
            print("\033[90m")
            squareside = input('\033[92mChoose size for Npuzzle: \n\033[91m')
            #####################
            #Ce check est obligatoire sinon tu peux balance une string ....
            if squareside.isdigit() == False or int(squareside) < 2:
                print("\033[91mBad value select int > 1\033[0m")
                exit()
            elif int(squareside) > 100:
                print("\033[91mDo you really wanna wait forever ??\033[0m")
                exit()
            #####################
            squareside = int(squareside)
            print("\033[90m")
        heuristic, algo = terminal_menu(squareside)
        gamemode = 'ia'
        # Comment this else if you don't want to go in the menu
        #
    else:
        fenetre = pygame.display.set_mode((1000, 800), 0, 32)
        menu_items = ('IA', 'Solo', 'Quit')
        pygame.display.set_caption('Game Menu')
        gm = GameMenu(fenetre, menu_items, input_board)
        # return the choice enter in the menu
        heuristic, algo, squareside, gamemode = gm.run()
    return heuristic, algo, squareside, gamemode, fenetre
Exemple #2
0
 def __init__(self):
     self.farm = Farm()
     self.dices = [
         Dice(6 * [AnimalType.RABBIT] + 3 * [AnimalType.SHEEP] + [AnimalType.PIG, AnimalType.COW, AnimalType.WOLF]),
         Dice(6 * [AnimalType.RABBIT] + 2 * [AnimalType.SHEEP, AnimalType.PIG] + [AnimalType.HORSE, AnimalType.FOX])]
     self.menu = GameMenu(self)
     self.turns = []
    def __init__(self, game):
        self.allSprites = pygame.sprite.Group()
        self.entities = pygame.sprite.Group()
        self.layer1 = pygame.sprite.Group()  # layer 1
        self.layer2 = pygame.sprite.Group()  # layer 2
        self.layer3 = pygame.sprite.Group()  # layer 3
        self.layer4 = pygame.sprite.Group()  # layer 4 is all layers combined
        self.game = game
        self.currentLayer = 4

        self.level = ""

        # Hud for when the game is running
        self.hud = GameHud(self.game)
        self.menu = GameMenu(self.game)
        self.messageSystem = MessageHud(self.game)

        self.personClickManager = PersonClickManager(self.game)
        self.transportClickManager = TransportClickManager(self.game)
        self.personHolderClickManager = PersonHolderClickManager(self.game)

        self.rendering = False

        # Game timer to keep track of how long has been played
        self.timer = 0

        # Make this dependant on the level and make it decrease
        # as the number of people who reach their destinations increase
        self.timeStep = 25

        self.lives = DEFAULTLIVES
        self.score, self.bestScore = 0, 0

        self.dt = 1  # Control the speed of whats on screen
        self.startDt = self.dt
        self.fixedScale = 1  # Control the size of whats on the screen
        self.startingFixedScale = 0
        self.paused = False  # Individual pause for the levels

        self.setDefaultMap()

        self.totalPeople, self.completed, self.totalToComplete = 0, 0, 0
        self.totalPeopleNone = False
        self.slowDownMeterAmount = 75

        self.debug = False
        self.darkMode = False

        # The connection types availabe on the map (always has layer 4)
        self.connectionTypes = ["layer 4"]
Exemple #4
0
class Game:
    def __init__(self):
        self.farm = Farm()
        self.dices = [
            Dice(6 * [AnimalType.RABBIT] + 3 * [AnimalType.SHEEP] + [AnimalType.PIG, AnimalType.COW, AnimalType.WOLF]),
            Dice(6 * [AnimalType.RABBIT] + 2 * [AnimalType.SHEEP, AnimalType.PIG] + [AnimalType.HORSE, AnimalType.FOX])]
        self.menu = GameMenu(self)
        self.turns = []

    def resolve_turn(self):
        self.menu.print_options()
        picked_option = InputListener.get_int_input()
        option = self.menu.get_option(picked_option)
        turn = Turn(option)
        turn.resolve_turn()
        self.turns.append(turn)

    def main_loop(self):
        while True:
            self.resolve_turn()
Exemple #5
0
    def __init__(self):
        self.is_running = False
        self.is_alive = False
        self.is_train = False
        self.is_human = True

        self.__hero = Hero()

        self.__score = 0
        self.__action_queue = []

        self.__width = WIDTH
        self.__height = HEIGHT

        self.__clock = None
        self.__environment = None

        self.screen = pg.display.set_mode((self.__width, self.__height))

        pg.init()

        self.__graphics = Graphics(self.screen)
        self.menu = GameMenu(self, self.screen)
Exemple #6
0
    def handle_key(self, key):
        if self.flow_path:
            return

        if self.menu is not None:
            self.menu.handle_key(key)
            return

        if key == pygame.K_ESCAPE and not self.menu:
            self.menu = GameMenu(game=self,
                                 main=self.main,
                                 screen=self.screen,
                                 settings=self.settings)
            return

        if self.reset_on_next_click:
            self.reset_fullness()
            self.reset_on_next_click = False

        if key == pygame.K_RETURN:
            self.start_flow()
Exemple #7
0
  #add bounds to game world  
  gameWorld.addObject(objects.BoundingBox(gameWorld, 20, 20))
  gameWorld.addObject(objects.Field())

  #add players to game world
  player = HumanPlayer(gameWorld, (-5.0, 1.1, 5.0))
  player.camera = gameWorld.camera
  gameWorld.addObject(player)
  gameWorld.addObject(AiPlayer(gameWorld, ball.body, (-5.0, 1.1, -5.0)))
  gameWorld.addObject(AiPlayer(gameWorld, ball.body, (5.0, 1.1, -5.0)))
  gameWorld.addObject(AiPlayer(gameWorld, ball.body, (5.0, 1.1, 5.0)))

  glClearColor(0.5, 0.7, 0.9, 1.0)
  #create game menu object
  gameMenu = GameMenu()

  #add the background objects to menu
  gameMenu.addObject(objects.Field())
  gameMenu.addObject(objects.BoundingBox(gameMenu, 10.0, 10))
  crazyCubes = [objects.Cube(gameMenu, (-5.0, 1.001, -5.0), 200, (2.0, 2.0, 2.0), (1,1,0)),
                objects.Cube(gameMenu, (-5.0, 3.002, -5.0), 200, (2.0, 2.0, 2.0), (0,0,1)),
                objects.Cube(gameMenu, (-5.0, 5.003, -5.0), 200, (2.0, 2.0, 2.0), (1,0,0)),
                objects.Cube(gameMenu, (-5.0, 7.004, -5.0), 200, (2.0, 2.0, 2.0), (0,1,0))]

  for cube in crazyCubes: gameMenu.addObject(cube)
  crazyBall = objects.Sphere(gameMenu, (-4,4,4), 200, 2.0, (0,0,1))
  crazyBall.body.addForce((5515, 3515, -454451))
  gameMenu.addObject(crazyBall)
  gameMenu.camera.setTarget(crazyBall)
Exemple #8
0
    layer.sprite.position = new.center
    scroller.set_focus(*new.center)


# Schedule Updates
layer.schedule(update)

# Add map to scroller
scroller.add(tilemap)

#Create Scene
scene = Scene()

# Create and add background
background = Background()
scene.add(background)

#Add main layer to scroller
scroller.add(layer)
scroller.add(ShowCollision())

# Add scroller to scene
scene.add(scroller)

# Game menu configuration
menu = GameMenu(scene)
menuScene = Scene()
menuScene.add(menu)

director.run(menuScene)
Exemple #9
0
def main():
    game_menu = GameMenu()
    game_menu.showing()
Exemple #10
0
    #add bounds to game world
    gameWorld.addObject(objects.BoundingBox(gameWorld, 20, 20))
    gameWorld.addObject(objects.Field())

    #add players to game world
    player = HumanPlayer(gameWorld, (-5.0, 1.1, 5.0))
    player.camera = gameWorld.camera
    gameWorld.addObject(player)
    gameWorld.addObject(AiPlayer(gameWorld, ball.body, (-5.0, 1.1, -5.0)))
    gameWorld.addObject(AiPlayer(gameWorld, ball.body, (5.0, 1.1, -5.0)))
    gameWorld.addObject(AiPlayer(gameWorld, ball.body, (5.0, 1.1, 5.0)))

    glClearColor(0.5, 0.7, 0.9, 1.0)
    #create game menu object
    gameMenu = GameMenu()

    #add the background objects to menu
    gameMenu.addObject(objects.Field())
    gameMenu.addObject(objects.BoundingBox(gameMenu, 10.0, 10))
    crazyCubes = [
        objects.Cube(gameMenu, (-5.0, 1.001, -5.0), 200, (2.0, 2.0, 2.0),
                     (1, 1, 0)),
        objects.Cube(gameMenu, (-5.0, 3.002, -5.0), 200, (2.0, 2.0, 2.0),
                     (0, 0, 1)),
        objects.Cube(gameMenu, (-5.0, 5.003, -5.0), 200, (2.0, 2.0, 2.0),
                     (1, 0, 0)),
        objects.Cube(gameMenu, (-5.0, 7.004, -5.0), 200, (2.0, 2.0, 2.0),
                     (0, 1, 0))
    ]
Exemple #11
0
class GameEngine:
    def __init__(self):
        self.is_running = False
        self.is_alive = False
        self.is_train = False
        self.is_human = True

        self.__hero = Hero()

        self.__score = 0
        self.__action_queue = []

        self.__width = WIDTH
        self.__height = HEIGHT

        self.__clock = None
        self.__environment = None

        self.screen = pg.display.set_mode((self.__width, self.__height))

        pg.init()

        self.__graphics = Graphics(self.screen)
        self.menu = GameMenu(self, self.screen)

    @staticmethod
    def off_screen():
        pg.display.iconify()

    def setup(self):
        self.is_running = True
        self.is_alive = True

        self.__action_queue = []
        self.__score = 0

        self.__hero = Hero()
        self.__environment = Environment()

        self.__environment.create_level()
        self.__clock = pg.time.Clock()

    def __key_checker(self, event):
        if not self.is_train:
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.menu.pause_menu()

                elif event.key == pg.K_SPACE:
                    if not self.is_alive:
                        self.menu.start_menu()

                    elif 'jump' not in self.__action_queue:
                        self.__action_queue.append('jump')

                elif event.key == pg.K_LCTRL:
                    if 'sit' not in self.__action_queue:
                        self.__action_queue.append('sit')

            elif event.type == pg.KEYUP:
                if event.key == pg.K_SPACE:
                    if 'jump' in self.__action_queue:
                        self.__action_queue.remove('jump')

                elif event.key == pg.K_LCTRL:
                    if 'sit' in self.__action_queue:
                        self.__action_queue.remove('sit')

    def get_action_from_key_check(self):
        if len(self.__action_queue) == 0:
            return 'nothing'
        else:
            return self.__action_queue[0]

    def __collision_check(self):
        collision_logic = CollisionLogic()
        current_prop = self.__environment.prop_list[0]

        if collision_logic.check_collision(self.__hero, current_prop):
            self.is_alive = False

    def get_state(self):
        cur_prop = self.__environment.prop_list[0]

        hero_y = self.__hero.coord[1]
        hero_x_size, hero_y_size = self.__hero.size
        hero_r_u_x = hero_x_size
        hero_r_u_y = hero_y + hero_y_size
        hero_vel_y = self.__hero.vel[1]
        hero_acc_y = self.__hero.acc[1]

        prop_x, prop_y = cur_prop.coord
        prop_x_size, prop_y_size = cur_prop.size
        prop_r_u_x = prop_x + prop_x_size
        prop_r_u_y = prop_y + prop_y_size
        prop_vel_x = cur_prop.vel[0]

        hero_y /= self.__height
        hero_r_u_x /= self.__width
        hero_r_u_y /= self.__height
        hero_vel_y /= MAX_VEL
        hero_acc_y /= MAX_ACC

        prop_x /= self.__width
        prop_y /= self.__height
        prop_r_u_x /= self.__width
        prop_r_u_y /= self.__height
        prop_vel_x /= MAX_VEL

        result = [
            hero_y, hero_r_u_x, hero_r_u_y, hero_vel_y, hero_acc_y, prop_x,
            prop_y, prop_r_u_x, prop_r_u_y, prop_vel_x
        ]
        return result

    def get_all_info(self):
        next_state = self.get_state()
        reward = 1
        done = not self.is_alive

        return next_state, reward, done

    def render(self):
        self.__clock.tick(FPS)

        for event in pg.event.get():
            if event.type == pg.QUIT:
                exit(0)
            else:
                self.__key_checker(event)

        if not self.is_alive:
            finished = self.__graphics.draw_wasted_screen()
            if finished:
                self.menu.start_menu()
        else:
            visible_obj = self.__environment.prop_list
            self.__graphics.draw(self.__hero, visible_obj, self.__score,
                                 STANDARD_MODE)

        pg.display.update()

    def step(self, action):
        self.__score += 1

        self.__collision_check()

        self.__hero.change_state(action)
        self.__hero.update()
        self.__environment.update()
def main():
    director.init(**window)
    menu = GameMenu()
    menu.start_game()
Exemple #13
0
from constants import *
from display import Display
from fever import Fever
from game import Game
from menu import GameMenu
from settings import Settings

# Set up
myDisplay = Display()
mySettings = Settings()
myMenu = GameMenu(myDisplay, mySettings)
# myPowerup = PowerUp(myDisplay.surface)
myFever = Fever(myDisplay.surface, myDisplay, mySettings)
# myPowerup.set_track(myFever.track)
myGame = Game(myMenu, myDisplay, myFever, mySettings)
running = True

# Game loop
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    myGame.run()

# Quit the game
pygame.quit()
quit()


class SpriteRenderer():
    # Loads all the sprites into groups and stuff
    def __init__(self, game):
        self.allSprites = pygame.sprite.Group()
        self.entities = pygame.sprite.Group()
        self.layer1 = pygame.sprite.Group()  # layer 1
        self.layer2 = pygame.sprite.Group()  # layer 2
        self.layer3 = pygame.sprite.Group()  # layer 3
        self.layer4 = pygame.sprite.Group()  # layer 4 is all layers combined
        self.game = game
        self.currentLayer = 4

        self.level = ""

        # Hud for when the game is running
        self.hud = GameHud(self.game)
        self.menu = GameMenu(self.game)
        self.messageSystem = MessageHud(self.game)

        self.personClickManager = PersonClickManager(self.game)
        self.transportClickManager = TransportClickManager(self.game)
        self.personHolderClickManager = PersonHolderClickManager(self.game)

        self.rendering = False

        # Game timer to keep track of how long has been played
        self.timer = 0

        # Make this dependant on the level and make it decrease
        # as the number of people who reach their destinations increase
        self.timeStep = 25

        self.lives = DEFAULTLIVES
        self.score, self.bestScore = 0, 0

        self.dt = 1  # Control the speed of whats on screen
        self.startDt = self.dt
        self.fixedScale = 1  # Control the size of whats on the screen
        self.startingFixedScale = 0
        self.paused = False  # Individual pause for the levels

        self.setDefaultMap()

        self.totalPeople, self.completed, self.totalToComplete = 0, 0, 0
        self.totalPeopleNone = False
        self.slowDownMeterAmount = 75

        self.debug = False
        self.darkMode = False

        # The connection types availabe on the map (always has layer 4)
        self.connectionTypes = ["layer 4"]

    def setDefaultMap(self):
        self.levelData = {
            "mapName": "",
            "locked": {
                "isLocked": False,
                "unlock": 0
            },  # Amount to unlock

            # Map can / cannot be deleted; maps that cant be
            # deleted cant be opened in the editor
            "deletable": True,
            "saved": False,  # Has the map been saved before
            "width": 18,
            "height": 10,
            "difficulty": 1,  # Out of 4
            "total": 8,  # Total to complete the level
            "score": 0,
            "completion": {
                "total": 10,
                "completed": False,
                "time": 0
            },
            "backgrounds": {
                "layer 1": CREAM,  # Default color: CREAM :)
                "layer 2": CREAM,
                "layer 3": CREAM,
                "layer 4": CREAM
            },
            "connections": {},
            "transport": {},
            "stops": {},
            "destinations": {}
        }  # Level data to be stored, for export to JSON

    # Save function, for when the level has already
    # been created before (and is being edited)
    def saveLevel(self):
        self.game.mapLoader.saveMap(self.levelData["mapName"], self.levelData)

    def setRendering(self, rendering, transition=False):
        self.rendering = rendering
        self.hud.main(transition) if self.rendering else self.hud.close()

        if self.rendering:
            self.messageSystem.main()
        else:
            self.messageSystem.close()

        # Create the paused surface when first rendering
        self.createPausedSurface()

    def runStartScreen(self):
        if self.rendering and not self.debug:
            self.menu.startScreen()

    def runEndScreen(self, completed=False):
        if self.rendering and not self.debug:
            if completed:
                self.menu.endScreenComplete(True)  # Run with transition
            else:
                self.menu.endScreenGameOver(True)  # Run with transition

    def setCompleted(self, completed):
        self.completed = completed
        self.hud.setCompletedText()

    # When the player completed the level, set it to complete
    # in the level data and save the data
    def setLevelComplete(self):
        if not hasattr(self, 'levelData'):
            return

        # If the level is not already set to completed, complete it
        if not self.levelData["completion"]["completed"]:
            self.levelData["completion"]["completed"] = True
            self.saveLevel()

    # Use the number of lives left to work out the players score TODO:
    #   Make this use other factors in the future

    # Return the previous keys and difference so
    # this can be used in the menu animation
    def setLevelScore(self):
        if not hasattr(self, 'levelData'):
            return

        self.score = self.lives
        previousScore = 0

        if "score" in self.levelData:
            previousScore = self.levelData["score"]
            self.bestScore = previousScore

        if self.score > previousScore:
            self.levelData["score"] = self.score
            self.saveLevel()

        if self.score - previousScore > 0:
            scoreDifference = self.score - previousScore
        else:
            scoreDifference = 0

        # Use this in the menu animation
        previousKeys = config["player"]["keys"]
        config["player"]["keys"] += scoreDifference
        dump(config)

        return previousKeys, scoreDifference, previousScore

    def setTotalToComplete(self, totalToComplete):
        self.totalToComplete = totalToComplete

    def setSlowDownMeterAmount(self, slowDownMeterAmount):
        self.slowDownMeterAmount = slowDownMeterAmount

    def setDt(self, dt):
        self.dt = dt

    def setFixedScale(self, fixedScale):
        self.fixedScale = fixedScale

    def setStartingFixedScale(self, startingFixedScale):
        self.startingFixedScale = startingFixedScale

    def setDebug(self, debug):
        self.debug = debug

    def setDarkMode(self):
        if ("backgrounds" in self.levelData
                and "darkMode" in self.levelData["backgrounds"]
                and self.levelData["backgrounds"]["darkMode"]):
            self.darkMode = True

        else:
            self.darkMode = False

    def setTotalPeople(self, totalPeople):
        self.totalPeople = totalPeople

    def setLives(self, lives):
        self.lives = lives

    def togglePaused(self):
        self.dt = 0
        self.paused = not self.paused
        # self.game.paused = not self.game.paused
        # self.createPausedSurface()

    def getStartDt(self):
        return self.startDt

    def getDt(self):
        return self.dt

    def getFixedScale(self):
        return self.fixedScale

    def getStartingFixedScale(self):
        return self.startingFixedScale

    def getHud(self):
        return self.hud

    def getMenu(self):
        return self.menu

    def getMessageSystem(self):
        return self.messageSystem

    def getLevel(self):
        return self.level

    def getLevelData(self):
        return self.levelData

    def getPersonClickManager(self):
        return self.personClickManager

    def getTransportClickManager(self):
        return self.transportClickManager

    def getLayer(self):
        return self.currentLayer

    def getCompleted(self):
        return self.completed

    def getTotalToComplete(self):
        return self.totalToComplete

    def getSlowDownMeterAmount(self):
        return self.slowDownMeterAmount

    def getDebug(self):
        return self.debug

    def getConnectionTypes(self):
        return self.connectionTypes

    def getDarkMode(self):
        return self.darkMode

    def getTotalPeople(self):
        return self.totalPeople

    def getLives(self):
        return self.lives

    def getAllDestination(self):
        if hasattr(self, 'allDestinations'):
            return self.allDestinations

    def getScore(self):
        return self.score

    def getBestScore(self):
        return self.bestScore

    def getPaused(self):
        return self.paused

    def getCurrentLayer(self):
        return self.currentLayer

    def getPersonHolderClickManager(self):
        return self.personHolderClickManager

    def removeLife(self):
        self.lives -= 1
        # remove a heart from the hud here or something
        self.hud.setLifeAmount()
        if self.lives <= 0:
            # Although we pause the game in the timer, we want to
            # stop anything else from reducing the life count here whilst the
            # timer is decreasing (so no one can die whilst it is decreasing)
            pass

    def addToCompleted(self):
        self.completed += 1
        # self.timeStep -= 0.5
        self.hud.setCompletedAmount()
        self.meter.addToAmountToAdd(20)

    # Reset the level back to its default state
    def clearLevel(self):
        self.paused = False  # Not to confuse the option menu
        self.startingFixedScale = 0  # reset the scale back to default
        self.timer = 0
        self.lives = DEFAULTLIVES
        self.totalPeople = 0
        self.totalPeopleNone = False
        self.entities.empty()
        self.allSprites.empty()
        self.layer1.empty()
        self.layer2.empty()
        self.layer3.empty()
        self.layer4.empty()

        # Reset the layers to show the top layer
        self.currentLayer = 4
        self.connectionTypes = []
        self.setDefaultMap()

    def createLevel(self, level, debug=False):
        self.clearLevel()
        # Currently this calls the wrong hud as its done before the hud is set
        self.setCompleted(0)
        self.debug = debug

        self.gridLayer4 = Layer4(self, (self.allSprites, self.layer4), level)

        # Set the name of the level
        self.level = self.gridLayer4.getGrid().getLevelName()

        # Set the level data
        self.levelData = self.gridLayer4.getGrid().getMap()

        # for running the game in test mode (when testing a level)
        if self.debug:
            # Push the level down since we have hud at the top
            spacing = (1.5, 1.5)
            self.hud = PreviewHud(self.game, spacing)
        else:
            # self.startingFixedScale = -0.05
            # spacings = {
            #     (16, 9): (1.5, 1),
            #     (18, 10): (2, 1.5),
            #     (20, 11): (1.5, 1),
            #     (22, 12): (1.5, 1)}

            # size = (self.levelData["width"], self.levelData["height"])
            # spacing = spacings[size]
            spacing = (1.5, 1)
            self.hud = GameHud(self.game, spacing)

        # we want to get which connectionTypes are available in the map
        for connectionType in self.levelData['connections']:
            self.connectionTypes.append(connectionType)

        self.gridLayer3 = Layer3(self,
                                 (self.allSprites, self.layer3, self.layer4),
                                 level, spacing)
        self.gridLayer1 = Layer1(self,
                                 (self.allSprites, self.layer1, self.layer4),
                                 level, spacing)

        # Walking layer at the bottom so nodes are drawn above metro stations
        self.gridLayer2 = Layer2(self,
                                 (self.allSprites, self.layer2, self.layer4),
                                 level, spacing)

        self.gridLayer4.addLayerLines(self.gridLayer1, self.gridLayer2,
                                      self.gridLayer3)

        self.gridLayer1.grid.loadTransport("layer 1")
        self.gridLayer2.grid.loadTransport("layer 2")
        self.gridLayer3.grid.loadTransport("layer 3")

        self.removeDuplicates()

        # Set all the destinations to be the destinations from all layers
        layer1Destinations = self.gridLayer1.getGrid().getDestinations()
        layer2Destinations = self.gridLayer2.getGrid().getDestinations()
        layer3Destinations = self.gridLayer3.getGrid().getDestinations()
        self.allDestinations = (layer1Destinations + layer2Destinations +
                                layer3Destinations)

        # Set number of people to complete level
        if "total" not in self.levelData:
            self.totalToComplete = random.randint(8, 12)

        else:
            self.totalToComplete = self.levelData["total"]
        # self.totalToComplete = 1

        self.meter = MeterController(self, self.allSprites,
                                     self.slowDownMeterAmount)
        self.setDarkMode()

        # If there is more than one layer we want to be able
        # to see 'all' layers at once (layer 4)
        # otherwise we only need to see the single layer

        if len(self.connectionTypes) > 1 or self.debug:
            self.connectionTypes.append("layer 4")
        else:
            self.showLayer(
                self.getGridLayer(self.connectionTypes[0]).getNumber())

    # Draw the level to a surface and return this surface for blitting
    # (i.e on the level selection screen)
    def createLevelSurface(self, level):
        self.clearLevel()
        self.startingFixedScale = -0.2

        spacings = {
            (16, 9): (3.5, 2),
            (18, 10): (4, 2.5),
            (20, 11): (4.5, 2.8),
            (22, 12): (5, 3)
        }

        gridLayer4 = MenuLayer4(self, (), level)

        levelData = gridLayer4.getGrid().getMap()
        size = (levelData["width"], levelData["height"])
        spacing = spacings[size]

        gridLayer3 = Layer3(self, (), level, spacing)
        gridLayer1 = Layer1(self, (), level, spacing)
        gridLayer2 = Layer2(self, (), level, spacing)
        gridLayer4.addLayerLines(gridLayer1, gridLayer2, gridLayer3)

        return gridLayer4.getLineSurface()

    # Create a new surface when the game is paused with all the sprites
    # currently in the game, so these don't have to be drawn every frame
    # (as they are not moving)

    def createPausedSurface(self):
        if self.rendering and self.game.paused:
            self.pausedSurface = pygame.Surface(
                (int(config["graphics"]["displayWidth"] *
                     self.game.renderer.getScale()),
                 int(config["graphics"]["displayHeight"] *
                     self.game.renderer.getScale()))).convert()

            lineSurface = (
                self.getGridLayer("layer " +
                                  str(self.currentLayer)).getLineSurface())
            self.pausedSurface.blit(lineSurface, (0, 0))

            for entity in self.entities:
                entity.drawPaused(self.pausedSurface)

            self.renderPausedLayer(1, self.layer1)
            self.renderPausedLayer(2, self.layer2)
            self.renderPausedLayer(3, self.layer3)
            self.renderPausedLayer(4, self.layer4)

            # for component in (
            #     self.hud.getComponents()
            #         + self.messageSystem.getComponents()):
            #     # draw hud and message system
            #     component.drawPaused(self.pausedSurface)

            return self.pausedSurface

    def getSpriteLayer(self, connectionType):
        if connectionType == "layer 1":
            return self.layer1
        elif connectionType == "layer 2":
            return self.layer2
        elif connectionType == "layer 3":
            return self.layer3
        elif connectionType == "layer 4":
            return self.layer4

    def getGridLayer(self, connectionType):
        if connectionType == "layer 1":
            return self.gridLayer1
        elif connectionType == "layer 2":
            return self.gridLayer2
        elif connectionType == "layer 3":
            return self.gridLayer3
        elif connectionType == "layer 4":
            return self.gridLayer4

    # Get all the nodes from all layers in the spriterenderer
    def getAllNodes(self, sortNodes=False):
        layer1Nodes = self.gridLayer1.getGrid().getNodes()
        layer2Nodes = self.gridLayer2.getGrid().getNodes()
        layer3Nodes = self.gridLayer3.getGrid().getNodes()
        allNodes = layer1Nodes + layer2Nodes + layer3Nodes

        # Sort the node so that the stops are at the top
        if sortNodes:
            allNodes = sorted(allNodes, key=lambda x: isinstance(x, Stop))
            allNodes = sorted(allNodes,
                              key=lambda x: isinstance(x, Destination))
            # Reverse the list so they're at the front
            allNodes = allNodes[::-1]

        return allNodes

    # Remove duplicate nodes on layer 4 for layering
    def removeDuplicates(self, allNodes=None, removeLayer=None):
        seen = {}
        dupes = []
        removeLayer = self.layer4 if removeLayer is None else removeLayer

        if allNodes is None:
            allNodes = self.getAllNodes()

        # Make sure stops are at the front of the list, so they are not removed
        allNodes = sorted(allNodes, key=lambda x: isinstance(x, Stop))
        allNodes = sorted(allNodes, key=lambda x: isinstance(x, Destination))
        allNodes = allNodes[::-1]  # Reverse the list so they're at the front

        for node in allNodes:
            if node.getNumber() not in seen:
                seen[node.getNumber()] = 1
            else:
                if seen[node.getNumber()] == 1:
                    dupes.append(node)

        for node in dupes:
            removeLayer.remove(node)

    # if there is a node above the given node,
    # return the highest node, else return node
    def getTopNode(self, bottomNode):
        allNodes = self.getAllNodes(True)

        for node in allNodes:
            if node.getNumber() == bottomNode.getNumber():
                return node

        return bottomNode

    def update(self):
        if not self.rendering:
            return
        self.allSprites.update()

        if self.paused:
            return

        self.events()
        self.timer += self.game.dt * self.dt

        # Always spawn a person if there is no people
        # left on the map, to stop player having to wait
        if self.timer > self.timeStep:
            self.timer = 0
            self.gridLayer2.createPerson(self.allDestinations)

        if self.totalPeople <= 0:
            if not self.totalPeopleNone:
                self.timer = 0
                self.totalPeopleNone = True

            # wait 2 seconds before spawing the next
            # person when there is no people left
            if self.timer > 2 and self.totalPeopleNone:
                self.timer = 0
                self.gridLayer2.createPerson(self.allDestinations)
                self.totalPeopleNone = False

    def events(self):
        if pygame.key.get_pressed()[pygame.K_SPACE]:
            self.game.clickManager.setSpaceBar(True)

            if (self.dt != self.startDt - self.meter.getSlowDownAmount()
                    and not self.meter.getEmpty()):
                self.game.audioLoader.playSound("slowIn", 1)

        else:
            if self.dt != self.startDt:
                self.game.audioLoader.playSound("slowOut", 1)

            self.game.clickManager.setSpaceBar(False)

    # Make people on the current layer clickable, and the rest non-clickable
    def resetPeopleClicks(self):
        totalPeople = (self.gridLayer1.getPeople() +
                       self.gridLayer2.getPeople() +
                       self.gridLayer3.getPeople())

        currentLayerPeople = self.getGridLayer(
            "layer " + str(self.currentLayer)).getPeople()

        for person in totalPeople:
            if person in currentLayerPeople or self.currentLayer == 4:
                # Always went every person to be clickable on the top layer
                person.setCanClick(True)

            else:
                person.setCanClick(False)

    def resetPersonHolderClicks(self):
        totalNodes = self.getAllNodes()

        for node in totalNodes:
            if (node.getConnectionType() == "layer " + str(self.currentLayer)
                    or self.currentLayer == 4):
                # Always want every person holder to be clickable
                # on the top layer
                node.getPersonHolder().setCanClick(True)

            else:
                node.getPersonHolder().setCanClick(False)

    def showLayer(self, layer):
        if not self.rendering:
            return

        # Only switch to a layer that is in the map
        if "layer " + str(layer) in self.connectionTypes:
            self.currentLayer = layer
            # Redraw the nodes so that the mouse cant collide with them
            self.resize()
            self.hud.updateLayerText()
            self.resetPeopleClicks()
            self.resetPersonHolderClicks()

    def resize(self):
        # If a layer has any images, they must be resized here
        if self.rendering:
            self.gridLayer1.resize()
            self.gridLayer2.resize()
            self.gridLayer3.resize()
            # Only need to do this if it has components
            self.gridLayer4.resize()

            # We want to reset the layer 4 lines with the
            # new ones (resized) from the other layers
            self.gridLayer4.addLayerLines(self.gridLayer1, self.gridLayer2,
                                          self.gridLayer3)

            # resize huds and menus
            self.hud.resize()
            self.menu.resize()
            self.messageSystem.resize()

            for sprite in self.allSprites:
                sprite.dirty = True

            self.createPausedSurface()

    # Draw all the sprites in a layer, based on what layer the player
    # is currently on
    def renderLayer(self, layerInt, gridLayer, group):
        if self.currentLayer == layerInt:
            gridLayer.draw()
            for sprite in group:
                sprite.draw()

    # Draw all sprites to the paused surface, based on what layer the player
    # is currently on
    def renderPausedLayer(self, layerInt, group):
        if self.currentLayer == layerInt:
            for sprite in group:
                sprite.drawPaused(self.pausedSurface)

    def render(self):
        if self.rendering:
            if not self.game.paused:
                # Entities drawn below the other sprites
                for entity in self.entities:
                    entity.draw()

                self.renderLayer(1, self.gridLayer1, self.layer1)
                self.renderLayer(2, self.gridLayer2, self.layer2)
                self.renderLayer(3, self.gridLayer3, self.layer3)
                self.renderLayer(4, self.gridLayer4, self.layer4)

            else:
                if hasattr(self, 'pausedSurface'):
                    self.game.renderer.addSurface(
                        self.pausedSurface, (self.pausedSurface.get_rect()))

            self.hud.display()
            self.messageSystem.display()
            self.menu.display()