game directory structure

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Seven
Posts: 1030
Joined: Mon Nov 14, 2005 2:03 pm

game directory structure

Post by Seven »

code to find the current directory and build a list of referenced directories.

in app.h, define stringc variables for all of the needed directories
in my case, i use some defines to make it easier to read

Code: Select all

 
    #define ADD_VARIABLE_SETGET(x,y)    private : x m_##y; public : virtual void set##y(x value) { m_##y = value; } virtual x get##y() { return m_##y; }    
 
        // game resource directory structure
        ADD_VARIABLE_SET2GET(stringc,WorkingDirectory);
        ADD_VARIABLE_SETGET(stringc,GameDataDirectory);
        ADD_VARIABLE_SETGET(stringc,GameSaveDirectory);
        ADD_VARIABLE_SETGET(stringc,MediaDirectory);
        ADD_VARIABLE_SETGET(stringc,ObjectsDirectory);
        ADD_VARIABLE_SETGET(stringc,PrefabDirectory);
        ADD_VARIABLE_SETGET(stringc,ActionTableDirectory);
 
somewhere (for me in the createApp() function)

Code: Select all

 
        // setup the directory structure
        int drive;
        char path[_MAX_PATH];
        drive = _getdrive();
        if( _getdcwd( drive, path, _MAX_PATH ) != NULL ) setWorkingDirectory(path);
 

Code: Select all

 
    // setup the directory paths
    void CSApplication::setWorkingDirectory(stringc path)
    {
        path.replace("\\","/");
        m_WorkingDirectory  = path;
        m_GameDataDirectory = path + stringc("/GameData/");
        m_GameSaveDirectory = path + stringc("/SaveGames/");
        m_MediaDirectory    = path + stringc("/Media/");
        m_ObjectsDirectory  = path + stringc("/CSObjects/");
        m_PrefabDirectory   = path + stringc("/Prefabs/");
        m_ActionTableDirectory  = path + stringc("/ActionTables/");
 
                // log all of the directories to the logger
        CS_LOG("settting working directory structure");
        CS_LOG2(" Working Directory - ",getWorkingDirectory());
        CS_LOG2(" Game Data Directory - ",getGameDataDirectory());
        CS_LOG2(" Save Data Directory - ",getGameSaveDirectory());
        CS_LOG2(" Media Directory - ",getMediaDirectory());
        CS_LOG2(" Objects Directory - ",getObjectsDirectory());
        CS_LOG2(" Prefab Directory - ",getPrefabDirectory());
        CS_LOG2(" Action Table Directory - ",getActionTableDirectory());
    }
 

so what we have done is define the directory variables and created simple set/get functions for each.
then we created the setWorkingDirectory(path) function which adds the working directory to each sub directory
and stores that new string.

now we need to be able to use just the base filename (for saving the levels) OR
use the long filename to load the file

Code: Select all

 
    #define CLIPTOMEDIAFILENAME(x) CLIPSTRING(x,getMediaDirectory())
    #define MEDIAFILENAME(x) stringc(getMediaDirectory()+x)
    #define CLIPTOACTIOTABLEFILENAME(x) CLIPSTRING(x,getActionTableDirectory())
    #define ACTIONTABLEFILENAME(x) stringc(getActionTableDirectory()+x)
    #define CLIPTOGAMEDATAFILENAME(x) CLIPSTRING(x,getGameDataDirectory())
    #define GAMEDATAFILENAME(x) stringc(getGameDataDirectory()+x)
    #define CLIPTOGAMESAVEFILENAME(x) CLIPSTRING(x,getGameSaveDirectory())
    #define GAMESAVEFILENAME(x) stringc(getGameSaveDirectory()+x)
    #define CLIPTOOBJECTSFILENAME(x) CLIPSTRING(x,getObjectsDirectory())
    #define OBJECTSFILENAME(x) stringc(getObjectsDirectory()+x)
    #define CLIPTOPREFABFILENAME(x) CLIPSTRING(x,getPreFabDirectory())
    #define PREFABFILENAME(x) stringc(getPrefabDirectory()+x)
 
    stringc CLIPSTRING(stringc s,stringc s2)
    {
        s.make_lower();
        s2.make_lower();
        stringc temp(s);
        temp.remove(s2.c_str());
        return temp;
    }
 


now, anytime we want to load an actor file, we simply use it like this

Code: Select all

 
..
old way : IAnimatedMesh* mesh = getSmgr()->getMesh("media/mymodel.x");
..
new way : IAnimatedMesh* mesh = getSmgr()->getMesh(MEDIAFILENAME("mymodel.x"));
 
this allows us to rearrange the directories as we wish without going through and changing all of the filenames.
Last edited by Seven on Tue Oct 01, 2013 11:06 pm, edited 1 time in total.
Seven
Posts: 1030
Joined: Mon Nov 14, 2005 2:03 pm

Re: game directory structure

Post by Seven »

the level save game data file might look like this.
note that the guplin object has an actorfilename = "3dfoin/guplin/guplin/realm crafter/gobinarc/goblin180.b3d"
and an actiontable filename of "guplin.actiontable"

Code: Select all

 
<?xml version="1.0"?>
<CSOBJECT TYPE="CSO_Terrain">
    <attributes>
        <string name="Name" value="CSO_Terrain" />
        <bool name="Dead" value="false" />
        <int name="Id" value="721" />
        <vector3d name="Position" value="0.672363, 0.000000, -1.318848" />
        <vector3d name="PositionOffset" value="400.000000, 0.000000, 0.000000" />
        <vector3d name="BBOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Rotation" value="0.000000, -0.000000, 0.000000" />
        <vector3d name="RotationOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Scale" value="400.000000, 1.000000, 400.000000" />
        <vector3d name="BaseScale" value="0.000000, 0.000000, 0.000000" />
        <bool name="DebugObject" value="false" />
        <string name="ActorFileName" value="default" />
        <string name="TextureFileName" value="default" />
        <float name="Mass" value="0.000000" />
        <float name="ReverseLight" value="0.000000" />
    </attributes>
 
</CSOBJECT>
 
<CSOBJECT TYPE="CSO_Diablo_Fire">
    <attributes>
        <string name="Name" value="CSDiablo_Fire" />
        <bool name="Dead" value="false" />
        <int name="Id" value="726" />
        <vector3d name="Position" value="4828.555664, 295.948608, 4914.139160" />
        <vector3d name="PositionOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="BBOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Rotation" value="0.000000, -0.000000, 0.000000" />
        <vector3d name="RotationOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Scale" value="101.900352, 101.900352, 101.900352" />
        <vector3d name="BaseScale" value="0.000000, 0.000000, 0.000000" />
        <bool name="DebugObject" value="false" />
        <string name="ActorFileName" value="default" />
        <string name="TextureFileName" value="default" />
        <float name="Mass" value="0.000000" />
        <float name="ReverseLight" value="0.000000" />
    </attributes>
 
</CSOBJECT>
 
<CSOBJECT TYPE="CSO_Diablo_Guplin">
    <attributes>
        <string name="Name" value="CSO_DiabloCharacter" />
        <bool name="Dead" value="false" />
        <int name="Id" value="712" />
        <vector3d name="Position" value="3550.239502, 207.846741, 4709.424805" />
        <vector3d name="PositionOffset" value="0.000000, -180.819977, 0.000000" />
        <vector3d name="BBOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Rotation" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="RotationOffset" value="0.000000, 0.000000, 0.000000" />
        <vector3d name="Scale" value="2.000000, 2.000000, 2.000000" />
        <vector3d name="BaseScale" value="0.000000, 0.000000, 0.000000" />
        <bool name="DebugObject" value="false" />
        <string name="ActorFileName" value="3dfoin/guplin/guplin/realm crafter/gobinarc/goblin180.b3d" />
        <string name="TextureFileName" value="default" />
        <float name="Mass" value="0.000000" />
        <float name="ReverseLight" value="0.000000" />
        <string name="ActionTableFileName" value="guplin.actiontable" />
    </attributes>
 
</CSOBJECT>
 

when saving / loading the level, these filenames are made longer / shorter as needed

Code: Select all

 
    void CSObject::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)
    {
        out->addString("Name",getName().c_str());
        out->addBool("Dead",getDead());
        out->addInt("Id",getId());
        out->addVector3d("Position",getPosition());
        out->addVector3d("PositionOffset",getPositionOffset());
        out->addVector3d("BBOffset",getBBOffset());
        out->addVector3d("Rotation",getRotation());
        out->addVector3d("RotationOffset",getRotationOffset());
        out->addVector3d("Scale",getScale());
        out->addVector3d("BaseScale",getBaseScale());
        out->addBool("DebugObject",getDebugObject());
        out->addString("ActorFileName",CLIPTOMEDIAFILENAME(getActorFileName()).c_str());
        out->addString("TextureFileName",CLIPTOMEDIAFILENAME(getTextureFileName()).c_str());
        out->addFloat("Mass",getMass());
        out->addFloat("ReverseLight",getReverseLight());
    }
 
    void CSObject::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
    {
        CS_LOG("CSObject::deserialize()");
 
        m_Name = in->getAttributeAsString("Name"); CS_LOG(getName());
        m_Dead = in->getAttributeAsBool("Dead");
        m_Id = in->getAttributeAsInt("Id");
        m_Position = in->getAttributeAsVector3d("Position");
        m_PositionOffset = in->getAttributeAsVector3d("PositionOffset");
        m_BBOffset = in->getAttributeAsVector3d("BBOffset");
        m_Rotation = in->getAttributeAsVector3d("Rotation");
        m_RotationOffset = in->getAttributeAsVector3d("RotationOffset");
        m_Scale = in->getAttributeAsVector3d("Scale");
        m_BaseScale = in->getAttributeAsVector3d("BaseScale");
        m_DebugObject = in->getAttributeAsBool("DebugObject");
        m_ActorFileName = MEDIAFILENAME(in->getAttributeAsString("ActorFileName"));
        m_TextureFileName = MEDIAFILENAME(in->getAttributeAsString("TextureFileName"));
        m_Mass = in->getAttributeAsFloat("Mass");
        m_Mass = in->getAttributeAsFloat("ReverseLight");
    }
 

I can now rearrange the folders however I want without 'correcting' each filename in each file by simply changing the subfolder in the CSApplication::setWorkingDirectory(path) function.

next step : store folder structure in xml file and load the directory names when the app is created, making the entire system editable without recompiling.

anyhow, back to the shadows. Though someone might be interested in it...................

Seven
Seven
Posts: 1030
Joined: Mon Nov 14, 2005 2:03 pm

Re: game directory structure

Post by Seven »

trying a new method for directory structures......

simple map<> that holds the directory structure and a few functions to add / get directory names.

Code: Select all

 
        // game resource directory structure
        map<stringc, stringc> m_Directories;
        
                // remember the starting working directory
                stringc m_WorkingDirectory; 
                stringc getWorkingDirectory() { return m_WorkingDirectory; } 
                void setWorkingDirecotry(stringc wd);
 
        // the game directory structure
        void registerDirectory(stringc dirName, stringc path);
        stringc getDirectory(stringc dirName);
 

Code: Select all

 
    void CSApplication::registerDirectory(stringc dirName, stringc path)
    {
        // if the directory exists, delete it
        map<stringc, stringc>::Node *node = m_Directories.find(dirName);
        if (node) m_Directories.remove(node);
 
        // add the directory to the map
        m_Directories.insert(dirName, path);
    }
 
    stringc CSApplication::getDirectory(stringc dirName)
    {
        stringc path("./");
        map<stringc, stringc>::Node *node = m_Directories.find(dirName);
        if (node) path = node->getValue();
        return path;
    }
 
    // setup the directory paths
    void CSApplication::setWorkingDirectory(stringc path)
    {
        // replace all of the slashes to the needed style
        path.replace("\\", "/");
 
        // register the directory names
        CS_LOG("setting the working directory structure");
        registerDirectory("WorkingDirectory", path);
        registerDirectory("GameDataDirectory", path + stringc("/GameData/"));
        registerDirectory("GameSaveDirectory", path + stringc("/SaveGames/"));
        registerDirectory("MediaDirectory", path + stringc("/Media/"));
        registerDirectory("ObjectsDirectory", path + stringc("/CSObjects/"));
        registerDirectory("PrefabDirectory", path + stringc("/Prefabs/"));
        registerDirectory("ActionTableDirectory", path + stringc("/ActionTables/"));
        registerDirectory("SoundDirectory", path + stringc("/media/Sound/"));
 
        CS_LOG2(" Working Directory - ", getDirectory("WorkingDirectory"));
        CS_LOG2(" Game Data Directory - ", getDirectory("GameDataDirectory"));
        CS_LOG2(" Save Data Directory - ", getDirectory("GameSaveDirectory"));
        CS_LOG2(" Media Directory - ", getDirectory("MediaDirectory"));
        CS_LOG2(" Objects Directory - ", getDirectory("ObjectsDirectory"));
        CS_LOG2(" Prefab Directory - ", getDirectory("PrefabDirectory"));
        CS_LOG2(" Action Table Directory - ", getDirectory("ActionTableDirectory"));
    }
 
Seven
Posts: 1030
Joined: Mon Nov 14, 2005 2:03 pm

Re: game directory structure

Post by Seven »

and code to use it

Code: Select all

 
    void CSObject::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)
    {
                // filenames are stored in the level without directory information
        out->addString(     "ActorFileName",    getActorFileName().c_str());          i.e. "dwarf.x"
        out->addString(     "TextureFileName",  getTextureFileName().c_str());      i.e. "drawf.jpg" 
    }
 
    void CSObject::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
    {
        m_ActorFileName = in->getAttributeAsString("ActorFileName");             i.e. "dawrf.x"
        m_TextureFileName   = in->getAttributeAsString("TextureFileName");         i.e. "dwarf.jpg" 
    }
 

Code: Select all

 
         #define MEDIAPATH(x) stringc(getDirectory("MediaDirectory") + ##x).c_str()
         #define CLIPPEDMEDIAPATH(x) stringc ( stringc(stringc(x).make_lower()).remove( stringc(getApplication()->getDirectory("MediaDirectory").make_lower())))
 
        // when loading an actor or texture, add the mediapath to the filename
    IAnimatedMesh* mesh = getSmgr()->getMesh(MEDIAPATH(getActorFileName()));    i.e. "c:\programming\mygame\media\assets\dwarf\dwarf.x"
 
       // when getting a filename from an IGUIFileOpen* dialog, clip the mediath path off
       IGUIFileOpen* fp = getGui()->createFileOpenDialog()
       stringc filename(fp->getFilename());                                     i.e. "c:\programming\mygame\media\assets\dwarf\dwarf.x"
       object->setActorFileName(CLIPPEDMEDIAPATH(filename));    i.e. "dwarf.x" because we removed "c:\programming\mygame\media\assets\dwarf\"
simple to setup and use, this allows us to move media assets to any folder and have the executable reference them correctly.
Post Reply