Hi,
I've been writing a simple 2D RPG in C++ and I'm gettnig a bit stuck again on how to organise certain things.
Firstly I have a question about RPG's typically handle what happens when a player moves from one area to the next. Is the area they are leaving kept in memory in any form? At first I thought they couldn't be, since surely you would simply run out of memory as the player keeps playing. But if the area is no longer in memory then it can't be updated and this could cause some problems.
Say for example an enemy wizard casts a defensive buff and an enterprising player decides to run to another area while it's duration runs out. Or say the player is being pursued and runs to another area, in a case where there's no reason why he couldn't be followed. It seems like I would need to keep track of what's going on in the other area. Or maybe not, I've thought that it's possible I could handle all these cases by having some special logic when areas are opened and closed, e.g I could examine all temporary spell effects and increment their durations by the time passed since the area was closed. And perhaps do things like randomise the positions of wandering creatures to make things look more dynamic. I can't quite figure out if all cases can be handled like this.
Could the alternative of keeping the area in memory work? I could release any resources needed to render the area, and reduce the frequency of AI updates, forget about collision detection and so on. And then perhaps organise my areas into sets based on the travel time between them, so areas can be closed when the player moves from one set to another.
When an area does have to be closed I plan to serialize it to the players save game folder, so in future my resource cache for area files will look there first for a modified file and load it if it exists. I don't think it's worth trying to split my area class into it's static and dynamic components and only saving the latter, since I think the latter dominate in terms of size.
As well as this issue of static and dynamic I have a general problem thinking about initialisation and serialisation. My game entities need access to a lot of resources and systems, stuff to do with scripts, sprites and sounds etc. I do this by dependency injection when the entities are constructed. Also the objects themselves need to be registered with a manager type class and assigned an ID as they are created. All of this works fine when creating a new object but seems to be awkard when loading them, particularly if you want to keep your loading and saving methods symmetric, which is very easy with boost serialization.
I've thought about splitting my entities into two, so I have say a CreatureProperties class which stores all the serializable state information about a creature, and a Creature class which inherits from Entity and deals with the dynamic and game logic aspects. A container of properties is serialized with the area file and the entities are created and registered etc when the area is initialised. Does this seem reasonable/necessary?
Appreciate any thoughts.
RPG areas and objects.
I think a common method for games with very large open worlds is that you will usually only have a small subset loaded at one time. If your areas are defined as square shapes of a certain size you can imagine having nine of them loaded at one time with the middle one being the area the player is actually in.
As for your problem of enemies chasing you through multiple areas I think you need to decouple the enemies from the area and rather having some other object update relevant enemies where the enemies can have a reference to the area they are in if needed. That way you can keep a list of enemies nearby and enemies that the player is interacting with at any one time independent from where they are in the world.
As for your problem of enemies chasing you through multiple areas I think you need to decouple the enemies from the area and rather having some other object update relevant enemies where the enemies can have a reference to the area they are in if needed. That way you can keep a list of enemies nearby and enemies that the player is interacting with at any one time independent from where they are in the world.
Quote:Original post by Somnia
Firstly I have a question about RPG's typically handle what happens when a player moves from one area to the next. Is the area they are leaving kept in memory in any form? At first I thought they couldn't be, since surely you would simply run out of memory as the player keeps playing. But if the area is no longer in memory then it can't be updated and this could cause some problems.
Depends how big the area is. Some games keep the whole world in memory all the time.
Other games just keep the current area in memory. They may not update other areas at all.
Quote:Say for example an enemy wizard casts a defensive buff and an enterprising player decides to run to another area while it's duration runs out. Or say the player is being pursued and runs to another area, in a case where there's no reason why he couldn't be followed. It seems like I would need to keep track of what's going on in the other area.
Who says you have to update NPCs based on which area they're in? You could just update any relevant NPCs, regardless of which geographical position they exist at.
Maybe that's inconvenient if your updating involves moving around the environment. So, consider updating spell effects regardless of area.
Or, stop tracking spells by manually counting them down. Track them by attaching an expiration time. If the spell lasts 10 minutes and you leave the area and come back 11 minutes later, the game will see that the spell has -1 minutes of duration left and will remove it.
Quote:Or maybe not, I've thought that it's possible I could handle all these cases by having some special logic when areas are opened and closed, e.g I could examine all temporary spell effects and increment their durations by the time passed since the area was closed.
You don't need special case logic. You never need to iterate through spells changing their durations - the current time minus the casting time is how long the spell has existed for and the end time minus the current time is how long it has left to run. No updates (except to find the current time) necessary.
Quote:Could the alternative of keeping the area in memory work? I could release any resources needed to render the area, and reduce the frequency of AI updates, forget about collision detection and so on.
Certainly. Your rendering information should be separate from the rest of it anyway.
Quote:When an area does have to be closed I plan to serialize it to the players save game folder, so in future my resource cache for area files will look there first for a modified file and load it if it exists. I don't think it's worth trying to split my area class into it's static and dynamic components and only saving the latter, since I think the latter dominate in terms of size.
I find that very surprising, but it depends on your game. In most modern games the textures for a single entity alone may well be larger than a lot of the dynamic data you store about it.
You'll also regret this if you need to patch your data later and need to go through everybody's cache files as well. I'm not just talking about when the game is finished, but during development.
Do yourself a favour now and make sure you have a clear distinction between static data and dynamic data, at the code level, and at the serialisation level.
Quote:As well as this issue of static and dynamic I have a general problem thinking about initialisation and serialisation. [...] All of this works fine when creating a new object but seems to be awkard when loading them, particularly if you want to keep your loading and saving methods symmetric, which is very easy with boost serialization.
Loading and saving typically cannot be symmetrical, since the saving routine knows exactly which item it is saving, whereas the loading routine typically has to read part of the data to know what it's meant to be loading in.
But if you want more help on this issue you're going to have to say something more specific than "[it] seems to be awkward".
Quote:I've thought about splitting my entities into two, so I have say a CreatureProperties class which stores all the serializable state information about a creature, and a Creature class which inherits from Entity and deals with the dynamic and game logic aspects.
Surely it's the dynamic stuff you need to serialise?
In all my RPG-like games I divide the creature data up like so:
CreatureType - this defines the characteristics of types of generic creatures and individual unique creatures. One instance might be for goblins, one might be for dragons, one might be for Gandalf, etc. Properties within include the maximum health value, the 3D model or 2D sprite set used to render it, a list of susceptibilities and immunities to various spells, etc. The data here is defined at load time, and it can usually be held entirely in memory. I never need to modify it during normal gameplay nor write it to disk.
CreatureInstance - this defines an individual instance (or entity, if you prefer), and contains a reference to precisely one CreatureType. It contains properties such as current health, current position, a personal name, spells and other effects currently affecting the creature, etc. Some of these values are initialised based on values read from the associated CreatureType. (eg. the current health is set to the creaturetype's maximum health.) Others are initialised based on calling methods on the CreatureType (eg. generating a name for this instance might be done by calling a script attached to the associated creature type.) All this data changes during the course of gameplay and is written out as part of a save game, as long as the creature exists.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement