Doachick.com KB

  • Increase font size
  • Default font size
  • Decrease font size
Home Development XNA Tutorials XNA multiple world and map instancing

XNA multiple world and map instancing

E-mail Print PDF
User Rating: / 0
PoorBest 
Instancing multiple worlds or maps

This tutorial is ment to introduce you to the basic concept of layered game states, handling updating, drawing etc in a situation where you would have to update an entire world based on

events and AI / player decisions while still being able to do realtime processing for your active world object.

The very simple and limited code samples are written in C# (If you get stuck wondering about the GameTime object I'm sending in most methods, it's simply a built-in timer in the XNA

Framework Game class).
XNA is an excellent framework written by microsoft for beginner game programmers or intermediates looking to get past the complexity of setting up a directx framework.

I will not go into the depths of game designing, but rather give guidelines based on a fictional gamedesign.
Also I am not a mainstream coder / developer, I rarely write engines for the purpose of being reusable, instead I go straight into the mechanics of what I am currently developing and

optimize it to work exceptionally for that one purpose.

I find making re-usable classes and using them on a when-needed basis is better.

Concept
You have a world map with different travelpoints or maybe entry/exit points.
The world you are in are dynamic, so every map needs to be updated even if it is not the active one. Likely your map class will have camera objects, draw methods, update methods, game

objects and more. Updating all of these in maps that do not have focus would likley cause a ton of problems and slowdowns.

A possible scenario could be a space rts game, where you have a starmap with different planets that brings you to their 3d equalient if clicked. Your space game has AI players as well as

human players, the AI builds, colonizes, sends ships and so on in each of the update cycles. Maybe you have resource gathering depending on ore mines or such built on each of the planets

that needs to be calculated on a per-planet basis. Maybe a fight is going on on a planet you are not focused on, the combat must be simulated and events must be updated.

Defining the world

A good approach would be to have a base game class with an object for each game state.

For example:


Planet currentPlanet = null;
GameScreen currentGameScreen = null;
WorldMap worldMap = null; //A 2D surface that draws planet/ship/satelite icons and such based on their worldmap location

WorldMap currentOverlayMap = null; //The overlay map would be for viewing the world map on top of the 3d world

Hud hud = null; //We want to be able to set the active hud depending on gamestate and other conditions, such as if we are on a planet maybe we should have different huds or at least 

different hud parameters depending on if we are the owner of the planet or not.

 


The next step is to initialize your worldmap with whatever parameters you have defined.

Let it generate planets, AI players, planet ownerships, starting money, starting ships / buildings and so on.

Your worldmap class or a dedicated class should also hold some sort of static array or list for all the planet objects.

 

One thing that should also be noted is that there is no limits to what each game state draws.

The worldmap, overlay, hud and gamescreen can be in 2D while the planets are rendered in full 3D.

Each game object such as ships would have to have two sets of coordinates. 3D coordinates for the current planet they are on, and 2D coordinates for their position in space if they are not

on a planet.

 

 

Updating the world

The main update method could look something like this:

 

if (worldMap != null)

{

    worldMap.Update(GameTime gameTime);

}

 

if (currentGameScreen != null)

{

    currentGameScreen.Update(GameTime gameTime);

}

 

if (currentPlanet != null)

{

    currentPlanet.Update(GameTime gameTime, true) //The true parameter is a boolean the Planet class update method takes that decides if it should do an focused or unfocused update. If the currentPlanet is not null, it means it has focus and it should be a focused update. In the update function you can place all realtime, graphics, and input updating in an if statement checking if it is an focused update

}

 

foreach (Planet planet in GameInfo.planetList)

{

    if (planet != currentPlanet) //we don't want to update our currently active planet twice

    {

    planet.Update(GameTime gameTime, false) //Here we set the focused boolean parameter to false, which means that all these planets should be updated, but they should not process any input or any other realtime updating

    }

}

 


In your worldmaps update method you can check for input if a player is clicking a planet. If he does we set the game class' currentPlanet object to the object the player just clicked. After

setting the currentPlanet you should also call the planet objects initialize function, which should work similar to this:

- Load terrain and textures

- Create local lists for ships, buildings and so on from the global lists by checking if they are located on the currently active planet.

- Initialize any other assets you need such as effects, spritefonts, sounds.

 

Whenever you add a new ship or building or whatever, you should update both the local AND the global lists to avoid having to re-initialize the local lists, or avoid object states not being

saved after you leave the planet because you didn't update the global list.


For example if a ship is destroyed and you remove it from the local shiplist but not the global. The next time you leave and re-enter the planet, the ship would be there again because the

local list re-initializes from the global list, to avoid slow updating and drawing. Imagine if you would always loop through the global list when updating and drawing game objects, your

entire world might have over 40 000 objects while the current planet only has maybe 200. Why loop through 40 000 objects when you can limit it to 200?

 

An example of a planet update method:

 

public void Update(GameTime gameTime, bool Focused)

{

    if (Focused)

    {

    ProcessInput(gameTime);

    ProcessLocalAI(gameTime); //Method for processing the local ship / buildings AI, things like movement, fighting and so on depending on orders. If this was an unfocused update we would update the AI in a simpler maner, just checking if they are fighting, if so we simulate the fight. Check if a ship leaves the planet and should be drawn on the worldmap, check if a ship enters a planet, if a building is destroye /built and so on

 

    //...any other realtime processing that needs to be done

    }

     

    if (!Focused) //Here comes the updates that are done ONLY if the planet is not focused

    {

    ProcessLocalSimpleAI(gameTime);

    ProcessEvents(gameTime); //If things happen but we can not see them, we generally want to process them in a different way as it does not need to be visualized

    UpdateGameObjects(gameTime); //The same goes for our game objects. Maybe we want to update positions, ship and building healthpoints, check if ship leaves/enters planets and so on, but we do not need to visualize it so there is no need to calculate any accurate movement or anything. We did not have this method in the realtime updating, because in general these types of updates would be more integrated with camera movements and AI decisions and could not be processed by calling that one method.

    }

     

    //Here we continue with all updating that should always be done, no matter if it is a focused or unfocused update. Since I'm not digging deep into game mechanics I'm leaving this empty. After all it is all depending on how your game is designed how your updating should be handled.

}

 


 

Handling the drawing methods

Drawing is the easiest part in all this. You can set your game class' draw function to something similar to this:

 

if (currentPlanet == null && worldMap != null)

worldMap.Draw(gameTime, device, spriteBatch);

 

 

if (currentPlanet != null)

currentPlanet.Draw(gameTime, device);

 

if (currentOverlayMap != null)

currentOverlayMap.Draw(gameTime, device, spriteBatch);

 

if (hud != null)

hud.Draw(gameTime, device, spriteBatch);

 

if (currentGameScreen != null)

currentGameScreen.Draw(gameTime, device, spriteBatch);

 


Ok so first of all we draw the worldMap IF it is set and we do not have a active planet. Next we draw the planet, the overlaymap and the current game screen. We do it in this order because

the world map should always be the base. If we have nothing else focused, the world map should be displayed. Next we draw the planet, the overlaymap (used for viewing map without leaving

planet, for assigning ship orders and so on) should be drawn on top of the current planet. After that we draw the hud, and of course, game screens should be drawn on top of everything

(stats screens, info screens, main menus and so on)


Conclusion
I hope this was helpful in some way. Game designing is hard and there is no right way to do it. That's why I didn't go into much depth here, I simply made up a scenario and a possible

solution to make it work.

You should NOTE that if for example, we a active planet, AND a gamescreen or maybe the overlaymap, you need a way to tell your update methods if they should check for input or not.

Otherwise, if you for example are on the world map, and you open up the main menu to go into the options screen, and when you click the options button you also hit the screen coords of a

planet on the worldmap, then the game would load the planet you clicked. You could also easily end up with even more bizzare side-effects.

Writing a good state manager algorithm is very important if you are going to have layers of game states like we did here.
I will go further into that in another future tutorial. Hope this is enough for now.
Last Updated on Wednesday, 02 December 2009 15:29  

Polls

What game are you mostly looking forward to?
 

Who's Online

We have 1 guest online

Advertisement