Loading a level

No matter if it's an FPS, RTS, or driving game we're making, we'll want to be able to load different kinds of environments for the players to roam around in. How can we do that easily?

In this recipe, we'll add functionalities to the networked FPS game we outlined previously in this chapter. The principle will work for any kind of already networked game, although it might differ depending on how the game implements the level. Here, we'll assume it uses jMonkeyEngine scenes or .j3o scenes.

How to do it...

Perform the following set of steps to load a level:

  1. We start by defining a new message class: LoadLevelMessage. It extends GameMessage since it might be useful to know the gameId. Apart from that, it has one field levelName.
  2. We'll add the same field to our Game class so that it can keep track of which level it's running.
  3. Next, let's create a levelNode field on our server, which we can load our level into, as follows:
    private Node loadLevel(String levelName){
      return (Node) assetManager.loadModel("Scenes/"+levelName + ".j3o");
    }
  4. Then, we create a small method that will load the level from a predefined path, as follows:
    levelNode = loadLevel("TestScene");
    rootNode.attachChild(levelNode);
    game.setLevelName("TestScene");
  5. Inside the simpleInitApp method, we'll tell the application to load TestScene from Chapter 1, SDK Game Development Hub:
    LoadLevelMessage levelMessage = new LoadLevelMessage();
    levelMessage.setLevelName(game.getLevelName());
    server.broadcast(Filters.in(conn), levelMessage);
  6. Finally, inside the addPlayer method, we need to create and send the message to the connecting client. That's all for the server side of things.
  7. In the client, we create a levelNode field and a loadLevel method, but it's a little bit different:
    public void loadLevel(final String levelName){
      enqueue(new Callable(){
        public Object call() throws Exception {
          if(rootNode.hasChild(levelNode)){
            rootNode.detachChild(levelNode);
            }
            levelNode = (Node) assetManager.loadModel("Scenes/"+levelName + ".j3o");
            rootNode.attachChild(levelNode);
            return null;
        }
      });
    }
  8. We need to make sure we manipulate the scene graph at the correct moment in time so that we can detach and attach the node inside an enqueue block.
  9. Finally, we make sure MessageListener picks up LoadLevelMessage as follows:
    else if (m instanceof LoadLevelMessage){
      gameClient.loadLevel(((LoadLevelMessage)m).getLevelName());
      game.setLevelName(((LoadLevelMessage)m).getLevelName());
    }
  10. That's it! When we connect to the server again, we should see a familiar scene.

How it works...

When a client joins, the server creates a LoadLevelMessage class and populates it with the name of the level currently loaded. The server doesn't supply the level itself, but the client must have the levels supplied previously. The LoadLevelMessage class only provides a name in this case, which is probably enough in many cases. For some games, it's a good idea to support a custom path when loading levels, since it allows for greater customization options.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.182.62