3D Othello

3D other involves creating a class to manage the game itself, interfacing it with the keyboard, and the graphics.

I added the class to the build system already under nebula/code/inc/vr/nothelloserver.h & nebula/code/src/vr/nothelloserver_main.cc & nebula/code/src/vr/nothelloserver_cmds.cc
.h is the include file.
main.cc is the main file where the game stuff should go
cmds.cc is where the interface to the scripting engine goes.

Interfacing with the Keyboard.

  1. Create your functions
  2. Create wrapper functions
  3. Setup the callback functions
  4. Keymap those to keys

Create your own functions

Create functions inside nothelloserver for the various interfaces you want with the keyboard.

So likely, MoveLeft, MoveRight,MoveUp,MoveDown,SelectSquare.

Add them to the .h file, and the main.cc, just n_printf something when they are called.

n_printf is identical to printf, except that it outputs to the console as well as stdout.

Create wrapper functions

For each function you created you need a static function to call it, this comes from a quirk of function pointers.

Calling a function inside a class requires the hidden this pointer, do call them from function pointers then you need to call out to a static function and pass it a void* with this in it, it then casts that over and calls the appropriate function. Then you get in a problem with arguments, but nebula extracts all of this nicely so dont worry about it. You can see lots of examples of this in most of the cmds.cc files, nent_cmds.cc is good for return types, the older nebula code includes examples of what it looks like without the macros.

A number of macros are defnied at the top of cmds.cc, these make it MUCH simpler and prettier to write these functions, also our functions dont take/return arguments so it is even simpler.

command( moveleft ) {

	self->MoveLeft();
}

Is all you need to write to define a wrapper for your functions.

Setup the callback

Next you need to tell the script enginge how to call your functions, this just amounts to calling a function and passing it it how your function is called, a unique identifier, and the function pointer.

clazz->AddCmd("v_moveleft_v", 'ML', moveleft );

The first part tells the engine how to call the function, its name is moveleft, it returns nothing, and takes nothing.

'ML' is the functions identifier, this is a long long char or some other strange declaration, which allows it to hold multiple characters (up to 4) inside on data type, just use a short character string to describe it. It really does not matter so long as they are unique.

moveleft is a function pointer to the static function created above, just pass the name you put it command above.

Once this is working you should be able to go into the console, create an othelloserver, sel it, and run moveleft which should call the function.

Keymappings

Add the following to go.tcl
new nothelloserver /othello
This will create your class at startup.

In keymappings.tcl link keys up to the function required to interact with your class

  .map keyb0:b.down "script:/othello.moveleft"

links the b key to the moveleft function

Interfacing with the graphics.

  1. Create a piece in /node
  2. Add a pointer to it
  3. Clone it into the game
  4. Place it

Creating the piece in /node

To show pieces add them to the visual tree, the best way to do this would be to clone them out of /node.

In go.tcl add some commands to create a piece in /node/piece.

Declare a smart pointer to that piece

Declare a nAutoRef<n3DNode> piece in the .h.
Construct it with piece(kernelServer, this )
In Initialize: piece = "/node/piece"

These declares a smart pointer, that points to the object at /node/piece.

Clone it and Place It.

n3DNode* newPiece = (n3DNode*) piece->Clone("/game/vis/piece0");

Will make a copy of the piece and put it in the visual tree, note that you will need to increment the index as they must have unique names. Clone returns a pointer to the object just created, so you can then call.

newPiece->Txyz(x,y,z) will then move the piece to the appropriate spot.

Misc

How to choose between colors? You "could" use channels ,but this is a long process, the quickest way is to paint onside of the piece one color, and the other side another, and then just flip it over like it is done in the real game.

Animating the flip? create a nIpolNode as the child of /node/piece, connect it to rx. Add to key1fs to it, the first should be the time when the flip starts, the second should be when the flip should end.