Jump to content


Basic action-response system


1 reply to this topic

#1 Almos

    Member

  • Members
  • PipPip
  • 99 posts

Posted 11 May 2006 - 12:09 PM

A prototype of system created with action-adventure game in mind. More specifically, for the "adventure" part. The idea came to me during a solo brainstorming session connected with walking around the perimeter of my room. It was a pitiable sight to behold. Be glad you didn't have to.

I wanted to create an easily extensible system, so that it would be easy to dynamically define new interactions for every object in the game world. First words that came to my mind were: structure, list and callback: each action is represented by a data structure holding an information about its name, callback, and some additional stuff, like for example animation played by the game engine when the action is being performed. For the prototype I stripped the structure down to the two basic elements: name and callback, and decided to use lua scripts instead of hard-coded callbacks. The basic concept was that an actor (called agens), which works as an "emitter" of action, performs the action on an object (patiens) which is the "receiver" of action. The program checks if the interaction by that name is available for it, and if it is, it fires the script defined for that action. To make it clearer, some code. First the header file:

#include <list>

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>


struct Action

{

    const char* name;

    const char* callback_script;

};



//the base for Agens and Patiens classes


class ActBase

{

    private:


    std::list<Action> AvailableActions;


    public:


    void Append(const char* name, const char* script);


    std::list<Action> GetList()

    {

        return AvailableActions;

    }

};


//action receiver


class Patiens: public ActBase

{

    private:


    lua_State* lVM;


    public:


    Patiens(lua_State* l)

    {

        this->lVM=l;

    }


    ~Patiens();


    void OnAction(Action act);


};

//action emitter

class Agens: public ActBase

{

    public:


    Agens();

    ~Agens();

    void Perform(const char* name, Patiens* pat);

};


The class structure sucks and I know it. However, the concept evolved when I was coding, so the final structure will probably mirror the concept in a more accurate manner. The implementation looks like that:

#include <iostream>

#include <list>

extern "C"

{

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>

}


#include "as.h"


//empty constructor and equally empty destructor for the Agens class

Agens::Agens()

{


}


Agens::~Agens()

{

}


Patiens::~Patiens()

{

}


// append an action to the list of actions that can be performed on the object


void ActBase::Append(const char* name, const char* script)

{

    Action act;

    act.name = name;

    act.callback_script = script;

    AvailableActions.push_back(act);

}


//check out if the action is available for an object. If yes, fire OnAction method

//and run the callback script


void Agens::Perform(const char* name, Patiens* pat)

{

    if (pat==NULL) return; //we don't like null pointers

    std::list<Action> list = pat->GetList();


    std::list<Action>::iterator i;


    for(i=list.begin(); i!=list.end(); i++)

    {

        if(i->name==name) pat->OnAction(*i);

        break;

    }


}



 void Patiens::OnAction(Action act)

{

    lua_dofile(lVM, act.callback_script);

}


int main()

{

    // create the lua virtual machine

    lua_State* mLVM;

    mLVM = lua_open();



    lua_baselibopen(mLVM);

    lua_iolibopen(mLVM);

    lua_strlibopen(mLVM);


    //create one instance of Agens, and one of the Patiens class


    Agens* agens = new Agens();

    Patiens* patiens = new Patiens(mLVM);


    patiens->Append("example","f:/lua-5.0/test/hello.lua");


    //perform two actions on patiens. Only one of them will provoke response.


    agens->Perform("example",patiens);

    agens->Perform("bad_example",patiens);




    // clean up after yourself, young man!

	delete agens;

	delete patiens;


	std::cout << std::endl << "That's all, folks!" << std::endl;


	lua_close(mLVM);


	return 0;

}



"as.h" stands for "action system" and refers to the header file I copied and pasted above. I've written the thing on WinXP, with Code::Blocks, compiled with Windows gcc port, and it ran fine. What's the point with posting it on Devmaster, you ask? For no other reason than your comments. What do you think of the system? Do you think it might be improved? Or should it be entirely discarded? Or should author of this post should abandon his interest in computer programming and spend the rest of his life waiting tables?

Thanks for reading this somewhat bloated and confusing post.
I want to make a game as good as Elder Scrolls oblivion with no programming, just point&click. If it's not possible, I want a team of programmers I'd be able to order around. After all, I'm a n00b.

#2 monjardin

    Senior Member

  • Members
  • PipPipPipPip
  • 1033 posts

Posted 11 May 2006 - 01:53 PM

I think your next step should be to provide context information for your actor and object to the lua script. You need a means of affecting the participants of the action when a lua "callback" is executed.
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users