• entries
    743
  • comments
    1924
  • views
    580455

Project update and some real life stuff

Sign in to follow this  

78 views

Project stuff first.

I've got the basic audio resource management system working now. First I need to explain how the general resource system has been implemented.

The engine creates an instance of the SharedResources class, which contains resources that persist throughout the entire run of the program. This includes things like the global vertex buffer, the render texture, anything that is shared between game modes.

Each mode then creates an instance of its own resource class e.g. GameResources, LogoResources etc. These take and store a reference to the SharedResources instance so that the shared resources can be accessed via the mode's own resource instance.

E.g:


void f()
{
GameRes.Shared.Buffer.Begin(D3DLOCK_DISCARD);
Graphics.SetTexture(GameRes.RenderTex);
}


The point of all this is to allow RAII to take care of releasing mode-specific resources when the mode is destroyed while leaving the shared resources alone.

For sounds, I wanted to keep all the currently loaded sounds in one place so that I could easily change the global volume, pause them, mute them etc.

So I added the AudioManager to the shared resources, but gave it a couple of private methods to Push() and Pop() resources. Push() stores the current size of the ptr_vector that stores the buffers into an internal stack. Pop() releases all of the resources up to the index on top of the stack then pops the stack.

(ptr_vector is just a template class that provides a std::vector interface (uses a std::vector internally) but deletes the pointers when they are removed or the ptr_vector is destroyed. I know boost has this but I still haven't got round to looking at boost and my ptr_vector is only about 20 lines of code. No excuse, I know, but there you go. Shame on me. [smile])


class AudioManager
{
private:
ptr_vector B;
std::stack S;

void Push();
void Pop();

public:
AudioManager(){ }
};

void AudioManager::Push()
{
S.push(B.size());
}

void AudioManager::Pop()
{
B.clear_from(S.top()); // deletes and removes everything from index to end
S.pop();
}


I then created an AudioScopeProxy class that AudioManager has as a friend. This just calls Push() in its constructor and Pop() in its destructor, storing a pointer to the AudioManager so the destructor can function.


class AudioManager
{
private:
friend class AudioScopeProxy;

// snip
};

class AudioScopeProxy
{
private:
AudioManager *M;

public:
AudioScopeProxy(AudioManager &Manager) : M(&Manager) { M->Push(); }
~AudioScopeProxy(){ M->Pop(); }
};


I then give each mode-specific resource class an AudioScopeProxy member and pass it the AudioManager from the shared resource instance in the mode resource class constructor:


class GameResources
{
private:
AudioScopeProxy AudioScope;

public:
GameResources(SharedResources &Shared) : Shared(Shared),AudioScope(Shared.Audio) { }

SharedResources &Shared;
};


Now I can create audio resources within GameResource's acquisition stage and they are automatically freed when the instance is destroyed, but all of the actual buffers are located inside the AudioManager.

The next step was to sort out buffer duplicates. DirectSound allows you to cheaply duplicate a buffer so that two or more buffers share the same sample memory but can be played and manipulated independantly.

My sound file tags each sample with a string name which is stored by the AudioManager against each sample, along with a flag to say whether it has been claimed, initially set to false.

I typedef size_t to AudioHandle and provide a method AudioHandle::AudioManager GetUniqueHandle(const std::string &Name).

This searches through the ptr_vector until it finds the correct name. It then checks to see if it has been claimed yet. If not, it sets its claimed flag to true and returns its index. If it has, it pushes a new buffer into the ptr_vector, duplicating from the original, sets that ones claimed flag to true and returns the new index.

So, for example, Squishy's arms can look a bit like:


class Arm
{
private:
AudioHandle FireEffect;

public:
Arm(GameResources &G){ FireEffect=G.Shared.Audio.GetUniqueHandle("fire"); }

void MakeSound(GameResources &G){ G.Shared.Audio[FireEffect].Play(); }
};


I can now create multiple instances of the arm and each automatically gets its own copy of the relevant buffer, duplicated where needed and playable independantly but all sharing the same sample memory.

It's a nice system and I like it. Unfortunately you can't apply effects to buffers that you also duplicate so effects are out.

In other shock news, brace yourselves but...water has been dropped from the game.

Reasons are:

  • The physics of underwater was a total hack and didn't work properly.
  • Since I can't use runtime effects on sounds, the sound system is never going to sound good underwater.
  • I liked it more for the graphical effect than what it added to gameplay - this is rarely good.


  • Reason one broke the cardinal rule of Squishy - if it can't be easily accomplished with Box2D, don't do it. I've imposed that limitation on this project since moment one, and it has proven to be a very interesting approach as I've said before.

    --------------------------------------

    Real life stuff.

    The job that I posted that I hadn't got a week or so ago rang me up out of the blue at work yesterday afternoon to say that the person they had offered it to had had a better offer and they want to see me again.

    It was all a bit of a shock.

    Weirdly, I had today off work anyway as I have another interview at lunchtime so I was able to arrange to go in to see the original job people later this afternoon. So now I have two interviews today. [smile]

    Funny how things work out.

    In terms of whether I should be leaving my current job, my reasoning is as follows: if I leave, it is possible I will regret it. If I get another offer and choose to stay where I am, I can guarantee I will regret it.

    It is never easy leaving a job voluntarily but I also firmly believe that you have to take some risks at times and that when a company tries to use threats of disciplinary action to stop people discussing problems, it is time to move on.

    Probably more later. Thanks for reading.

    --------------------------------------

    YAY! [smile][smile][smile]

    I got the job I was really keen on. Nothing official in writing yet so I can't give my notice just yet, but all just formalities now.

    I'm over the moon.

    I've done some more on the game as well but I'm a bit too excited to talk about it at the moment.
    Sign in to follow this  


    1 Comment


    Recommended Comments

    No doubt, when a company tries to keep everyone on the hush hush, it's time to leave. That's just the spark before the blaze of a world of problems. Hopefully you get the job you're looking for. :)

    Share this comment


    Link to comment

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now