科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Nebula2探秘13-输入管理器nInputServer

Nebula2探秘13-输入管理器nInputServer

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本节将介绍如何创建和使用nInputServer来检测输入设备的状态及事件.

作者:happykevins 来源:CSDN 2008年3月25日

关键字: 管理器 输入 Nebula2 游戏 Linux

  • 评论
  • 分享微博
  • 分享邮件
本节将介绍如何创建和使用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(
"MouseEvent Detected! [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(
"KeyEvent Detected! [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 - Tutorial 13                                                    */
/*  Input Server                                                            */
/*  author: happykevins                                                        */
/****************************************************************************/

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

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

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


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


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

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

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

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


#pragma comment(lib, "wsock32.lib")

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

#pragma comment(lib, "d_nkernel.lib")
#pragma comment(lib, "d_nnebula.lib")
#pragma comment(lib, "d_ndirect3d9.lib")
#pragma comment(lib, "d_ndinput8.lib")

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

///
----------------------------------------------------------------------------
/// +声明使用的Nebula2 Package&Module

nNebulaUseModule(nresource);
nNebulaUseModule(nresourceserver);
nNebulaUseModule(nfont2);
nNebulaUseModule(nmesh2);
nNebulaUseModule(nmesharray);
nNebulaUseModule(nshader2);
nNebulaUseModule(ntexture2);
nNebulaUseModule(ngfxserver2);
nNebulaUseModule(ninputserver);
nNebulaUsePackage(ndirect3d9);
nNebulaUsePackage(ndinput8);
///
 -声明使用的Nebula2 Package&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");

    
/// 初始化显示模式

    nDisplayMode2 mode;
    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();
    
///
 -添加按键映射
    
///----------------------------------------------------------------------------


    
return true;
}
///

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

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

    gfx2->CloseDisplay();

    
/// 销毁KernelServer

    n_delete(ks);

    
return true
;
}
///

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

///
----------------------------------------------------------------------------
///
 +输入测试
///
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(
"MouseEvent Detected! [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(
"KeyEvent Detected! [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

int main(int argc, const char** argv)
{
    
/// 初始化Application

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

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

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

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

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

            gfx2->Clear(nGfxServer2::AllBuffers, 0.2f0.2f0.8f1.0f00);
            
/// 绘制场景结束

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

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

        gfx2->EndFrame();

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

        DumpInput();

        
/// 清空输入事件列表

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

        n_sleep(
0.01f
);
    }
    
    
/// 释放资源

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

    
return 0
;
}
///
 -Application
///
----------------------------------------------------------------------------

 

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章