Nebula2探秘10-Signal System

阅读更多

Nebula2探秘10-Signal System

happykevins文

使用Nebula2信号系统的目的:

Nebula2的信号系统主要功能是对象间的消息传递。
由于消息的发出者和接收者是在运行时动态邦定的,所以用这种方式传递消息并不会增加程序的耦合度。
另外Nebula2还提供了一个SignalServer用于实现延时消息。

Nebula2信号系统主要包含以下几个类:
nSignal:
继承自nCmdProto类,用于标识一个信号,并描述信号回调函数的原形
nSignalRegistry:
包含多个nSignal的集合;nClass继承自此类;因此可以推测出信号是与类
邦定的,要使Nebula类型支持产生信号,我们首先要向该类注册信号
nSignalBinding:
封装了信号接收者及其回调函数,用于向信号发出者注册
nSignalBindingSet:
包含多个nSignalBinding的集合
nSignalEmitter:
信号发生器,nObject继承自此类;因此所有的Nebula对象都支持发出信号
的功能,前提是你注册了信号
nSignalServer:
这其实是独立于信号系统的一个附加功能,主要是实现了相应延时信号

Nebula2信号系统的使用方法:

Nebula2的信号系统支持Native代码和脚本两种途径的传递,下面简单介绍通过脚本途径的使用。
首先需要实现一个用于产生信号的Emtter类,Emitter就是一个普通的继承自nObject的Nebula2类型,只是在初始化命令的函数中添加了信号(nSignal)。
然后我们需要实现一个Receiver类,Receiver类也是一个继承自nObject的普通Nebula2脚本类,可以将Receiver的脚本指令向Emitter中感兴趣的信号注册,这样在Emitter产生信号时就会向注册的Receiver广播消息了;需要注意的是在Receiver向Emitter注册时需要保证Receiver的回调函数与Emitter的信号的函数原形保持一致。

Nebula2引擎的Bug:
需要改正一个Nebula2的Bug,在nargs.h的第276行加上代码:
this->type = Type::String;
原来的代码由于缺少这句话,在nArgs从va_list复制String类型参数时会丢失类型信息,所以在信号传递过程中如果使用String类型参数的话Nebula2就会出错。

下面是Emitter的代码:

/* ************************************************************************** */
/* Nebula2-Tutorial10 */
/* Nebula2SignalSystem */
/* author:happykevins */
/* ************************************************************************** */

/// Emitter.h
#pragma once
#include
" kernel/nroot.h "
#include
" signals/nsignal.h "

class Emitter: public nRoot
{
/// @note
/// 为了支持信号系统,在类的实现中不需要添加任何代码
/// 只需在Emitter对应的nClass中注册信号即可
/// 注册信号的工作一般在初始化脚本指令的函数(n_initcmds)中完成
};

/// Emitter.cpp
#include " Emitter.h "
#include
" kernel/nkernelserver.h "
#include
" ../NebulaUtils/nutildefs.h "

nNebulaScriptModule(Emitter,emitter,
" nroot " );

void nNebulaScriptInitCmds(emitter)(nClass * cls)
{
/// 在这里添加信号
/// 注册信号始需要指出信号对应回调函数的原形以及信号的ID
cls -> BeginSignals( 1 );
cls
-> AddSignal( " v_sig1_s " , ' SIG1 ' );
cls
-> EndSignals();
}

下面是Receiver的代码:

/* ************************************************************************** */
/* Nebula2-Tutorial10 */
/* Nebula2SignalSystem */
/* author:happykevins */
/* ************************************************************************** */

/// Receiver.h
#pragma once
#include
" kernel/nroot.h "

class Receiver: public nRoot
{
public :
void Print( const char * str)
{
n_printf(
" %s " ,str);
}
};

/// Receiver.cpp
#include " Receiver.h "
#include
" kernel/nkernelserver.h "
#include
" ../NebulaUtils/nutildefs.h "

nNebulaScriptModule(Receiver,receiver,
" nroot " );

static void n_print( void * o,nCmd * cmd);

void nNebulaScriptInitCmds(receiver)(nClass * cl)
{
/// 为Emitter的回调添加脚本函数
/// 信号系统也是通过脚本函数来传递消息
/// 脚本函数的需要与Emitter对应的信号保持一致
cl -> BeginCmds();
cl
-> AddCmd( " v_print_s " , ' PRNT ' ,n_print);
cl
-> EndCmds();
}

static void n_print( void * o,nCmd * cmd)
{
Receiver
* slf = (Receiver * )o;
slf
-> Print(cmd -> In() -> GetS());
}

下面是使用信号系统的范例代码:

/* ************************************************************************** */
/* Nebula2-Tutorial10 */
/* Nebula2SignalSystem */
/* author:happykevins */
/* ************************************************************************** */

/// ----------------------------------------------------------------------------
/// +必要头文件

// nebula2includes
#include " kernel/nkernelserver.h "
#include
" kernel/ntimeserver.h "
#include
" signals/nsignalserver.h "
#include
" ../NebulaUtils/nutildefs.h "

#include
" Emitter.h "
#include
" Receiver.h "

/// -必要头文件
/// ----------------------------------------------------------------------------



/// ----------------------------------------------------------------------------
/// +声明使用的Nebula2Package&Module
nNebulaUseModule(emitter);
nNebulaUseModule(receiver);
/// -声明使用的Nebula2Package&Module
/// ----------------------------------------------------------------------------

/// ----------------------------------------------------------------------------
/// +Application
int main( int argc, const char ** argv)
{
/// 创建KernelServer
nKernelServer * ks = n_new(nKernelServer);

nNebulaAddModule(emitter);
nNebulaAddModule(receiver);

/// 创建SignalServer
nSignalServer * signals = (nSignalServer * )ks -> New( " nsignalserver " , " /sys/servers/signals " );

/// 创建信号发生器
Emitter * emit = (Emitter * )ks -> New( " emitter " , " /usr/signals/emitter " );
/// 创建信号接收器
Receiver * rec = (Receiver * )ks -> New( " receiver " , " /usr/signals/receiver " );

/// 将信号接收器邦定到信号发生器指定的信号
emit -> BindSignal( ' SIG1 ' ,rec, ' PRNT ' , 0 , true );

/// 发出立即信号
emit -> EmitSignal( ' SIG1 ' , " EmitSignalSynchronized! " );

/// 发出延迟信号(5秒后执行)
emit -> PostSignal( 5.0f , ' SIG1 ' , " EmitSignalAsynchronized! " );

n_printf(
" *****WaitAsynchronizedSignal***** " );

/// 等待延迟信号
double time = 0 ;
while (time <= 8.0f )
{
signals
-> Trigger(nTimeServer::Instance() -> GetFrameTime());
n_sleep(
0.2f );
time
+= 0.2f ;
}

n_printf(
" *****PressAnyKey!***** " );

/// 销毁KernelServer
n_delete(ks);

getchar();
return 0 ;
}
/// -Application
/// ----------------------------------------------------------------------------

你可能感兴趣的:(脚本)