Mega Demo Coding OOP style - viper/Serenity 1999 ( yes it's Y2K )

Hi fellow coders, since everyone it seems are contributing to the "Rift Diskmag" effort I thought I'd write a little tutor on coding demo's OOP style. I'm no expert on the subject but I thought I'd just share some of my ideas with you. You know the drill if you're pc blows up it's prob. you're fault and not mine.

Demos in C++ are you mad, too much overhead... ( sighed the foolish man ) Overhead is not the issue, most compilers these days have a fielday when it comes to c++

Well consider the following
If you have a nice standard interface for you're demos and you have more than one person working on the demo and parts then OOP is the way to go.
example.

                             /- part1
    (demo engine)  --/-- part2
                             \-- part3
                              \- part4

The person who coded the demo engine does'nt know how the groups members coded their parts but since we're using the a OOP model he doesn't need to know or care. All that matters is that the coders know how to interface with the demo and follow the rules set down but the engine coder.

Let's have a closer look.

    --part.h--
    class Part {
    	public:
            virtual void init() = 0;
            virtual void loop() = 0;
            virtual void render( int32 *) = 0;
    };

    --effect1.h--
    class Effect1 : public Part {
    	public:
            virtual void init()
    		{ // load all the graphics and tables };
            virtual void loop()
    		{ // calculate values };
            virtual void render( int32 *buffer)
    		{ // render all graphics to buffer };
    };

    --main.cpp--
    void main(void)
    {
    	// setup graphics & sounds
    	// get a pointer to the drawing surface/buffer = buffer;

    	effect1 sine_blob;

    	// preload all demo events;
    	sine_blob.init();

    	while ( !demo_end )
    	{
    		// check key events
    		sine_blob.loop();
    		sine_blob.render( buffer);
    	}
    }

As you can see from the above listings we have our parts inheriting the part class thus creating a standard interface for all the demo parts. Thus you can ask one coder to write let's say a sine_blob routine aka effect1 and he knows what the demoengine is only interested in the 3 virtual functions init, loop & render.

This is the easy way to get people to work together. You don't have to worry about coding crashing other code or strange things since all you're part code is in it's own class.
Nice and clean and you don't need to flog you're coders to focus.

But what if I have a demo with more than one part, wise ass? Well who has a demo with more than one part ?? ok well since everyone put their hands up I'll show you how I did it using scripting.

consider the following.

    --script.h--
    typedef struct {
    	int pattern;		// our music pattern
    	int row;		// our row
            void (*func)(void);	// pointer to the function we would like to call
            } script_t;

    script_t script[]={
    {       1, 1,	Part_intro },
    {	1, 5,	Show_picture },
    {	3, 4,	Part_3d },
    ..
    ..
    ..
    {    100, 2,    NULL}
    };

we change the above code as follow.

    --main.cpp--
    void main(void)
    {
    	// setup graphics & sounds
    	// get a pointer to the drawing surface/buffer = buffer;

    	effect1 sine_blob;
    	effect2 lens_part;
    	.
    	.
    	.
    	.

    	Part *active_part; 	// pointer to the active part

    	// preload all demo events;
    	sine_blob.init();
    	lens_part.init();
    	.
    	.
    	.

    	active_part = sine_blob;	// point us to the 1st part

    	while ( !demo_end )
    	{
    		// check key events
    		// check the script and execute the function if the music matches the script
    		// 	pos and pattern.

    		if ( active_part != NULL )
    		{
    			active_part->loop();
    			active_part->render( buffer);
    		}
    	}
    }

As you can see from the above example we have a pointer to our parts and we only reference the pointer with our loop and render functions. So how do we change the pointer to other parts ?
Well that's where the script comes in. In our main loopwe compare the music time to the script. If we find a match we execute that function pointed to in the script. It is this called function's job to change the pointer to the appropriate part.

example

    script_t script[]={
    {       1, 1,	Part_intro },
    {	1, 5,	Show_picture },
    {	3, 4,	Part_3d },
    ..
    ..
    ..
    {    100, 2,    NULL}
    };

    void Part_intro ()
    {
    	active_part = 	lens_part;
    }

    void Show_picture ()
    {
    	active_part = NULL; // no part is being called instead
    			    // display a picture
    	loadAndShowPic( buffer, "pic1.tga");
    }

    void Part_3d()
    {
    	active_part = lens3d_part;
    }

and so on.

As you may have noticed we changed the pointer to NULL in the show_picture function. We will have to check in our main loop for NULL pointers and ignore them. This is just a cheap way to display pics etc etc. You can of course make a part that displays pics.

    class ShowPic : public Part {
    	public:
            virtual void init() { // load the picture if possible };
            virtual void loop() { // do nuffing }
            virtual void render( int32 *buffer)
    		{ // render the pic to the screen };
    };

Let's face it, C++ has not been the best way to do things in the past but then again ignorance is bliss. C++ has almost come of age and things are looking up OOP wise for demos.

I hope you could make some kinda sens from my lucid ramblings.
I'm not the best person to explain things.

Enjoy you're coding and see you all at optimise 99.

viper/Serenity
vpr@quakclan.net

greetings go out to
caz, maverick, rawhed, deadpoet or was that deadpot, saurax, jahya, get-a-fix, zeroimpact, meeku, neuron, riot, AJ, Serenity, Atomic Warloks, Shunt, OO, SO