Archive for the ‘ GameDev ’ Category

Colony Station

The first thing to do when starting a new game in DSS is to build your colony station. This station is central to your local empire, as it will provide the work force to build and staff your other stations and ships. You will be able to train workers and pilots out of the available population. This population grows over time if you provide it with the necessary commodities such as entertainment and health care. The higher the moral and health are, the faster it grows.

The station itself has 6 customizable district sockets. Each sockets can host a district, that has a direct effect on the station and population:

Residential District
Increases the station population limit. Comes in form of a pyramid and provides quality living space.
High Density Residential District
Increases the station population limit even more. Influenced by totalitarian architecture, provides crammed living space, but comes at the price of a decrease in morale.
Park District
Provides a small moral boost. Inspired by the classic concept of a greenhouse in space, encapsulated by an atmospheric bubble. Thereโ€™s a waterfall, some forest and a beach.

Several other districts are still in development, for instance: hospital will increase population health, academy will train higher tier professions, etc.

Also, as you progress in the game and unlock new technologies, you will be able to expand the colony station considerably to add new district sockets. Here’s a preview of how the station will grow:

So by the end of the game you should get a huge station that looks like a floating city in space. ๐Ÿ˜€

Creative Process:

The initial brief for the artist was as follows:

Composed of a central hull with 6 districts and 6 expansions with 6 districts each.
The central hull is ~800 meters in diameter and provides living space for colonist, basic education system and commodities to sustain a small population. There is also a corvette shipyard for tiny ships of no more than 20 meters.

The city of Atlantis(from stargate atlantis) provided a rough starting point for how to lay out the colony station. Core structures in the center and additional structures in the periphery.
Additionally, a hexagonal shape was deemed as useful for the districts, because it allows for a nice, compact arrangement, without the static feel a square would have.

So, the colonystation with its 6 expansions is essentially a city in space, or rather a blueprint for a city in space, because the player can build districts on it.
One of the first things to do, was to figure out how to arrange the expansions and districts accordingly. Although we are in 3D space, a planar arrangement was preferred to provide best visibility and allow to see things at a glance.


The third variant was chosen, as it is the most compact and expansions โ€œgrowโ€ most naturally.

Afterwards the central hull had to be worked out. The idea here was to have elements clearly separated by function. There should be an area for habitation, for education(training pilots, etc), a small shipyard, some part focused on engineering(life support systems, energy source etc) and finally 6 areas where a districts can be build upon.
Approved was the idea of a central ring fused with 6 hexagonal platforms at the outside and three vertical structures in the middle.
colonystation_concept

The ring and the platforms are used for habitation. The smallest tower is the shipyard. Opposite the bay opening is a medium sized tower, with elements inspired by Air Traffic Control towers. This one is also housing the education facilities. The tall, narrow structure is the engineering tower.

Home | Forum | IndieBd | Twitter

Still Alive

It’s been a long time since my last post so I’d figured I’d make a new video for your eyes to enjoy. A lot of new features are in, of which there is guns and corvette class ship dogfight behavior.
D.S.S. will feature epic space battles with tons of ships and lots of pew pew. So this is where i am in the development of such battles.

Pew pew pew! ๐Ÿ˜€

D.S.S. Fleet System

What I often find lacking in most strategy game is the presence of any sort of fleet management system. What I mean by that is a mechanism that allows the player to setup the unit’s positions within the fleet when they are in formation. Usually you would put ships with more defense up front and ships with a wider weapon range back. Also, if you have ships that buff/debuff other ships within some range, you would certainly want them to hold a specific position in the fleet.

I find it to play a very important role strategy-wise in my game. So I spent a lot of effort in making a fleet editor that would give the player full control while (hopefully) being easy to use.

Placing ships in three dimensions can be challenging but I think I found an elegant way to solve this. The player puts ships on a X-Y grid which he can move up and down the Z axis by ctrl+left click and dragging it. And there is a green cursor that shows how high the grid is from the origin.

So that’s it, hope you enjoyed my first video of D.S.S. ๐Ÿ˜€

Multi-threading my way

In D.S.S. I have to handle tons and tons of ships and projectiles in many star-systems. Consequently, if I want a decent framerate I’ll have to multi-process all this to take advantage of new multi-core CPUs.
So without further ado, here is how I did it. It’s actually a pretty standard way to do it. It’s just the simplest way I could think to implement it. I’ll be using common primitive like mutex, event and thread so I won’t go into details for these classes. I’m using FastDelegate library as well cause I just like it a lot.
The model is basically: queue a bunch of tasks (or jobs) and process them with several threads. The magic happens in 3 classes: JobQueue, MPWorker and MultiProcess.

JobQueue:
This one synchronizes job addition and retrieving. It really just acts as a synchronization primitive.

MPWorker:
this guy process job from the JobQueue. There are usually several of them spawned at initialization time. They literally fight each other to get and execute jobs. They are pretty good workers indeed.

MultiProcess just ties everything together.

So here goes a wall of code:
JobQueue:

class JobQueue{
public:
    JobQueue()
    : muiNbWorkingJob(0)
    , muiMaxSimultaneous(0){}
    void addJob(const fastdelegate::FastDelegate0<>& a){
        Mutex::Lock lock(mJobMutex);
        mAllDone.reset();
        mJobs.push_back(a);
    }
    fastdelegate::FastDelegate0<> retrieveNextJob(){
        Mutex::Lock lock(mJobMutex);
        if(mJobs.size()>0){
            fastdelegate::FastDelegate0<> job = mJobs.front();
            mJobs.pop_front();
            _InterlockedIncrement(&muiNbWorkingJob);
            updateMaxSimultanious();
            return job;
        } else{
            return nullptr;
        }
    }
    // called when a job is done
    void markJobDone(fastdelegate::FastDelegate0<>& a){
        Mutex::Lock lock(mJobMutex);
        // _InterlockedDecrement is used to force updating local variable 
        // with up-to-date variable changed by other thread
        // a volatile pointer would probably work as well.
        uint32 uiNbWorking = _InterlockedDecrement(&muiNbWorkingJob); 
        if(uiNbWorking == 0 && mJobs.size()==0 ){
            mAllDone.raise();
        }
    }
    // waits until all job are done
    void waitForAllDone(){
        mAllDone.wait();
    }
    uint32 getMaxSimultanious()const {return muiMaxSimultaneous;}
    void resetMaxSimultanious(){muiMaxSimultaneous=0;}
private:
    // prevent copying this class
    JobQueue(const JobQueue&);
    JobQueue& operator=(const JobQueue&);
    void updateMaxSimultanious(){
        if(muiNbWorkingJob>muiMaxSimultaneous) muiMaxSimultaneous=muiNbWorkingJob;
    }
    std::list< fastdelegate::FastDelegate0<> > mJobs;
    Mutex mJobMutex;
    long muiNbWorkingJob; // number of job currently executing at the moment
    Event mAllDone; // Event raised when all jobs have been processed
    uint32 muiMaxSimultaneous; // max number of simultaneous worker working at the same time. use for statistics
};

MPWorker

class MPWorker{
public:
    MPWorker(uint32 auiId, JobQueue& aJq)
        :muiId(auiId)
        ,mJobQueue(aJq) {
        mpThread = new Thread(fastdelegate::MakeDelegate(this,& MPWorker::workerFunc));
        mpThread->start();
    }
    ~MPWorker(){
        delete mpThread;
    }
    void workerFunc(){
        while(1){
            fastdelegate::FastDelegate0<> job = mJobQueue.retrieveNextJob();
            if(job){
                job();
                mJobQueue.markJobDone(job);
            }
        }
    }
    uint32 muiId; // don't really need this, it is just for debug purpose
    Thread * mpThread;
    JobQueue& mJobQueue; // the queue from which to get jobs
private:
    MPWorker(const MPWorker& a);
    MPWorker& operator=(const MPWorker& a);
};

MultiProcess

class MultiProcess{
public:
    MultiProcess()
        :mbWorkInSingleProcess(true){}
    // initialize system with number of desired workers
    void init(uint32 auiNbWroker){
        if(auiNbWroker==0){
            mbWorkInSingleProcess=true;
        } else {
            mbWorkInSingleProcess=false;
            for(uint32 i = 0; i < auiNbWroker; ++i){
                mWorkers.push_back( new MPWorker(i, mJobQueue));
            }
        }
    }
    ~MultiProcess(){
        for(uint32 i = 0; i < mWorkers.size(); ++i){
            delete mWorkers[i];
        }
    }
    void addJob(const fastdelegate::FastDelegate0<>& aJob){
        if(mbWorkInSingleProcess){
            aJob();
        } else {
            mJobQueue.addJob(aJob);
        }
    }

    // called when the user want all jobs to be processed
    void flush(){
        fastdelegate::FastDelegate0<> job = mJobQueue.retrieveNextJob();
        while(job){
            job();
            mJobQueue.markJobDone(job);
            job = mJobQueue.retrieveNextJob();
        }
        if(!mbWorkInSingleProcess)
            mJobQueue.waitForAllDone();
    }
    // some stats
    uint32 getMaxSimultaniousWorker()const {return mJobQueue.getMaxSimultanious();}
    void resetMaxSimultaniousWorker(){mJobQueue.resetMaxSimultanious();}
private:
    JobQueue mJobQueue;
    std::vector< MPWorker* > mWorkers;
    bool mbWorkInSingleProcess; // if work in single process, job are executed when added. otherwise they are put in the job queue.
    //prevent copying this class
    MultiProcess(const MultiProcess&a);
    MultiProcess& operator=(const MultiProcess&a);
};

Now to use it, do something like:

class MPUser{
public:
    void expensiveJob(){
        float fValue=0;
        for(uint32 i = 0; i < 50000; ++i){
            fValue+=rand()/(float) RAND_MAX;
        }
        printf("", fValue);
    }
    void use(){
        MultiProcess mp;
        mp.init(3);
        for(uint32 i = 0; i < 100; ++i){
            mp.addJob(fastdelegate::MakeDelegate(this, &MPUser::expensiveJob));
        }
        mp.flush();
    }
};

If you don’t know how much worker you should spawn, I suggest using the CPU number of processor – 1

    SYSTEM_INFO sysinfo;
    GetSystemInfo( &sysinfo );
    uint32 nbWorker = sysinfo.dwNumberOfProcessors-1;

Be aware that if your jobs are too small, the overhead of adding and getting job will be quite high. For instance, in D.S.S., I update whole star-systems in a job. Updating each ships with its own jobs would be terrible. Also, as ships usually interact only with other ships in the same star-system, I don’t have a lot of synchronization to handle.

Here is the full code with VS 2010 solution.

DSS news

I’ve been working hard on my game lately. Lots of new features are in, namely: save game, technology tree, ship ability tree,ย  galaxy view and freighter transport route. But I also worked on a major graphics revamp as you can see here:


There are new gfx assets like space stations, warp gate and some ships. New gfx feature like alpha support(yeah that one should have been done way long ago),ย  engine trail and sky box.

Next up are : Ai and combat

Also I finally decided how to name my game but I’m not going to say just yet. From now on I’ll refer to it as DSS.

Todo

I’m very forgetful so I tend to write every little things down for later reference. Over the years I learned to coop with that trait of mine in many ways. I even bought an Ipod touch so i can take notes and pictures of what i should remember. So it’s not surprising that my todo list got quite big and exhaustive over the ~4 months I’ve been working on my new project. But the problem is that I add a new item in the list and just never go back to do it. I just forget about my todo list… I’m that forgetful. So as an incentive to do my todo list items, I did this:

#define JOIN_STR2__(x) #x
#define JOIN_STR1__(x) JOIN_STR2__(x)
#define LOC_TODO __FILE__ "("JOIN_STR1__(__LINE__)") : Warning _TODO: "
#define TODO(x) __pragma(message(LOC_TODO x))

So when I think about something i should remember and actually do later I just write it down at the right place in the code like this:

TODO("Make this real");

So when I compile I get a warning message that look like:
Warning 110 warning _TODO: Make this real c:\p4\test\test.cpp 96

I like getting a warning message, It reminds me that I should fix it while I’m working in the same file.

Early screen shots

It’s been a while now since I’ve started working on my new project. There was a lot of foundation work that needed to be done, mostly in the graphics department. And I’m happy with what I have accomplished so far knowing that I have pretty much started this project from scratch 2 months ago.

Although I still need to do some graphic features, I am willing to share a few early screen shots.




The game concept comes from an idea I had long ago but never had time to develop. Hopefully, things will evolve like I planned.
The game has no name yet. I usually refer to it as “E.W.”. Although I have most of the production pipeline in place, it is still in pre-production.
It involves spaceships, a lot of pew pew and will put the emphasis on strategy.
I wish I could say more, but I’ld rather keep some surprises for later. ๐Ÿ™‚