Nebula2探秘15-Simple Application  Framework

happykevins文 

         在经历了前14章的学习之后,本章将介绍一个简单的Nebula2应用程序框架nAppFrame。 nAppFrame可以说是nApplication的最简化版本,去掉了状态机和所有不必要的Packages和Servers。 nAppFrame的代码简单明了,易于使用,可以是省去每次重新创建Nebula2程序繁杂而枯燥的活动。

          以下的示例代码就应用了nAppFrame,并挂载了Render2D和Render3D两个函数,Render3D什么 事情都没做,读者有兴趣的话可以扩展该例子代码,例如显示个3D模型或骨骼动画之类的东东, 当然这些内容我将在以后章节中介绍,请大家继续关注Nebula2探秘哦:)

开始贴代码,nAppFrame的代码:


/****************************************************************************/

/*    Nebula2 - Tutorial nAppFrame                                            */

/*  A Simple Program Framework                                                */

/*  author: happykevins                                                        */

/****************************************************************************/

#pragma once


// 关闭讨厌的类型检查warning

#pragma warning(disable: 4244 4267)


#include "kernel/nkernelserver.h"

#include "kernel/nroot.h"

#include "kernel/nautoref.h"

#include "gfx2/ndisplaymode2.h"

#include "gfx2/ncamera2.h"

#include "tools/nmayacamcontrol.h"

#include "tools/nnodelist.h"


class nScriptServer;

class nGfxServer2;

class nInputServer;

class nConServer;

class nResourceServer;

class nSceneServer;

class nVariableServer;

class nAnimationServer;

class nParticleServer;

class nVideoServer;

class nGuiServer;

class nShadowServer2;

class nAudioServer3;

class nPrefServer;

class nLocaleServer;


// 

// class nAppFrame

// 仿照napplication制作的一个Nebula2应用程序框架,对初始化和运行做了减化

// 只开启我认为必要的服务

//

class nAppFrame : public nRoot

{

public:

    typedef void (*nFunc) (void);


    nAppFrame();

    ~nAppFrame();

    

    /// 初始化Nebula2引擎

    bool OpenNebula();

    /// 关闭Nebula2引擎

    bool CloseNebula();

    /// 进入Nebula2引擎的主循环

    void RunNebula();


    /// 用户可重载的初始化方法(在OpenNebula的最后被调用)

    virtual bool ClientOpen() {return true;}

    /// 用户可重载的关闭方法(在CloseNebula之前被调用)

    virtual bool ClientClose() {return true;}


    /// 在这里添加3D渲染代码

    virtual void OnRender3D();

    /// 在这里添加2D渲染代码

    virtual void OnRender2D();

    /// 在这里添加游戏逻辑代码

    virtual void OnFrame();


    /// Kernel Server

    static nKernelServer* ks;


    /// OnFrame Function Hook

    nFunc m_fpOnFrame;

    /// OnRender3D Function Hook

    nFunc m_fpOnRender3D;

    /// OnRender2D Function Hook

    nFunc m_fpOnRender2D;


    /// nNode节点列表

    nNodeList m_nodes;


protected:


    /// 摄像机控制代码(有默认实现,用户可重载)

    virtual void OnCameraControll();


    /// Nebula2启动标志

    bool isOpen;


    /// Servers

    nAutoRef<nScriptServer>     refScriptServer;

    nAutoRef<nGfxServer2>       refGfxServer;

    nAutoRef<nInputServer>      refInputServer;

    nAutoRef<nConServer>        refConServer;

    nAutoRef<nResourceServer>   refResourceServer;

    nAutoRef<nSceneServer>      refSceneServer;

    nAutoRef<nVariableServer>   refVariableServer;

    nAutoRef<nGuiServer>        refGuiServer;

    nAutoRef<nShadowServer2>    refShadowServer;

    nAutoRef<nParticleServer>   refParticleServer;

    nAutoRef<nAnimationServer>  refAnimationServer;


    //nAutoRef<nVideoServer>      refVideoServer;

    //nAutoRef<nAudioServer3>     refAudioServer;

    //nAutoRef<nPrefServer>       refPrefServer;

    //nAutoRef<nLocaleServer>     refLocaleServer;


    /// Camera Controll

    nDisplayMode2 display;

    nCamera2 camera;

    matrix44 view;

    nMayaCamControl m_ccam;

};


/// nappframe.cpp


#include "nappframe.h"

#include "nutildefs.h"


#include "kernel/nfileserver2.h"

#include "kernel/ntimeserver.h"

#include "kernel/nscriptserver.h"

#include "gfx2/ngfxserver2.h"

#include "input/ninputserver.h"

#include "misc/nconserver.h"

#include "resource/nresourceserver.h"

#include "scene/nsceneserver.h"

#include "variable/nvariableserver.h"

#include "anim2/nanimationserver.h"

#include "particle/nparticleserver.h"

#include "video/nvideoserver.h"

#include "gui/nguiserver.h"

#include "kernel/nremoteserver.h"

#include "audio3/naudioserver3.h"

#include "misc/nprefserver.h"

#include "locale/nlocaleserver.h"

#include "shadow2/nshadowserver2.h"


nNebulaUsePackage(nnebula);

nNebulaUsePackage(ntoollib);

nNebulaUsePackage(ndirect3d9);

nNebulaUsePackage(ndinput8);

nNebulaUsePackage(ngui);


nNebulaScriptModule(nAppFrame, nappframe, "nroot");


void nNebulaScriptInitCmds(nappframe)(nClass *)

{

    /// add any cmd you want.

}


nKernelServer* nAppFrame::ks = NULL;


nAppFrame::nAppFrame() :

    isOpen(false),

    refScriptServer("/sys/servers/script"),

    refGfxServer("/sys/servers/gfx"),

    refInputServer("/sys/servers/input"),

    refConServer("/sys/servers/console"),

    refResourceServer("/sys/servers/resource"),

    refSceneServer("/sys/servers/scene"),

    refVariableServer("/sys/servers/variable"),

    refGuiServer("/sys/servers/gui"),

    refShadowServer("/sys/servers/shadow"),

    refParticleServer("/sys/servers/particle"),

    refAnimationServer("/sys/servers/anim")


    //refVideoServer("/sys/servers/video"),

    //refAudioServer("/sys/servers/audio"),

    //refPrefServer("/sys/servers/nwin32prefserver"),

    //refLocaleServer("/sys/servers/locale"),

{

    n_assert(!nAppFrame::ks);


    nAppFrame::ks = n_new(nKernelServer);


    m_fpOnFrame        = NULL;

    m_fpOnRender3D    = NULL;

    m_fpOnRender2D    = NULL;

}


nAppFrame::~nAppFrame()

{

    n_assert(nAppFrame::ks);


    n_delete(nAppFrame::ks);

    nAppFrame::ks = NULL;

}


/// Open Nebula App

bool nAppFrame::OpenNebula()

{

    /// Add Modules

    ks->AddPackage(nnebula);

    ks->AddPackage(ntoollib);

    ks->AddPackage(ndirect3d9);

    ks->AddPackage(ndinput8);

    ks->AddPackage(ngui);


    /// Create Servers

    ks->New("ntclserver",        "/sys/servers/script");

    ks->New("nresourceserver",    "/sys/servers/resource");

    ks->New("nvariableserver",    "/sys/servers/variable");

    ks->New("ndi8server",        "/sys/servers/input");

    ks->New("nguiserver",        "/sys/servers/gui");

    ks->New("nconserver",        "/sys/servers/console");

    ks->New("nd3d9server",        "/sys/servers/gfx");

    ks->New("nsceneserver",        "/sys/servers/scene");

    ks->New("nshadowserver2",    "/sys/servers/shadow");

    ks->New("nparticleserver",    "/sys/servers/particle");

    ks->New("nanimationserver", "/sys/servers/anim");


    //ks->New("ndshowserver", "/sys/servers/video");

    //ks->New("nprefserver", "/sys/servers/nwin32prefserver");

    //ks->New("nlocaleserver", "/sys/servers/locale");

    //ks->New("ndsoundserver3", "/sys/servers/audio");


    /// SetDisplay

    display.SetXPos(150);

    display.SetYPos(100);

    display.SetWidth(640);

    display.SetHeight(480);

    refGfxServer->SetDisplayMode(display);

    refGfxServer->SetCamera(camera);


    ///////////////////////////////////////////////////////////////////////////

    nString ret;


    /// 获得FileServer设置系统路径

    nFileServer2* file = (nFileServer2*)ks->Lookup("sys/servers/file2");

    /// 设置系统路径

    file->SetAssign("home",            "bin:../../");

    file->SetAssign("renderpath",    "home:datafiles/shaders");

    file->SetAssign("scripts",        "home:datafiles/scripts");


    file->SetAssign("particles",    "home:datafiles/particles");

    file->SetAssign("gfxlib",        "home:datafiles/gfxlib");

    file->SetAssign("textures",        "home:datafiles/textures");

    file->SetAssign("meshes",        "home:datafiles/meshes");

    file->SetAssign("anims",        "home:datafiles/anims");


    /// 启动RemoteServer

    ks->GetRemoteServer()->Open("8379");


    /// 启动sceneserver(启动d3d9server)

    refSceneServer->SetRenderPathFilename("renderpath:dx7_renderpath.xml");

    if ( !refSceneServer->Open() )

    {

        return false;

    }


    /// 启动GUIServer

    ret.Clear();

    refScriptServer->RunScript("scripts:ngui.tcl", ret);

    refGuiServer->Open();


    /// Map Input

    refInputServer->Open();

    ret.Clear();

    refScriptServer->RunScript("scripts:ninput.tcl", ret);


    /// Open node list

    this->m_nodes.SetStageScript("gfxlib:stdlight.n2");

    this->m_nodes.Open();


    /// Init Client Res

    this->ClientOpen();


    /// make the open mark

    this->isOpen = true;


    return true;

}


/// Close Nebula App

bool nAppFrame::CloseNebula()

{

    /// make the close mark

    this->isOpen = false;


    /// release client res

    this->ClientClose();


    /// close node list

    this->m_nodes.Close();


    /// close servers

    if (this->refGuiServer.isvalid())

    {

        this->refGuiServer->Close();

    }

    if (this->refSceneServer.isvalid())

    {

        this->refSceneServer->Close();

    }

    //if (this->refAudioServer.isvalid())

    //{

    //    this->refAudioServer->Close();

    //}

    //if (this->refVideoServer.isvalid())

    //{

    //    this->refVideoServer->Close();

    //}

    //if (this->refLocaleServer.isvalid())

    //{

    //    if (this->refLocaleServer->IsOpen())

    //        this->refLocaleServer->Close();

    //}


    // close the remote port

    ks->GetRemoteServer()->Close();


    this->refShadowServer->Release();

    this->refGuiServer->Release();

    this->refParticleServer->Release();

    this->refVariableServer->Release();

    this->refSceneServer->Release();

    this->refConServer->Release();

    this->refInputServer->Release();

    this->refGfxServer->Release();

    this->refResourceServer->Release();

    this->refScriptServer->Release();

    this->refAnimationServer->Release();


    //this->refVideoServer->Release();

    //this->refLocaleServer->Release();

    //this->refPrefServer->Release();

    //this->refAudioServer->Release();


    return true;

}


/// Main loop

void nAppFrame::RunNebula()

{

    n_assert(this->isOpen);


    bool run = true;


    /// Trigger GfxServer (Windows Messages) && Ping Script Quit Request

    while ( run = refGfxServer->Trigger() && this->refScriptServer->Trigger() )

    {

        /// Trigger TimeServer

        nTimeServer::Instance()->Trigger();

        double time = nTimeServer::Instance()->GetTime();


        /// Trigger InputServer

        this->refInputServer->Trigger(time);


        /// Trigger Logic

        this->OnFrame();


        /// Begin Scene (Begin Frame)

        if ( refSceneServer->BeginScene(view) )

        {

            // Trigger Particle Server

            refParticleServer->Trigger();


            // Render 3D

            this->OnRender3D();


            // Render Scene

            refSceneServer->RenderScene();


            // End Scene

            refSceneServer->EndScene();


            // Render 2D

            this->OnRender2D();


            // Present Scene (End Frame)

            refSceneServer->PresentScene();

        }


        /// Flush Events

        this->refInputServer->FlushEvents();

    }

}


/// OnRender3d

void nAppFrame::OnRender3D()

{

    for ( size_t i = 0; i < m_nodes.GetCount(); ++i )

    {

        this->refSceneServer->Attach(m_nodes.GetRenderContextAt(i));

    }


    if ( m_fpOnRender3D )

    {

        m_fpOnRender3D();

    }

}


/// OnRender2d

void nAppFrame::OnRender2D()

{

    if ( m_fpOnRender2D )

    {

        m_fpOnRender2D();

    }

}


/// logic trigger

void nAppFrame::OnFrame()

{

    /// update camera

    this->OnCameraControll();


    /// update node list

    static unsigned int nFrameID = 0;

    this->m_nodes.Trigger(nTimeServer::Instance()->GetTime(), nFrameID++);


    if ( m_fpOnFrame )

    {

        m_fpOnFrame();

    }

}


/// camera controll

void nAppFrame::OnCameraControll()

{

    // Default Camera Controller

    if ( !this->refGuiServer->IsMouseOverGui() )

    {

        // Render Debug

        if ( refInputServer->GetButton("debug") )

        {

            if ( refSceneServer->GetRenderDebug() )

            {

                refSceneServer->SetRenderDebug(false);

            } 

            else 

            {

                refSceneServer->SetRenderDebug(true);

            }

        }


        // give inputs to camControl

        this->m_ccam.SetResetButton(refInputServer->GetButton("reset"));

        this->m_ccam.SetLookButton(refInputServer->GetButton("look"));

        this->m_ccam.SetPanButton(refInputServer->GetButton("pan"));

        this->m_ccam.SetZoomButton(refInputServer->GetButton("zoom"));

        this->m_ccam.SetSliderLeft(refInputServer->GetSlider("left"));

        this->m_ccam.SetSliderRight(refInputServer->GetSlider("right"));

        this->m_ccam.SetSliderUp(refInputServer->GetSlider("up"));

        this->m_ccam.SetSliderDown(refInputServer->GetSlider("down"));


        // update view and get the actual viewMatrix

        this->m_ccam.Update();

        this->view.set(this->m_ccam.GetViewMatrix());

    }

}


以下是使用实例代码:


/****************************************************************************/

/*    Nebula2 - Tutorial 15                                                    */

/*  Simple Application  Framework                                            */

/*  author: happykevins                                                        */

/****************************************************************************/


#include "kernel/nkernelserver.h"

#include "gfx2/ngfxserver2.h"

#include "../NebulaUtils/nappframe.h"

#include "../NebulaUtils/nutildefs.h"


void Render3D()

{

    // Write 3D Render Code Here.

}


void Render2D()

{

    // draw cubes

    vector3 CenterPoint(0, 0.5f, 0);

    float fSize = 0.5f;

    vector3 v[8];

    v[0].set(CenterPoint.x - fSize, CenterPoint.y - fSize, CenterPoint.z - fSize);

    v[1].set(CenterPoint.x + fSize, CenterPoint.y - fSize, CenterPoint.z - fSize);

    v[2].set(CenterPoint.x + fSize, CenterPoint.y + fSize, CenterPoint.z - fSize);

    v[3].set(CenterPoint.x - fSize, CenterPoint.y + fSize, CenterPoint.z - fSize);

    v[4].set(CenterPoint.x - fSize, CenterPoint.y - fSize, CenterPoint.z + fSize);

    v[5].set(CenterPoint.x + fSize, CenterPoint.y - fSize, CenterPoint.z + fSize);

    v[6].set(CenterPoint.x + fSize, CenterPoint.y + fSize, CenterPoint.z + fSize);

    v[7].set(CenterPoint.x - fSize, CenterPoint.y + fSize, CenterPoint.z + fSize);


    vector3 cube[16] = {

        v[1], v[0], v[4], v[5],

        v[1], v[2], v[6], v[5],

        v[3], v[2], v[6], v[7],

        v[3], v[0], v[4], v[7]

    };


    vector3 CenterPoint1(0, 1.5f, 0);

    float fSize1 = 0.5f;

    vector3 v1[8];

    v1[0].set(CenterPoint1.x - fSize1, CenterPoint1.y - fSize1, CenterPoint1.z - fSize1);

    v1[1].set(CenterPoint1.x + fSize1, CenterPoint1.y - fSize1, CenterPoint1.z - fSize1);

    v1[2].set(CenterPoint1.x + fSize1, CenterPoint1.y + fSize1, CenterPoint1.z - fSize1);

    v1[3].set(CenterPoint1.x - fSize1, CenterPoint1.y + fSize1, CenterPoint1.z - fSize1);

    v1[4].set(CenterPoint1.x - fSize1, CenterPoint1.y - fSize1, CenterPoint1.z + fSize1);

    v1[5].set(CenterPoint1.x + fSize1, CenterPoint1.y - fSize1, CenterPoint1.z + fSize1);

    v1[6].set(CenterPoint1.x + fSize1, CenterPoint1.y + fSize1, CenterPoint1.z + fSize1);

    v1[7].set(CenterPoint1.x - fSize1, CenterPoint1.y + fSize1, CenterPoint1.z + fSize1);


    vector3 cube1[16] = {

        v1[1], v1[0], v1[4], v1[5],

        v1[1], v1[2], v1[6], v1[5],

        v1[3], v1[2], v1[6], v1[7],

        v1[3], v1[0], v1[4], v1[7]

    };


    nGfxServer2::Instance()->BeginLines();


    nGfxServer2::Instance()->DrawLines3d(cube,   8, vector4(1.0f, 0, 0, 0.5f) );

    nGfxServer2::Instance()->DrawLines3d(cube+8, 8, vector4(1.0f, 0, 0, 0.5f) );


    nGfxServer2::Instance()->DrawLines3d(cube1,   8, vector4(0, 1.0f, 0, 0.5f) );

    nGfxServer2::Instance()->DrawLines3d(cube1+8, 8, vector4(0, 1.0f, 0, 0.5f) );


    nGfxServer2::Instance()->EndLines();


    vector3 LineH[22];

    vector3 LineV[22];

    float fLen = 5.0f;

    for(int i = 0; i < 11; i++)

    {

        LineH[ i * 2].set(0 - fLen, 0, i-fLen);

        LineH[ i * 2 + 1].set(10.0f - fLen, 0, i - fLen);

    }


    for(i = 0; i < 11; i++)

    {

        LineV[ i * 2].set(i- fLen, 0, 0 - fLen);

        LineV[ i * 2 + 1].set(i- fLen, 0, 10.0f- fLen);

    }


    // draw grids

    nGfxServer2::Instance()->BeginLines();


    for(i = 0; i < 11; i++)

    {

        nGfxServer2::Instance()->DrawLines3d(LineH + i * 2,   2, vector4(1.0f, 0, 1.0f, 0.5f) );

    }


    for(i = 0; i < 11; i++)

    {

        nGfxServer2::Instance()->DrawLines3d(LineV + i * 2,   2, vector4(1.0f, 0, 1.0f, 0.5f) );

    }


    nGfxServer2::Instance()->EndLines();

}


///----------------------------------------------------------------------------

/// +Application

int main(int argc, const char** argv)

{

    // 生成一个nAppFrame的实例

    nAppFrame app;


    // 注册渲染函数

    app.m_fpOnRender2D = Render2D;

    app.m_fpOnRender3D = Render3D;


    // 初始化引擎

    if ( app.OpenNebula() )

    {

        // 启动引擎主循环

        app.RunNebula();

    }


    // 关闭引擎

    app.CloseNebula();


    return 0;

}

/// -Application

///----------------------------------------------------------------------------

-The End-