Nebula2探秘13-输入管理器nInputServer

Nebula2探秘13-输入管理器nInputServer

happykevins文

本节将介绍如何创建和使用nInputServer来检测输入设备的状态及事件。
在创建InputServer之前首先要创建一个Windows窗口,这项工作我们已经在第11节中完成。您可能会注意到本节的代码结构与第11节非常相似,只是多出了创建nInputServer的代码和一个DumpInput函数(用来检测用户输入,并将结果输出到控制台)。

与创建其他Server一样,只需要在KernelServer中将它new出来然后Open一下即可;但是目前的Nebula2版本并没有提供对应的Close函数,所以用户并不需要为销毁InputServer做什么,下面是创建inputserver及建立事件映射的代码:

/// 创建nInputServer
nInputServer * input = (nInputServer * )ks -> New( " ndi8server " , " /sys/servers/input " );
input
-> Open();

/// ----------------------------------------------------------------------------
/// +添加按键映射
/// @1.可以在脚本中配置
/// @2.可以通过设备的映射名来索取设备并检测设备状态
/// @3.可以将脚本函数与设备直接帮定,这样在设备产生事件时会自动调用相关函数
input -> BeginMap();
input
-> Map( " keyb0:space.down " , " reset " );
input
-> Map( " relmouse0:btn0.pressed " , " look " );
input
-> Map( " relmouse0:+x " , " right " );
input
-> EndMap();
/// -添加按键映射
/// ----------------------------------------------------------------------------

nInputServer提供了一下3种处理设备事件的方式:
1.传统的遍历消息列表并转发或处理的模式。
2.由用户逻辑轮训事件。
3.由InputServer主动出发用户感兴趣的事件。
其中第2、3种的使用方式基本一样,只不过2是用户为事件起一个别名,而3是用户直接把脚本函数注册到事件上而已。
下面的函数DumpInput展示了如何使用第1种方式遍历并处理事件列表:

/// ----------------------------------------------------------------------------
/// +输入测试
///
void DumpInput()
{
/// 遍历事件列表,并将事件详细信息分类输出到控制台
for (nInputEvent * inputEvent = nInputServer::Instance() -> FirstEvent();
inputEvent
!= NULL;
inputEvent
= nInputServer::Instance() -> NextEvent(inputEvent))
{
/// 根据事件的DeviceID区分设备
switch (inputEvent -> GetDeviceId())
{
case N_INPUT_MOUSE( 0 ):
printf(
" MouseEventDetected![BTN:%i] " ,inputEvent -> GetButton());
switch (inputEvent -> GetType())
{
case N_INPUT_MOUSE_MOVE:
printf(
" [MouseMove] " );
break ;

case N_INPUT_BUTTON_DOWN:
printf(
" [ButtonDown] " );
break ;

case N_INPUT_BUTTON_UP:
printf(
" [ButtonUp] " );
break ;
}
break ;
case N_INPUT_KEYBOARD( 0 ):
printf(
" KeyEventDetected![KEY:%i] " ,inputEvent -> GetKey());
switch (inputEvent -> GetType())
{
case N_INPUT_KEY_DOWN:
printf(
" [KeyDown] " );
break ;

case N_INPUT_KEY_UP:
printf(
" [KeyUp] " );
break ;

case N_INPUT_KEY_CHAR:
printf(
" [CharEvent] " );
break ;
}
break ;
}
printf(
" " );
}
}
///
/// -输入测试
/// ----------------------------------------------------------------------------

另外在游戏主循环每一帧结束的位置都要调用nInputServer::FlushEvents()方法以确保事件列表被清除,否则即使已经被处理过的事件也会一直保留在列表中。

下面是完整的程序代码:

/****************************************************************************/
/*Nebula2-Tutorial13*/
/*InputServer*/
/*author:happykevins*/
/****************************************************************************/

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


//nebula2includes
#include"kernel/nkernelserver.h"
#include
"kernel/nfileserver2.h"
#include
"input/ninputserver.h"
#include
"gfx2/nd3d9server.h"

//Tutorial工具库:一些通用的宏定义
#include"../NebulaUtils/nutildefs.h"

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

///
----------------------------------------------------------------------------
///+链接库


#pragmacomment(lib,"wsock32.lib")

#pragmacomment(lib,"dxguid.lib")
#pragmacomment(lib,"dxerr9.lib")
#pragmacomment(lib,"d3d9.lib")
#pragmacomment(lib,"d3dx9d.lib")
#pragmacomment(lib,"dinput8.lib")

#pragmacomment(lib,"d_nkernel.lib")
#pragmacomment(lib,"d_nnebula.lib")
#pragmacomment(lib,"d_ndirect3d9.lib")
#pragmacomment(lib,"d_ndinput8.lib")

/// -链接库
///
----------------------------------------------------------------------------

///
----------------------------------------------------------------------------
///+声明使用的Nebula2Package&Module

nNebulaUseModule(nresource);
nNebulaUseModule(nresourceserver);
nNebulaUseModule(nfont2);
nNebulaUseModule(nmesh2);
nNebulaUseModule(nmesharray);
nNebulaUseModule(nshader2);
nNebulaUseModule(ntexture2);
nNebulaUseModule(ngfxserver2);
nNebulaUseModule(ninputserver);
nNebulaUsePackage(ndirect3d9);
nNebulaUsePackage(ndinput8);
///
-声明使用的Nebula2Package&Module
///----------------------------------------------------------------------------


nKernelServer
*ks= NULL;
nGfxServer2
*gfx2=
NULL;

///
----------------------------------------------------------------------------
///
+初始化环境,创建需要的Server
///
bool
InitApp()
{
///创建KernelServer

ks= n_new(nKernelServer);

///
----------------------------------------------------------------------------
///+向KernelServer中添加Package&Module

nNebulaAddModule(nresource);
nNebulaAddModule(nresourceserver);
nNebulaAddModule(nfont2);
nNebulaAddModule(nmesh2);
nNebulaAddModule(nmesharray);
nNebulaAddModule(nshader2);
nNebulaAddModule(ntexture2);
nNebulaAddModule(ngfxserver2);
nNebulaAddModule(ninputserver);
ks
->
AddPackage(ndirect3d9);
ks
->
AddPackage(ndinput8);
///
+向KernelServer中添加Package&Module
///
----------------------------------------------------------------------------

///创建D3D9Server

gfx2=(nGfxServer2*)ks->New("nd3d9server","/sys/servers/gfx" );
///创建ResourceServer

nResourceServer*res=(nResourceServer*)ks->New("nresourceserver","/sys/servers/resource" );

///获得FileServer设置shaders的路径

nFileServer2*file=(nFileServer2*)ks->Lookup("sys/servers/file2" );
///
@note:这是启动d3d9server必须的
///因为d3d9server在初始化时会访问"shaders:shape.fx",用它来控制绘制调试图形的渲染状态

file->SetAssign("shaders","bin:../../datafiles/shaders/fixed" );

///初始化显示模式

nDisplayMode2mode;
mode.SetXPos(
0
);
mode.SetYPos(
0
);
mode.SetWidth(
320
);
mode.SetHeight(
200
);
///将显示模式应用到d3d9server

gfx2-> SetDisplayMode(mode);

///启动d3d9server

gfx2-> OpenDisplay();


///创建nInputServer

nInputServer*input=(nInputServer*)ks->New("ndi8server","/sys/servers/input" );
input
->
Open();

///
----------------------------------------------------------------------------
///
+添加按键映射
///
@1.可以在脚本中配置
///
@2.可以通过设备的映射名来索取设备并检测设备状态
///@3.可以将脚本函数与设备直接帮定,这样在设备产生事件时会自动调用相关函数

input-> BeginMap();
input
->Map("keyb0:space.down","reset"
);
input
->Map("relmouse0:btn0.pressed","look"
);
input
->Map("relmouse0:+x","right"
);
input
->
EndMap();
///
-添加按键映射
///----------------------------------------------------------------------------


returntrue ;
}
///

/// +初始化环境,创建需要的Server
///
----------------------------------------------------------------------------

///
----------------------------------------------------------------------------
///
+退出程序,清理资源
///
bool
CloseApp()
{
///关闭d3d9server

gfx2-> CloseDisplay();

///销毁KernelServer

n_delete(ks);

returntrue
;
}
///

/// -退出程序,清理资源
///
----------------------------------------------------------------------------

///
----------------------------------------------------------------------------
///
+输入测试
///
void
DumpInput()
{
///遍历事件列表,并将事件详细信息分类输出到控制台

for(nInputEvent*inputEvent=nInputServer::Instance()-> FirstEvent();
inputEvent
!=
NULL;
inputEvent
=nInputServer::Instance()->
NextEvent(inputEvent))
{
///根据事件的DeviceID区分设备

switch(inputEvent-> GetDeviceId())
{
caseN_INPUT_MOUSE(0
):
printf(
"MouseEventDetected![BTN:%i]",inputEvent->
GetButton());
switch(inputEvent->
GetType())
{
case
N_INPUT_MOUSE_MOVE:
printf(
"[MouseMove]"
);
break
;

case
N_INPUT_BUTTON_DOWN:
printf(
"[ButtonDown]"
);
break
;

case
N_INPUT_BUTTON_UP:
printf(
"[ButtonUp]"
);
break
;
}
break
;
caseN_INPUT_KEYBOARD(0
):
printf(
"KeyEventDetected![KEY:%i]",inputEvent->
GetKey());
switch(inputEvent->
GetType())
{
case
N_INPUT_KEY_DOWN:
printf(
"[KeyDown]"
);
break
;

case
N_INPUT_KEY_UP:
printf(
"[KeyUp]"
);
break
;

case
N_INPUT_KEY_CHAR:
printf(
"[CharEvent]"
);
break
;
}
break
;
}
printf(
" "
);
}
}
///

/// -输入测试
///
----------------------------------------------------------------------------

///
----------------------------------------------------------------------------
///+Application

intmain(intargc,constchar** argv)
{
///初始化Application

if(! InitApp())
{
n_error(
"程序初始化失败! "
);
return0
;
}

///这里相当于游戏循环,gfx2->Trigger()将触发win32的消息泵

while(gfx2-> Trigger())
{
///一帧开始

gfx2-> BeginFrame();
///绘制场景开始

if(gfx2-> BeginScene())
{
///设置渲染缓冲区

gfx2->Clear(nGfxServer2::AllBuffers,0.2f,0.2f,0.8f,1.0f,0,0 );
///绘制场景结束

gfx2-> EndScene();
///显示场景

gfx2-> PresentScene();
}
///一帧结束

gfx2-> EndFrame();

///检测输入事件,并输出到控制台

DumpInput();

///清空输入事件列表

nInputServer::Instance()-> FlushEvents();

n_sleep(
0.01f
);
}

///释放资源

if(! CloseApp())
{
n_error(
"释放资源失败! "
);
return0
;
}

return0
;
}
///
-Application
///
----------------------------------------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值