🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Shared: The Object

Published May 02, 2000
Advertisement
Workin' on 'Shared' now.

Shared is a base class (probably better described as a pattern) that I came up with quite a while ago for the 'new' games (eventually released as the Cosmi game pack). They were originally designed as a friendly abstraction for networked games, but it turns out that they were frightfully useful for separating the GUI from the game logic. It was certainly an example of an idea that outgrew its original vision, as I ended up pulling the network functionality out of the games, but I still used shared.

Come to think of it, I probably ought to think of a better name than 'Shared'. Doesn't do it justice.

How it originally worked was a 'shared object'. What it was was an object that was shared between multiple computers. If a computer wanted to change member data in the object, it simply had to change the data and call Update(), which would automatically stream the changes to the other computers, change their member data, and call the WasUpdated() function, informing them that they had changed. The games themselves built little token-passing mechanisms on top of this, so that there weren't lost updates.

Anyway, here's the public interface. It's based on the old version, but it's not much different.

class Shared


{



public:



Shared(ui8 ObjIndex);


~Shared();


void Update(void);







virtual void WasUpdated(void)=0;

virtual void Exchange()=0;











void ExchangeItem(i8 &rItem);


void ExchangeItem(ui8 &rItem);


void ExchangeItem(i16 &rItem);


void ExchangeItem(ui16 &rItem);


... // all primitive data types will have an associated Exchange();



















ui8 Index(void) { return MyIndex; }















// note: the following are stubbed out for now. They should be set

for networked apps


bool Networked() { return false; }


bool Primary() { return true; }












};

What was neat thing I found, though, was that by sharing an object with

itself (which was the plan for single player games), this makes a dandy class for state machines.

A sample state machine is the following. Gameinfo is derived from Shared,

and contains game-specific info. This is adapted from Wari, which is a simple two-player game:

void GameInfo::WasUpdated(void)


{ // this should look at the object and figure out what's going on



ui8 CommandOrg = Command;





switch(Command)


{



case CMD_1TOMOVE:


case CMD_2TOMOVE:



if (MyTurn()) // see if you are player 1 or 2 (always 1 if not networked)


{ // set up the move



[tell UI that it's now valid for the user to click the screen to

make a move]




































[if user clicks a cell, UI must set Command to CMD_1MOVED and call

Update()]






}


else if (!Networked())


{ // perform a computer move



Wait(); // show the wait cursor





[perform the math on the board to find the best move, storing it in LastMoveMade]





Wait(FALSE); // hide the wait cursor


Command = CMD_2MOVED; // signal that the computer's made his move










}


break;

























case CMD_1MOVED:


case CMD_2MOVED:


{ // apply the move to the board



MainWindow().MakeMove(LastMoveMade); // display the move just made

on the UI


if (!MainWindow().GameOverProcessing()) // check for a game over condition


{ // if no game over, tell the next player it's his turn



if (Command == CMD_1MOVED)



Command = CMD_2TOMOVE; // next player's turn





else



Command = CMD_1TOMOVE;












}










}


break;




















case CMD_NEWGAME:


{



MainWindow().NewGame(); // have the GUI set up a new game


if (Primary())


{ // flip a coin to see who goes first



if (Application::Random(2))



Command = CMD_1TOMOVE; // you won the toss!





else



Command = CMD_2TOMOVE; // lost the toss, computer goes first












}









}


break;









}










if (Command != CommandOrg) // there is a new command, signal it



Update();










}

The Exchange() function looks like this. . .

void GameInfo::Exchange(void)


{



ExchangeItem(Command);


ExchangeItem(LastMoveMade);






}

When you call Update(), it'll use this function to build a packet out of the items given. When the object receives a packet, it uses the same function to see what the items in the packet look like. In the old version, I had two different functions to stream the data in and out. I realized, though, that they were always the same except for the direction of the streaming. In the new version, I'll just put the object into 'send' or 'receive' mode depending on what's happening and use this function to make a packet from the data or to extract from the packet to the data..

Betcha didn't know that so much thought went into discount-rack games :)




















0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement