• irrlicht v1.6 例程18 Splitscreen


    /** Example 018 Splitscreen, U( a# q, @( S' f1 ]( p
    作者:Max Winkel." `9 ?( W; K' V1 x8 \
    译:小时候可靓了(履霜坚冰)2 m! C! N# J2 i6 a2 Z! Q
    0 U2 D4 U: U% J1 E5 N! a0 L4 q& x
    这个例程中我们将学习怎么使用irrlicht中的分屏(比如在赛车类游戏中)& ~$ M; ]8 f. _4 {
    我们将创建一个被分为4个部分的视口,有3个固定摄相机和一个用户可以控制的摄相机4 N% L! s9 [( l# n
    好,让们从头文件开始吧(我想没有再多说的必要了)3 C9 |* C8 P! X
    */
    #include <irrlicht.h>
    #include <iostream>

    #ifdef _MSC_VER
    #pragma comment(lib, "Irrlicht.lib")
    #endif


    ) h- x" R- L6 B4 b6 L
    //引擎命名空间! [" B6 k9 Y2 J1 @/ K& {
    using namespace irr;
    using namespace core;
    using namespace video;6 n$ L6 u6 X  ?: {0 M+ Z
    using namespace scene;, z+ I& c, e- O- n# `4 n  z

    /*& N' H5 g8 W) U
    现在我们将定义用于初始化设备分辨率常量,另外我们设置一个全局变量用于决定分屏是否激活
    */6 ~% ~+ ]& M. k! o  F) C
    const int ResX=800;
    const int ResY=600;3 U- b& o1 j$ c1 G- D! C$ B& ~
    const bool fullScreen=false;
    @6 A
    //是否使用分屏
    bool SplitScreen=true;# p: x* k' {* s
    % A% x/ d* j5 k2 j* ~& G7 ?8 y
    /*
    现在我们需要4个点来设定即将要创建摄相机的位置。( s" N  n( |; y
    */
    //摄相机
    ICameraSceneNode *camera[4]={0,0,0,0};4 L/ N7 C" \1 V. Z& u5 i# r  L


    /*
    在我们的事件接收器中,当用户按下S键的时候,我们切换分屏变量,所有的其它事件则交给FPS摄相机。1 j3 Y/ v. l' T- e; L+ o! |, @
    */
    class MyEventReceiver : public IEventReceiver
    {6 K/ S* |" k8 x( ~% D2 M
            public:- n7 V0 Y8 b! x  @8 m6 _
                    virtual bool OnEvent(const SEvent& event)- w$ y# T. E8 T3 Q( {  k& H, W
                    {! I" S% Z$ C( o, R8 \7 a
                            
       //S键   启用/禁用分屏
       if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
      event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)6 I- U6 C) b+ g- W9 X5 J
                            {
                              SplitScreen = !SplitScreen;
                                   return true;) {8 R7 A+ e. t4 W: B* [% _4 ?  O
                            }                    5 X) j" _: i) a& h# [% L7 j
                            //发送其它所有的事件给第4个摄相机! F; ?# r8 W; f! F
                            if (camera[3])# p& Q7 j  h+ z+ Y% D2 N' c
                                    return camera[3]->OnEvent(event);
                      return false;
                }2 z6 G- w+ `$ ?3 _& z( H4 y
    };


    F8 H
    /*
    好,现在看Main函数
    首先,我们初始化设备,取得资源管理器和图形驱动。从md2中加载一个动画模型,; K6 F* ^9 F% a7 K5 `  z5 [
    从pk3中加载一个地图。因为这是先前使用过的东西,我就不逐步解释了。
    只关心地图的位置
    *// u0 X6 N; b) L8 ?& T8 q  d
    int main()5 l& p* P3 m+ i+ s* D
    {
        video::E_DRIVER_TYPE driverType;, j! ]2 a8 ?# y; q
    1 _% O( A/ n- F
            printf("Please select the driver you want for this example:\n"\6 T  a* Y. ~& B! P+ w8 x  X
                    " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
               " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
             " (f) NullDevice\n (otherKey) exit\n\n");% m5 @2 @) }! [& a! e

            char i;+ w- b/ X6 l, q/ J
            std::cin >> i;$ P' `* _; @$ y% h$ G  M  {
      h: H0 y/ f' _! Y/ L8 T
            switch(i)2 Q8 ^& t5 h) x, {, e
            {* U5 `: B1 y" h/ K* O1 a# Y) }
                    case 'a': driverType = video::EDT_DIRECT3D9;break;
                    case 'b': driverType = video::EDT_DIRECT3D8;break;4 Q, {' \5 B1 a9 d3 U0 l4 u* q
                    case 'c': driverType = video::EDT_OPENGL;   break;9 D8 t9 P2 U; _/ S6 ~1 Z7 e
                    case 'd': driverType = video::EDT_SOFTWARE; break;
                   case 'e': driverType = video::EDT_BURNINGSVIDEO;break;" ^7 W# ^, u( p
                    case 'f': driverType = video::EDT_NULL;     break;
                default: return 1;
             }
    m0 I: K5 O" ]8 w
            

         //实例化事件接收器1 i, i# a# j/ Y! f3 ?
            MyEventReceiver receiver;$ y/ I7 ]* Z! R9 _8 x

         //初始化引擎
        IrrlichtDevice *device = createDevice(driverType,1 O- Y# K% x- s6 u
                            dimension2du(ResX,ResY), 32, fullScreen,
                          false, false, &receiver);
        if (!device)
              return 1;
    - i- c
            ISceneManager *smgr = device->getSceneManager();
         IVideoDriver *driver = device->getVideoDriver();
         //加载模型
          IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2");
         if (!model)
                  return 1;: }' k2 L5 J, c6 F7 O% ]8 i0 ]
            IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);
           //加载纹理
         if (model_node): H0 m7 `2 H" V
            {
                ITexture *texture = driver->getTexture("../../media/sydney.bmp");2 _2 O% I7 [$ R  k  V3 P2 w1 f
                    model_node->setMaterialTexture(0,texture);' G" R+ T6 c" o1 m+ i! w+ v
                    model_node->setMD2Animation(scene::EMAT_RUN);
                //禁用光照. W/ B- {; T$ @
                    model_node->setMaterialFlag(EMF_LIGHTING,false);
           }
    + A  I5 H
            //加载地图/ n. Y1 n. e  f& e+ F
            device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");# R* @8 U1 U" t' ]' r$ `
            IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp");; N8 o* Q  l# `$ s/ [
            if (map)
          {
                ISceneNode *map_node = smgr->addOctTreeSceneNode(map->getMesh(0));
                 //设置位置
                map_node->setPosition(vector3df(-850,-220,-850));
           }+ o7 A! v% `, w% |9 S5 t, i- C& O
    8 a; x/ ?7 u1 ~/ s& D+ d
    /*  D: g' p+ ?2 O4 A) Y9 y
    现在我们建仓我们的4个摄相机,一个用于从前面看模型,
    一个用于从上往下看模型,另一个从侧面看。! l* S: q3 c- }0 `" f! `* O* T+ O
    另外,我们还创建一个FPS摄相机,用来让用户操作# a. B1 p  @2 V5 V
    */7 ]* h# T% z" {- ?
            //创建3个固定的摄相机
          //前% T' P) p7 n! E( z6 O5 v3 V" Q
            camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
           //上
           camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
           //左0 p7 W# @9 D% _+ z9 g
            camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));8 \% N* b4 a* Z$ ~# b! b
            //用户控制的
            camera[3] = smgr->addCameraSceneNodeFPS();$ M) P* {* q7 ?/ `$ M0 \' M
            //不要在sydney的位置开始' {* T" B9 d8 _) `
            if (camera[3])
                   camera[3]->setPosition(core::vector3df(-50,0,-50));( d' z% ]# M$ `) T8 n: w+ \
    ! Z- G" d! p  u, ?0 Q) X
    /*7 {* g9 ]6 F% `/ n
    //创建用于记录帧数的变量和隐藏鼠标4 |9 _. ?. |4 G  Y" h
    */% O, d( U+ j! w7 G0 i' F
            //隐藏鼠标
            device->getCursorControl()->setVisible(false);
           //帧数记录
            int lastFPS = -1;
    /*! R2 c4 u6 B2 [! @
    到现在还没出现什么新的内容
    仅是定义我们的4个摄相机,那游戏画面不会出现分屏效果。
    为了实现这个目标,你需要以下几步; r' S: p: j4 i, a/ A6 w
           设置整个屏幕的视口
             开始一个新的场景(清除屏幕)
             以下3步是分屏中的每个视口都要重复的7 r* N# Y( k* _& h7 q% b. J. F
                  设置视口到你想看的区域
                   激活摄相机,使它和视口“连接”& P8 i8 j; D; l( I/ P
                      渲染所有物体2 Z5 [3 X( `9 D6 C

       如果你有一个GUI. R# h+ N$ U# ]0 m* y8 m
          设置视口到整个屏幕5 F7 |4 G$ h2 C; `% }
              显示GUI& ]6 J9 N8 Z- d9 E6 V
      结束场景
     z" E0 v+ R5 g9 q8 k
    听起来好像有点复杂,但你看了就明白了
    */
           while(device->run())
           {
                   //设置整个场景的视口并开始绘制
                driver->setViewPort(rect<s32>(0,0,ResX,ResY));
                  driver->beginScene(true,true,SColor(255,100,100,100));& J- i$ o; T. w: m' \# [
                    //如果分屏被启动
                if (SplitScreen) //还记得这个变量吗?前面定义过的; K/ y2 c& y' C( }/ Y, U9 }
                    {) h7 P* c( C2 }) y
                            //Activate camera1+ w: V3 }3 Q* ?! `: v
                            //激活1号摄相机2 e8 V' M' f8 k6 l
                            smgr->setActiveCamera(camera[0]);
                         //Set viewpoint to the first quarter (left top)

                           //设置视口到左上角
                        driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));) K: ?. W# x+ ~9 i! ^
                            //Draw scene
                       //绘制场景
                          smgr->drawAll();2 l% L, Z% V1 b' W+ x
                            //Activate camera22 V  \; o: @7 M: g* X
                            //激活2号摄相机
                      smgr->setActiveCamera(camera[1]);
                         //Set viewpoint to the second quarter (right top)
                         //设置视口到右上角% g' N1 d! x3 N$ f7 o+ C- }
                            driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
                         //Draw scene
                        //绘制场景5 x7 L: `6 k& E; x, ?' k" u
                            smgr->drawAll();
                          //Activate camera3
                          //激活3号摄相机' x% S( E( B$ f5 H# Y4 o& l
                            smgr->setActiveCamera(camera[2]);! c# c0 u& v% O  I1 ^& F
                            //Set viewpoint to the third quarter (left bottom)' O3 M, t5 u. O3 ^8 g" O8 G% z
                            //设置视口到左下角
                          driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
                        //Draw scene/ q+ B3 [7 Y+ M
                            //绘制场景' l; ~$ w' b7 t. x
                            smgr->drawAll();6 y( k3 G% B1 M5 K
                            //Set viewport the last quarter (right bottom)
                          //设置视口到右下角6 W% h/ |" l' Q( Z: l
                            driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
                   }
                  //Activate camera46 ~3 I5 O7 o! A0 k, R
                    //激活4号摄相机$ g: O+ R2 j% |' w. y5 g
                    smgr->setActiveCamera(camera[3]);
                  //Draw scene1 L( a4 x: I  C- A; q8 K9 R2 d
                    //绘制场景: j. f0 H" B! Z2 J0 S+ Q
                    smgr->drawAll();! G- \$ Y7 p% `: B# p# P
                    driver->endScene();
    /*3 A3 l  a+ C5 N/ q: r( [& T
                    你大概已经看到了,这幅图片被每个视口分别渲染,那意味着你要损失许多性能(毕竟同样的场景绘了四次)
                   好,如果你问;“我这样做有必要吗?”不要慌,它真的很简单:在区域函数中,我们定义了4个坐标: R  m7 T% B% \# t0 o
                    (0,0)左上角坐标,(X,Y)右下角坐标* U; L4 T! u$ f; V2 k: p

                  这意味着,如果你想要把屏幕分割成两部分,你需要给出如下的坐标
                  1号视口: 0,0,ResX/2,ResY
                 2号视口:ResX/2,0,ResX,ResY
     M5 V- ~3 n0 Q9 i
                    如果你没有完全明白,只需要修改示例程序的值,看发生了什么。
    G* l3 ?! M) q4 s
                    现在我们只需要显示FPS和在用户要离开的时候销毁引擎即可. _; ~+ H' ~6 y, M: ]+ E
    */
                   //取得并显示帧率8 x  W: e( ?7 |# g9 s7 T3 Z/ d
                    if (driver->getFPS() != lastFPS)
                {' G7 _0 E) E: l" m+ `& |% \
                            lastFPS = driver->getFPS();* V- ~+ D& x  R3 }4 c
                            core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: ";6 G5 h9 x# a! G0 w, S# V
                            tmp += lastFPS;) Q- h" x# j0 g5 T
                            tmp += ")";
                          device->setWindowCaption(tmp.c_str());% S1 `3 f6 {% R0 `
                    }
    l' X' R
            //销毁设备# T  t% w$ o' ?# [
            device->drop();
           return 0;
    }
    /*( P: F4 J, T6 l$ c8 u1 P! H* i: ]
    全部结束,只需要编译就可以玩了
     注意:用S键你可以控制是否分屏
    */" f9 |% Q# F- U9 E8 \7 Q1 F
    发表于: irrlicht3d中文官方论坛(3D网游开发论坛) http://www.irrlicht3d.cn

  • 相关阅读:
    python socket文件传输实现
    python 进程与线程(理论部分)
    python函数-基础篇
    python变量、注释、程序交互、格式化输入、基本运算符
    python基础数据篇
    python基础之从认识python到python的使用
    判断素数
    辗转相除法
    你了解gets()和scanf()吗
    密码破译
  • 原文地址:https://www.cnblogs.com/qilinzi/p/1940506.html
Copyright © 2020-2023  润新知