Third Party Command Tutorial 1 - [2]

Byungil Jeong

bijeong@evl.uic.edu

This second tutorial shows you how to implement a simple FSM as a DLL using Visual C++ and how to use it in DBPro. Since a DLL can hold data between each calls from DBPro, we can store the state information of our objects in a DLL and retrieve it whenever we want. This means that we can locate the AI part of our game in a DLL and control our objects in DBPro by just retrieving the state information from the DLL. For this tutorial, I made a FSM to control a moving sphere in DBPro according to key inputs. It is a simple example which shows you can implement game AI entirely as a DLL.

1. creating your DLL functions

a. Open Visual C++ 6.0 and select NEW, choose Win32 Dynamic-Link Library, call your project “FSM” and click OK.

b. Select 'Create a SIMPLE DLL Project'.

c. In FileView, double click FSM files, then Source Files, then FSM.cpp.

d. Add the following below #include “stdafx.h”:

// indicating following function will be exported to other executables

#define MYCOMMAND __declspec ( dllexport ) 

// moving states

#define GO_UP   1
#define GO_DOWN 2
#define GO_LEFT 3
#define GO_RIGHT 4

// rotation states

#define CW 11  // clock-wise
#define CCW 12 // couter clock-wise

// key inputs

#define KEY_RIGHT 21
#define KEY_LEFT 22

e. Add the following below DllMain().

// state variables

int m_stat, r_stat, next_r_stat;
int count;

// initialize state variables

MYCOMMAND void init_states(void)
{
    m_stat = GO_UP;   
    r_stat = next_r_stat = CW;
    count = 0;
}

// change moving direction

void change_state()
{
    switch(m_stat) {
    case GO_UP :
              if (r_stat == CW)
                        m_stat = GO_RIGHT;
              else
                        m_stat = GO_LEFT;
              break;
    case GO_DOWN :
              if (r_stat == CW)
                        m_stat = GO_LEFT;
              else
                        m_stat = GO_RIGHT;
              break;
    case GO_LEFT :
             if (r_stat == CW)
                       m_stat = GO_UP;
             else
                        m_stat = GO_DOWN;
              break;
    case GO_RIGHT :
             if (r_stat == CW)
                        m_stat = GO_DOWN;
              else
                        m_stat = GO_UP;
              break;
    }
}

// find next direction of rotation

MYCOMMAND void change_rotation(int key)
{  
    switch(m_stat) {
    case GO_UP :
              if (key == KEY_RIGHT)
                        next_r_stat = CW;
              else if (key == KEY_LEFT)
                        next_r_stat = CCW;
              break;
    case GO_DOWN :
              if (key == KEY_RIGHT)
                        next_r_stat = CCW;
              else if (key == KEY_LEFT)
                        next_r_stat = CW;
              break;
    case GO_LEFT :
              if (key == KEY_RIGHT) {
                        if (r_stat == CW) // reverse rotation direction
                                   next_r_stat = CCW;
                        else
                                   next_r_stat = CW;
              }
            else if (key == KEY_LEFT)  // keep rotation direction
                        next_r_stat = r_stat;
              break;
    case GO_RIGHT :
              if (key == KEY_LEFT) {
                        if (r_stat == CW)  // reverse rotation direction
                                   next_r_stat = CCW;
                        else
                                  next_r_stat = CW;
              }
              else if (key == KEY_RIGHT)  // keep rotation direction
                        next_r_stat = r_stat;
              break;
    }
}

// retrieve state

MYCOMMAND int get_state(void)
{
    count++;

    // every 300 access change the moving direction of sphere

    if (count == 300) {
              r_stat = next_r_stat; // change of rotation direction
              change_state(); // change of moving direction
              count = 0;
    }
    return m_stat;
}

f. Change of moving state is simple. But, in case of rotation, direction can be reversed several times when we press left or right key, because DBPro can take it unexpected number of times even though we think that we just press it once. So I introduced an additional state variable, next_m_stat, and change rotation direction just before change of moving direction.

g. Press F7 to compile your DLL.

2. creating your DLL string table

A DLL string table informs DBPro which commands the DLL has and which function is associated with each command.

a. Click INSERT from the Menu, then RESOURCE.

b. Select STRING TABLE to highlight it and then click NEW to create a new string table

c. Double click the highlighted box under ID and then click in the caption box where we will type out our command:

INIT FSM%0%?init_states@@YAXXZ

d. Type out the second and third command under first command in the same way

CHANGE ROTATION%L%?change_rotation@@YAXH@Z%int
GET STATE[%L%?get_state@@YAHXZ

e. Save this resource file in your project directory assigning file name as ‘FSM.rc’.

f. Now select the PROJECT menu and click ADD TO PROJECT and then FILES. Select ‘FSM.rc’ and click OK. To make sure, click F7 to compile your DLL again. It will now contain a string table describing your first command.

3. testing your commands in DBPro

a. You can find your DLL file(FSM.dll) in debug directory or release directory under your project directory according to your compile mode.

b. Copy your DLL file to plug-in user folder of DBPro. The default path to this folder is ‘C:\Program Files\Dark Basic Software\Dark Basic Professional\Compiler\plugins-user’.

c. Launch DBPro and type out the following:


REMSTART

 ## move states
  GO_UP : 1
  GO_DOWN : 2
  GO_LEFT : 3
  GO_RIGHT : 4
 ## key value
  KEY_RIGHT : 21
  KEY_LEFT : 22
REMEND

make object sphere 1, 10

position object 1, -15,-15,100

INIT FSM

do
  IF RIGHTKEY() = 1 THEN CHANGE ROTATION 21
  IF LEFTKEY() = 1 THEN CHANGE ROTATION 22

  SELECT GET STATE()
     CASE 1 : MOVE OBJECT UP 1, 0.1 : ENDCASE
     CASE 2 : MOVE OBJECT DOWN 1, 0.1 : ENDCASE
     CASE 3 : MOVE OBJECT LEFT 1, 0.1 : ENDCASE
     CASE 4 : MOVE OBJECT RIGHT 1, 0.1 : ENDCASE
  ENDSELECT
loop
sync

d. You can see the role of this DBPro code just takes key inputs and moves a sphere according to the state stored in DLL.

e.  Press F5 to run the program and see a moving sphere. At first, it moves in the order of Up, RIGHT, DOWN, LEFT(clock wise). You can change the direction of rotation by pressing LEFT or RIGHT arrow key. Each key has different meaning according to moving direction of the sphere. When the sphere goes up, left key change the rotation direction to CCW, right key to CW. When the sphere goes down, the change is revesed ( left key : CW, right key : CCW). When the sphere goes left or right, pressing the key which has reverse direction to the moving direction reverses the rotation direction.