OpenGL game
Vlastní skriptovací jazyk

První jednoduchý skript

zdroják ke stažení (3kB)

01.12.2005

Začneme opravdu jednoduchým skriptem, který do konzole vypíše toto

I am talking.
I am talking.

Proto si vytvoříme enumerátor:

enum EScriptOpCode
{
        K_OP_TALK,
        K_OP_END
};


Třída CInstruction


class CInstruction 
{
	EScriptOpCode  m_eCode;
public:
	CInstruction(EScriptOpCode _eCode) : m_eCode(_eCode){}		
	~CInstruction(){}

	EScriptOpCode GetCode() const         
	{ 
		return m_eCode; 
	}
};

Ukládá a vrací enumeratory skriptů
talk
a
end


Třída CScript


class CScript
{
	std::vector<CInstruction> m_vInstruction;
public:
	CScript(const std::vector<CInstruction>& _rvInstruction)
		: m_vInstruction(_rvInstruction){}		
	~CScript(){}
		
	const CInstruction* GetInstruction() const 
	{
		return &m_vInstruction[0]; 
	}
};


Ukládá a vrací pole instrukcí.

Třída CVirtualMachine


class CVirtualMachine
{
	/// useful abstractions
	/// pointers used as non-modifying dynamic references
	typedef const CScript* TScriptRef;
	typedef const CInstruction*  TInstrRef;

	std::vector<CScript> m_vScript;
	TScriptRef m_tScript;		/// current script
	TInstrRef m_tInstrRoot;		/// root instruction
	TInstrRef m_tInstrCurr;	    /// current instruction
	size_t m_uiNumScripts;		/// number of loaded scripts

	/// Add script to list and retrieve id
	size_t AddScript(const CScript& _rScript) 
	{
		m_vScript.push_back(_rScript); 
		return m_uiNumScripts++;
	}
	/// Set current script by id
	void SelectScript(size_t _uiScriptId) 
	{
		assert(_uiScriptId < m_uiNumScripts);  /// make sure the id is valid
		m_tScript = &m_vScript[_uiScriptId];
		m_tInstrRoot = m_tScript->GetInstruction();
	}
	
public:
	CVirtualMachine()
		: m_tScript(0), m_tInstrRoot(0), m_tInstrCurr(0), m_uiNumScripts(0){}		
	~CVirtualMachine(){}

	/// Execute script
	void Execute(size_t _uiScriptId);
	size_t Load(const CScript& _rkScript)
	{
		return AddScript(_rkScript); 
	}
};	


Načítá skripty do pole a vrací index.


size_t Load(const CScript& _rkScript)
{
	return AddScript(_rkScript); 
}


Potom za běhu engine volá funkci


void CVirtualMachine::Execute(size_t _uiScriptId)
{
	/// Select root script by script index
	SelectScript(_uiScriptId);	
	/// Set our iterator to the beginning       
	m_tInstrCurr = m_tInstrRoot;	
	while (m_tInstrCurr)
	{
		switch(m_tInstrCurr->GetCode())
		{
		case K_OP_TALK:
			std::cout << "I am talking." << std::endl;
			// Iterate
			++m_tInstrCurr;	
			break;
		case K_OP_END:
			/// Discontinue the loop
			m_tInstrCurr = 0;	
			break;
		}
	}
}


Která nastaví skript podle indexu
_uiScriptId


/// Set current script by id
void SelectScript(size_t _uiScriptId) 
{
	assert(_uiScriptId < m_uiNumScripts);  /// make sure the id is valid
	m_tScript = &m_vScript[_uiScriptId];
	m_tInstrRoot = m_tScript->GetInstruction();
}


Nastaví aktuální instrukci


/// Set our iterator to the beginning       
m_tInstrCurr = m_tInstrRoot


a pokud instrukce existuje


while (m_tInstrCurr)

získává a provádí skript


switch(m_tInstrCurr->GetCode())
{
case K_OP_TALK:
	std::cout << "I am talking." << std::endl;
	// Iterate
	++m_tInstrCurr;	
	break;
case K_OP_END:
	/// Discontinue the loop
	m_tInstrCurr = 0;	
	break;
}

Test skriptu

Při načítání scény:
Vytvoříme virtual machine VM

CVirtualMachine kVM;

Vytvoříme instrukce a skript

// build the script
vector<CInstruction> vInstr;
vInstr.push_back(CInstruction(K_OP_TALK));	// talk twice
vInstr.push_back(CInstruction(K_OP_TALK));	// talk twice
vInstr.push_back(CInstruction(K_OP_END));	// then end
CScript kScript(vInstr);

Načteme skript a získáme jeho index.

/// Load the script and save the id
size_t uiScriptId = kVM.Load(kScript);

Při běhu aplikace:
Předáváme VM index skriptu. Tento skript se aktivuje.

/// execute the script by its id
kVM.Execute(uiScriptId);



home / opengl game


Valid XHTML 1.0 Transitional