精华内容
下载资源
问答
  • 游戏引擎开发

    千次阅读 2012-07-08 19:32:02
    用C++实现跨平台游戏引擎开发  你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它。  1. 3D游戏...
    
    
    用C++实现跨平台游戏引擎开发

      你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它。

      1. 3D游戏引擎的简短历史

      在游戏开发中,从一开始就确定正确的开发平台是很重要的。是否你的游戏支持Windows,Linux和OS X?是否你的游戏开发只使用OpenGL就足够了?OpenGL是十九世纪九十年代初期设计的,起初只运行于价值约$25,000的Unix CAD工作站上,后来移植到Windows和其它一些低端平台上。与此同时,随着游戏工业的发展,图形加速器价格从$2,000剧跌到你今天看到的价值约$150的大众市场价格。 

      确实,许多人都会援引在1996年用OpenGL开发成功的革命性的游戏Quake,作为以上急速发展现象的直接的原因。然而,成功的Quake级的游戏开发标准要求更多:世界级音频支持,网络连接,用户输入设备支持,以及实时的管理能力等。既需要实现跨平台支持又能使游戏效果激动人心,要实现这样的解决方案最好建立一个体面的游戏开发站台。

      2. 用于C++,Java和其它开发语言的简单DirectMedia层

      对,历史就是这样有趣,但并不是每一部游戏都要做成Quake的克隆品。一直被业界许多人吹捧有着许多优点的选择是简单DirectMedia层(SDML)。这是一套跨平台的多媒体库,它提供对于音频,键盘,鼠标,游戏杆,OpenGL和2D视频帧缓冲的低级存取。SDML支持几乎我能想像出的每一个平台,包括Linux,Windows,所有的MacOS变异物,WinCE,Dreamcast还有另外一些操作系统。它被广泛应用于开发MPEG播放器,硬件仿真器,和许多流行的游戏,包括获奖的运行于Linux平台的Civilization:Call to Power。

      SDML用C写成,但生来就与C++一起工作,已经绑定到了另外许多语言,包括Ada,Eiffel,Java,Lua,ML,Perl,PHP,Pike,Python和Ruby。SDML的应用环境简直就没有什么限制,而且它碰巧是我最喜爱的开源飞行模拟器GL-117(见图1)的开发引擎。事实上,513游戏的当前开发已经基于SDML引擎而且被注册到了SDML的主页。


    图1.GL-117中的一个视图


      3. 通道视觉效果演示程序

      研究游戏引擎的最好方法是看一些示例程序代码。简单地看一下图2中用SDML实现的2D通道类型演示图,你就能发现你仅用几行代码所能完成的工作。你可以使用该实例作为一个保护屏程序,音乐可视化动画效果,等等。篇幅所限,我已经整理了实际的绘制代码。请跟随我的注释分析下面对SDML的工作原理的描述:

    #include "Tunnel.h"
    // SDL 相关变量定义
    SDL_Surface *screen,*bBuffer,*Image;
    SDL_Rect rScreen,rBuffer;
    int main (int argc, char **argv)
    {
     int flag = SDL_SWSURFACE;// 请求一个软件表面.
     //软件表面处于系统内存中,
     // 一般不如硬件表面速度快
     #ifdef WIN32
     int fullscreen = MessageBox(NULL, "Show Full Screen (y/n):","Screen Setting", MB_YESNO);
     if (fullscreen==IDYES) {
      flag |= SDL_FULLSCREEN; // 如果用户需要,接管整个屏幕
     }
     #endif
     Tunnel_Timer(); // 读取起始的系统时钟值
     SDL_Init( SDL_INIT_VIDEO ); // 初始化视频子系统
     //把屏幕设置到 320x240,32位颜色
     screen = SDL_SetVideoMode( 320, 240, 32, flag);
     // 如果可用的话,为屏幕表面请求硬件缓冲
     bBuffer = SDL_CreateRGBSurface( SDL_HWSURFACE, screen->w,screen->h,screen->format->BitsPerPixel,
        screen->format->Rmask,
        screen->format->Gmask,
        screen->format->Bmask,
        screen->format->Amask);
     // 这是种子图像,一旦开始它就会盘旋起来
     Image = SDL_LoadBMP( "tunnel_map.bmp" );
     Image = SDL_ConvertSurface(Image, screen->format, SDL_HWSURFACE);
     rBuffer.x = 0;
     rBuffer.y = 0;
     rBuffer.w = bBuffer->w;
     rBuffer.h = bBuffer->h;
     // 忽视大多数事件, 包括 鼠标动作, 并取消光标
     SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
     SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
     SDL_ShowCursor( SDL_DISABLE );
     Tunnel.Set( 320, 240 ); // 通道将填充整个的缓冲区
     Tunnel.Precalc( 16 ); //内部的圆圈直径
     while (SDL_PollEvent(NULL)==0) {
      float fTime = Tunnel_GetTime();
      //在修改前,必须锁定表面,特别当缓冲区处于图形硬件内存中时
      SDL_LockSurface(bBuffer);
      SDL_LockSurface(Image);
      Tunnel.Draw(bBuffer, Image, 180*sin(fTime), fTime*100);
      SDL_UnlockSurface(bBuffer); // 在更新以后你可以开锁
      SDL_UnlockSurface(Image);
      // 把缓冲区中的数据输出到屏幕绘图区域并强迫进行重画
      SDL_BlitSurface( bBuffer, NULL, screen, &rBuffer );
      SDL_UpdateRect( screen, 0, 0, 0, 0 );
     }
     Tunnel.Free();
    }

     


    图 2. 演示旋转和扭曲的2D通道


      4. 对另外一些游戏引擎的探索

      让我们看一下另外一些开源的游戏引擎。

      a) ALLEGRO(Allegro低级游戏开发例程)

      Allegro是一个开源的可移植的库,主要针对视频游戏和多媒体编程。Allegro由Shawn Hargreaves(近来称为Climax)创建,现在成长为一个能够跨越许多操作系统如Linux,Windows,MacOS,MS-DOS和许多另外的流行平台等的游戏系统。

      除了具有一个高级的2D图形库,它能容易地存取鼠标,键盘,游戏杆和高精度定时器中断。Allegro并没有包装或替换OpenGL,但是通过参观他们广阔的开发站点(http://www.allegro.cc/),你能学习怎样把OpenGL集成到Allegro游戏程序中。

      大约有700种不同的游戏工程,与Allegro一起发行,其中最为杰出的两类是街机游戏和谜题游戏。我特别地喜欢经典的街机游戏Zaxxon(见图3)的重制品。


    图3.酷毙的Zaxxon的重制品


      b) Irrlicht:点燃快速实时的3D引擎

      这个Irrlicht 引擎是一个跨平台,高性能实时引擎,用C++写成。你可以选择Direct3D,OpenGL或基于软件的着色技术。高端特点包括动态阴影,粒子系统,人物动画,进门和出门技术和碰撞检测(见图4)。Irrlicht支持Windows和Linux并提供到语言Java,Perl,Ruby等的绑定。业界先驱Nikolaus Gebhardt在他的朋友的少部分帮助下完成的这个引擎工。


    图4.在Irrlicht中的一个十分逼真的场景


      c) ClanLib:为多玩家游戏设计的引擎

      ClanLib提供了一个平台独立的接口来书写游戏-它们有一个共同的到低级库如DirectX和OpenGL的接口。借助于ClanLib,你只需编写少量代码即可在Windows,Linux和OSX系统上开发游戏程序。ClanLib包括一个广泛的声音库,2D碰撞检测,动画,GUI框架和网络库。图5显示了游戏XenoHammer中的一个场景。


    图5.XenoHammer屏幕快照

    用C++实现跨平台游戏开发之Allegro引擎

    要:本文重点讨论开源游戏开发库Allegro(Allegro低级游戏例程),同时涉及到一些深度技术并提供了一个简单的示例程序,帮你进一步确定它是否是适合你的开发平台。

      一、 一个适于多环境的引擎

      Allegro最开始被研发于八十年代后期古老的Atari ST平台上,随后被快速地移植到流行的DJGPP环境(一个在九十年代早期流行的32位的MS-DOS扩展程序)。此后,Allegro被移植到最为流行的Windows C++开发环境中,包括VS,MinGW,Cygwin和Borland C++。另外的支持它的平台包括Linux,BeOS,QNX,Mac OSX以及几乎任何其它带有X11库的Unix平台上。

      Allegro能着色到各种类型的位图和硬件加速的环境中,例如DirectX,XWindows,SVGAlib,FreeBE/AF,CGDirectDisplay,QuickDraw,等等。Allegro并不想提供它自己的3D环境或模拟器,但是OpenGL可以被容易地集成,这是通过使用AllegroGL库-它提供了一个类似于GLUT的接口(包括扩展管理)-实现的。

      二、 性能概要

      在进一步使用API开发前,让我们看一下Allegro提供的总体功能:

      ·具体到像素级的绘图函数,包括平坦阴影,gouraud阴影,纹理贴图,z缓冲的多边形和圆绘制,填充,贝塞尔样条曲线,图案填充,精灵,blitting(位图复制),位图计算缩放和旋转,半透明/光效果以及比例字体支持的文本输出 

      ·FLI/FLC(在计算机生成的动画方面,这种格式比MPEG有更高的压缩性能)动画播放器

      ·播放后台MIDI音乐,可达64种同时的声音效果,并能录制样本波形和MIDI输入(声音平台支持,包括WaveOut,DirectSound,OSS,ESD,CoreAudio和QuickTime,等等)

      ·容易地存取鼠标,键盘,游戏杆等设备,还支持高分辨率定时器中断,包括一个DOS版本的垂直折回中断模拟器

      ·读/写LZSS压缩文件的例程

      ·数学函数,包括定点算术,表查找和3D矢量/矩阵/四元数操作

      ·GUI对话框管理器和文件选择器

      ·内建地支持16位和UTF-8格式的Unicode字符 

      三、 使用引擎

      使用Allegro进行开发,就象在许多其它游戏场合下一样,游戏的总体结构都包括游戏开始前的初始化,游戏循环以及游戏完成后的清理。初始化意味着既包含Allegro启动代码也包含在开始的位置实现基本地装载或生成你的游戏级别。在创建你的初始化代码时,启动Allegro基本上没有什么代价付出(见图1).

      如果你需要很多屏幕相关的真实性能,建议你首先礼貌地用get_gfx_mode_list()函数查询一下最大可用方式:

    #include <allegro.h> //必须放于系统头文件的引用之后
    set_color_depth(32); // 缺省情况下使用8位颜色
    if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
     abort_on_error("Couldn’t set a 32 bit color resolution");
    }


      set_gfx_mode()的最后两个参数用于指定虚拟缓冲区的大小-我们的图形屏幕存储于其中。这可以使创建一个卷边游戏-其中地形是连续移动的-变得容易。例如,你可能要使虚拟缓冲区,比方说,宽出20%以留出足够的空间来平滑卷动新的精灵和地形。

     四、 一个完整的Allegro实例

      本教程将使用Kee-Yip Chan的SnookerClone演示程序,它是基于James Lohr的另一个具有相同名字的演示程序。图1显示了演示程序的基本屏幕快照。


    图1.Kee-Yip Chan的"SnookerClone"演示程序

      这个工程向你展示了许多不同的Allegro技术,包括动画,键盘输入和鼠标输入,碰撞和游戏物理知识(例如重力)。它利用了三个主要的元素:一个有8个扶手的旋转的车轮,一个用箭头键来控制的大红球,还有一些从顶部往下坠落的蓝球。车轮以接触方式推动红球,而当红球碰上蓝球时,它们之间相互影响。

      下列是完整的Allegro演示程序的代码:

    1 #include <allegro.h>
    2 vector<Point> g_points; //aka球上点的列表
    3 vector<Joint> g_joints; //物理对象列表,如车轮和缓冲器
    4 kVec g_accControl;
    6 int main(void)
    7 {
    8  allegro_init(); // 初始化allegro.
    9  install_keyboard(); // 启动键盘.
    10 install_mouse(); // 启动鼠标.
    11 install_timer(); //过程show_mouse()所需要;
    13 // 创建一个800x600的非全屏窗口.
    14 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
    16 set_window_title("Kee-Yip Chan’s Snooker Clone");
    17 text_mode(-1); // 文本将被画在透明的背景之上
    19 BITMAP* buffer = create_bitmap(SCREEN_W, SCREEN_H);
      //创建一张位图用于双缓冲.
    21  // 初始化数据.
    22 create_joints(g_joints); //注册车轮、地板和缓冲器的硬编码的屏幕位置
    25 // 创建顶点以组成aka球: 玩家所用球和三个蓝球
    26 // 的位置, 速度, 大小和质量.
    27 g_points.push_back(Point(kVec(100, 300),kVec(0, 0),16, 10));
    // 玩家.
    28 g_points.push_back(Point(kVec(50, 40), kVec(0, 0),12, 5));
    // 中等的球.
    29 g_points.push_back(Point(kVec(80, 40), kVec(0, 0) 12, 5));
    //中等的球.
    30 g_points.push_back(Point(kVec(110, 40),kVec(0, 0),6, 1));
    // 小球.
    32 //主循环,在按ESC键后退出
    33 while(!key[KEY_ESC]) { //检查输入.
    34  if(key[KEY_UP])
    35   g_accControl.y = -0.07; //Jet pack.向上加速
    36  if(key[KEY_LEFT])
    37   g_accControl.x = -0.07; //左走.向左加速
    38  if(key[KEY_RIGHT])
    39   g_accControl.x = 0.07; //右走.向右加速
    41   static bool leftMousePressed = false,
        rightMousePressed = false;
    42  if(mouse_b & 1) { //鼠标左键按下
    43   if(!leftMousePressed){
    44    leftMousePressed = true; // 创建一个新球.
    45    g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 12, 5));
    46   }
    47  }
    48  if(!(mouse_b & 1))
    49  //保证不重复鼠标按键
    50  //否则,就会出现许多的新球
    51  leftMousePressed = false;
    52  if(mouse_b & 2) { //鼠标右键按下
    53   if(!rightMousePressed){
    54    rightMousePressed = true; // 创建一个新球
    55    g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 6, 1));
    56   }
    57  }
    58  if(!(mouse_b & 2))
    59   //保证不重复鼠标按键
    60   //否则,就会出现许多的新球.
    61   rightMousePressed = false;
    63   doPhysics();
    65   // 着色:如果我们能再次使用缓冲区,则清除它;
        //否则,旧图像将滞留显示
    66   //用白色进行清除.
    67   clear_to_color(buffer, makecol(255, 255, 255));
    68   for(unsigned i = 0; i < g_points.size(); i++) {
         //画点.
    69    //画一个实心球
    70    circlefill(buffer, //画向缓冲区
    71    g_points[i].position.x,g_points[i].position.y,// aka 球的中心点的位置
    72    g_points[i].size, // 半径.
    73    (i == 0) ? makecol(255, 0, 0) : makecol(0, 0, 255)); //红色如果是玩家;否则为蓝色
    75    // 画一个轮廓球.
    76    circle(buffer, //画向缓冲区
    77     g_points[i].position.x,g_points[i].position.y, // aka 球的中心点的位置.
    78     g_points[i].size, // 半径.
    79     makecol(0, 0, 0)); //红色如果是玩家;否则为蓝色.
    81   }
    83   // 画接合点
    84   for (unsigned i = 0; i < g_joints.size(); i++)
    85    line(buffer, //画向缓冲区
    86     g_joints[i].p1.x, g_joints[i].p1.y, // 点 1.
    87     g_joints[i].p2.x, g_joints[i].p2.y, // 点 2.
    88     makecol(0, 0, 0)); // 黑颜色.
    89    );
    91   // 打印指令.
    92   textout(buffer, font, "Left Mouse Button - new big ball Right Mouse Button - new small ball",
    93     125, 1, makecol(0, 0, 0));
    95   textout(buffer, font, "Arrow Keys - move red ball",
    96     300, 592, makecol(0, 0, 0));
    98   show_mouse(buffer); // 画鼠标光标.
    100   draw_sprite(screen, buffer, 0, 0);// 把缓冲区中的数据画向屏幕.
    101  } // while循环结束
    103  return 0;
    105 }END_OF_MAIN();

      33-101行包括了典型的游戏编程循环模式。游戏继续进行直到玩家按下ESC键退出为止。34-39行支持同时进行的键盘输入,因为你可以按下向上和向左箭头键来获取粗略的斜向运动。

      在41-61行,鼠标动作被捕获到全局变量mouse_b(用于按钮),mouse_x和mouse_y。如果你一直在使用一滚轮鼠标,你还可以使用变量mouse_z。我们对反向弹跳逻辑进行了一点硬编码以确保每次鼠标按下事件只有一个球下落。

      第63行调用doPhysics(),其目的是旋转车轮的线段,更新球位置,检测球碰撞和适当地改变它们的方向矢量。这个模块(350行的数学代码)有点深入了些,但它确实是一个一流的实现,值得你深入研究。

      余下的代码,65-101行,开始着色,在典型的示例程序中这属于常规实现部分。这里的着色用典型的双缓冲区技术,下一次屏幕变化被计算出来并进行脱屏绘制并在最的一毫秒进行缓冲交换(第100行)。这确保了视觉的连续性又减少了烦人的闪烁-对象看上去是随机地绘制的。在着色代码部分,对line()和circlefill()的调用是相当直接的:circlefill()以x,y,半径和填充颜色作为参数。

      textout_ex()函数的功能稍强于textout()(示于92-96行),允许你指定前景和背景颜色。Allegro提供例程以直接从GRX格式.fnt文件,8x8或8x16 BIOS格式.fnt文件,位图图象以及数据文件格式中装入字体。作为选择,你能导入一种大范围的Unicode字体,这可以通过写一个.txt脚本-它为每一范围的字符指定相应的不同的源文件-来实现。如果你想要支持TrueType,那么你需要AllegroTTF或相同功能的插件。
    最后,在第100行的draw_sprite()实现一个覆盖性复制新生成的位图到第14行创建的屏幕对象上。覆盖性复制意指只有非透明的颜色像素被复制。在本例中,我确信它已被退化成一个"blit"(块复制)转储。

      五、 Allegro的音频

      这个snooker演示程序只涉及到了一些最基本的图形和I/O函数,但是并没有用到Allegro的音频开发包。该包中的MIDI混频,音响效果和录音API,其效果达到或超过几乎每一个我所见过的专业的声音库。Allegro音频应用软件大量存在,包括WinCab-一个MP3和OGG Vorbis音乐唱片机,还有LouTronic Rhythm Box-一个鼓声生成合成器,它具有可全面融合到一起的snare鼓,低音鼓和hi hat的效果。下面我们简单地回顾Allegro音频API的一小部分。

      每一个使用音频的程序都应该调用reserve_voices()来指定数字和MIDI声音驱动程序分别使用的声音的数目。接下去,你能控制这些音频轨道的混合.

      你可以非常容易地象下面这样插入一个音轨:

    MIDI *midFile = load_midi("myfile.mid’);
    play_midi(midFile, TRUE);//连续循环

      对于更复杂的需要,你可以安装三个钩子函数之一,它们可以使你拦截MIDI玩家事件。如果被设置为非NULL,这些例程将在每次MIDI消息,元事件和系统独占的数据块中被分别调用。

      Allegro的数字音频系统被设计为从最基本的配置到可高度扩展的。你能容易安装读取器和写入器来处理新的或者不同的音频文件类型, 例如:

    register_sample_file_type("mp3",load_mp3,NULL);//安装MP3读取器

      当正播放数字音频时,你可以随时编辑它。下列代码改变将在播放一个样本参数时改变该样本(用于操作循环播放的声音):

    void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);

      你能改变音量,平移音频数据并清除循环标志,在下次执行到循环末尾时,这将停止该样本。如果在播放相同样本的好几个副本,这会调整它遇到的第一个副本。如果该样本没有播放,对它没有任何影响。

     

    用C++实现跨平台游戏开发之Irrlicht引擎

      Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。通过使用Direct3D(Windows平台),OpenGL 1.2或它自己的软件着色程序,可以实现该引擎的完全跨平台。尽管是开源的,该Irrlicht库提供了可以在商业级的3D引擎上具有的艺术特性,例如动态的阴影,粒子系统,角色动画,室内和室外技术以及碰撞检测等(见图1)。


    图1.Irrlicht 3D引擎

      Irrlicht是一个德国神话故事中的一种动物的名字,它能够发光和飞翔,可以在大部分的沼泽地附近发现它。单词"Irrlicht"是两个德国单词("irr"意思是疯狂的;而"Licht"意思是光)的组合。在英语中,它被译为"鬼火"。

      Irrlicht十分幸运地为一个巨大的活跃的开发团队以大量的工程所支持。然而,因为Irrlicht主要由游戏名家Nikolaus Gebhardt所设计,所以该游戏在设计上十分连贯。你可以在网上到处发现有Irrlicht的增强程序,如可选用的地形生成器,入口生成器,输出器,world层生成器,相关教程和编辑器等。而且,它独立地创建了到Java,Perl,Ruby,BASIC,Python,LUA甚至更多种语言的绑定。而最为重要的是,它是完全自由的。

      二、 Irrlicht特性

      在深入分析API之前,请让我更具体地介绍一下Irrlicht提供给了3D游戏开发者哪些功能: 

      ·一个可以运行于Linux以及Windows 98,ME,NT,2000和XP(MacOS在计划之中)等操作系统之上的引擎

      ·针对Direct3D 8生成器或Direct3D 9生成器(可选)提供了Anti-aliasing支持

      ·可换肤的GUI环境(包括一个很酷的具有金属质地的带阴影的皮肤),给一些老式的对话框加上漂亮的外观

      ·场景管理系统,它允许无缝的室内/室外过渡

      ·角色动画系统,带有骨骼和变形目标动画功能

      ·一个特殊的效果系统,包括粒子效果(雨,烟,火,雪,等等),告示板,灯光贴图,环境,地图,模板缓冲区阴影,雾,纹理动画,视差贴图,凹凸贴图,还有更多

      ·内建的材质支持,包括支持Pixel and Vertex Shaders版本1.1到3.0,ARB Fragment and Vertex程序以及HLSL(GLSL正在计划中)

      ·.NET语言绑定,这使得引擎可用于所有的.NET语言例如C#,Visual Basic.NET以及Delphi.NET

      ·一内建的平台独立的软件生成器,特性有:z-缓冲,Gouraud阴影,alpha混合和透明性,还有快速的2D绘图(见图2)

      ·你久已期待的2D绘图功能,例如alpha混合,基于关键色的位图复制,字体绘制,以及混合3D与2D图形

      ·能直接导入常见的建模文件格式:Maya,3DStudio Max,COLLADA,DeleD,Milkshape,Quake 3 levels,Quake2 models,DirectX,Pulsar,My3DTools,FSRad以及Cartography Shop

      ·能直接从BMP,PNG,Photoshop,JPEG,Targa和PCX导入纹理

      ·快速而易用的碰撞检测与响应

      ·为快速的3D运算和容器模板库进行了优化处理

      ·直接读取档案(可能是压缩的,如.zip文件)

      ·集成了快速的XML分析器

      ·为实现容易的本地化开发提供Unicode支持


    图2:基于Irrlicht的游戏Yet Another Space Shooter(YASS),这里显示的是一个静态游戏帧中的令人吃惊的着色效果
      三、 在Irrlicht中的特殊效果

      在本文的例子中,我将向你展示怎样使用模板缓冲区影子技术,还有粒子系统,告示板,动态光以及水表面场景结点等技术。参见图3。


    图3.结合动态的光和水进行的场景着色

      Irrlicht引擎自动地检查是否你的硬件支持模板缓冲;而如果不支持,则不启动阴影。在这个演示程序中,在方法createDevice()中的’shadows’标志被置位,以产生从一个动画角色投下的动态影子。如果这个实例程序在你的PC上运行太慢,可以把这个标志设置为false或者干脆再买一块更好些的图形加速卡。

      为能够使用Irrlicht.DLL文件,你需要链接到Irrlicht.lib库文件。你可以在工程设置对话框中设置这个选项;但是为了容易实现,你可以使用一个pragma预编译注释命令。方法createDevice()负责实例化根对象-它使用引擎完成一切事情。参数如下:

      ·deviceType:设备类型。当前你可选取Null设备以及软设备,如DirectX8,DirectX9或OpenGL。

      ·windowSize:要创建的窗口的大小或全屏幕模式。这个例子中使用512x384。

      ·bits:每像素位数(当在全屏幕情况时)。仅允许值为16或者32。

      ·fullscreen:指定是否你想使设备运行于全屏幕方式。

      ·stencilbuffer:指定是否你想使用模板缓冲区以用于绘制阴影。

      ·vsync:指定是否你想启动vsync(仅在全屏幕情况),可选。

      ·eventReceiver:一个接收事件的对象,可选。

      为适合于本实例环境,你将装载一个3D Studio Max文件(一幢房子)。该房子看起来并没有什么特别的,但是Irrlicht引擎能为你创建一个相当酷的纹理贴图。只需使用造型操纵器并为之创建一个planar纹理贴图即可:

    #include <irrlicht.h>
    #include <iostream>
    using namespace irr;
    #pragma comment(lib, "Irrlicht.lib")
    int main()
    {
     //让我们假定用户在本例中使用OpenGL
     //当然,也可以指定DirectX 8, 9, 等等.
     video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
     //创建设备,如果创建失败立即退出。
     IrrlichtDevice *device = createDevice(driverType,
     core::dimension2d(640, 480), 16, false, true);
     if (device == 0)
      return 1;
     video::IVideoDriver* driver = device->getVideoDriver();
     scene::ISceneManager* smgr = device->getSceneManager();

      我对从这个导入文件产生的发射光线颜色的效果并不满意。下列代码显示怎样实现这些步骤:

    scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds");
    smgr->getMeshManipulator()->makePlanarTextureMapping(
    mesh->getMesh(0), 0.008f);
    scene::ISceneNode* node = 0;
    node = smgr->addAnimatedMeshSceneNode(mesh);
    node->setMaterialTexture(0, driver->getTexture("wall.jpg"));
    node->getMaterial(0).EmissiveColor.set(0,0,0,0);

      四、 水动画

      你将添加的第一个特殊的效果是水动画。为此,WaterSurfaceSceneNode导入一个造型文件并使之象水表面一样地波动。如果你让这个场景结点使用一种相当好的材质如MT_REFLECTION_2_LAYER,那么它看起来相当酷:

    mesh = smgr->addHillPlaneMesh("myHill",
    core::dimension2d(20,20),
    core::dimension2d(40,40), 0, 0,
    core::dimension2d(0,0),
    core::dimension2d(10,10));
    node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30);
    node->setPosition(core::vector3df(0,7,0));
    node->setMaterialTexture(0,driver->getTexture("water.jpg"));
    node->setMaterialTexture(1,driver->getTexture("stones.jpg"));
    node->setMaterialType(video::EMT_REFLECTION_2_LAYER);

      作为输入造型,你可以创建一个陡峭的平面造型,但是你也可以为此使用任何其它的造型。你甚至能重用room.3ds输入文件(它看上去确实很奇怪)。该实例还用一个普通的石头纹理模型来绘制所有另外的表面。

      五、透明的告示板和灯光

      第二个特殊的效果是很基本的但是非常有用:一个透明的告示板,伴之有一个动态的灯光。为产生这种效果,你只需要产生一个灯光场景结点,并让它四处飞行;而且,为了让它看起来更酷一些,可以把一个告示板场景结点依附到它上面:

    //创建灯光
    node = smgr->addLightSceneNode(0, core::vector3df(0,0,0),
    video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f);
    scene::ISceneNodeAnimator* anim = 0;
    anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),250.0f);
    node->addAnimator(anim);
    anim->drop();
    // 把告示板依附到灯光
    node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50));
    node->setMaterialFlag(video::EMF_LIGHTING, false);
    node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
    node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp"));

     

     六、 粒子系统

      下面介绍的这个特别效果更有趣:一个粒子系统。在Irrlicht引擎中,粒子系统既是组件化的,也是可扩展的,但是仍然易于使用。你只需要简单地把粒子发射器放到一个粒子系统场景结点,这样以来粒子看上去没有产生源。这些发射器可以据需要进行灵活配置,并经常带有许多参数,如粒子方向,粒子数量,以及粒子颜色等。 

      当然,发射器类型有区别(例如,一个点发射器能够使粒子从一个固定的点上发出粒子)。如果该引擎提供的粒子发射器还不能满足你的要求,你可以容易地创建你自己的发射器。这只需简单地从IParticleEmitter接口派生一个新类并使用setEmitter()方法把它依附到粒子系统上去即可。

      下一个实例将创建一个盒子粒子发射器。你可能已经猜出,它从一个跳跃的盒中随机生成粒子。由参数来定义盒子,粒子的方向,每秒产生粒子的最小和最大数目,颜色以及粒子的最小和最大生命周期。

      一个完全由发射器组成的粒子系统将是令人生厌的,因为缺乏真实感。因此,Irrlicht支持粒子影响器-它负责在粒子到处飞扬时予以修整。一旦添加到粒子系统上,它们就能模仿另外的更真实的效果,象重力或风。在本例中的粒子影响器只是简单地修改粒子的颜色来产生一种淡出效果。

      可能你已经猜出,粒子影响器是通过派生IParticleAffector接口实现的,然后通过使用addAffector()方法把它添加到粒子系统上去。在你为该粒子系统设置了一种好看的材质后,你就有了一个看上去相当酷的野外宿营火的效果。通过调整材质,纹理,粒子发射器,还有影响器参数,你能容易地创建烟雾,下雨,爆炸,下雪等效果:

    scene::IParticleSystemSceneNode* ps = 0;
    ps = smgr->addParticleSystemSceneNode(false);
    ps->setPosition(core::vector3df(-70,60,40));
    ps->setScale(core::vector3df(2,2,2));
    ps->setParticleSize(core::dimension2d(20.0f, 10.0f));
    scene::IParticleEmitter* em = ps->createBoxEmitter(
    core::aabbox3d(-7,0,-7,7,1,7),
    core::vector3df(0.0f,0.03f,0.0f),
    80,100,
    video::SColor(0,255,255,255), video::SColor(0,255,255,255),
    800,2000);
    ps->setEmitter(em);
    em->drop();
    scene::IParticleAffector* paf =ps->createFadeOutParticleAffector();
    ps->addAffector(paf);
    paf->drop();
    ps->setMaterialFlag(video::EMF_LIGHTING, false);
    ps->setMaterialTexture(0, driver->getTexture,"particle.bmp"));
    ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

      七、 影子投射

      最后但也不容忽视一个问题是,你需要为一个动画角色产生一个动态的影子。为此,你装载一个Quake2.md2模型文件并把它放到你的world上去。为了创建影子,你只需要调用方法addShadowVolumeSceneNode()。你可能通过调用ISceneManager::setShadowColor()来控制影子的颜色;注意,这仅是全局可调整的,并影响所有的影子。好,下面就是你的产生动态影子效果的代码:

    mesh = smgr->getMesh("../../media/faerie.md2");
    scene::IAnimatedMeshSceneNode* anode = 0;
    anode = smgr->addAnimatedMeshSceneNode(mesh);
    anode->setPosition(core::vector3df(-50,45,-60));
    anode->setMD2Animation(scene::EMAT_STAND);
    anode->setMaterialTexture(0, driver->getTexture("../../media/Faerie5.BMP"));
    anode->addShadowVolumeSceneNode();
    smgr->setShadowColor(video::SColor(220,0,0,0));

      八、 游戏循环

      最后,你能进入由device->run()方法控制的游戏循环。该循环将不断运行,直到通过获取一个关闭窗口事件(例如在Windows操作系统下的ALT-F4击键)来退出设备。你必须在一个beginScene()和endScene()命令对之间绘制每样东西。beginScene()用指定的一种颜色清屏,如果需要的话,可以同时清除深度缓冲区。然后你就可以让场景管理器和GUI环境来绘制它们的内容。随着调用endScene(),每一样东西都被绘制到屏幕上去。在本例中,你还可以动态地在标题栏上显示帧每秒(FPS)数,这对于严肃的游戏开发者是十分重要的事情:

    scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
    camera->setPosition(core::vector3df(-50,50,-150));
    int lastFPS = -1;
    while(device->run())
    {
     driver->beginScene(true, true, 0);
     smgr->drawAll();
     driver->endScene();
     int fps = driver->getFPS();
     if (lastFPS != fps)
     {
      core::stringw str = L"Campfire FX example [";
      str += driver->getName();
      str += "] FPS:";
      str += fps;
      device->setWindowCaption(str.c_str());
      lastFPS = fps;
     }
    }
    device->drop();

      结束循环后,你必须删除先前用createDevice()方法创建的Irrlicht设备。通过使用Irrlicht引擎,你应该删除所有你用以’create’开头的方法或函数创建的所有对象。你可以通过简单地调用device->drop()来删除该设备对象。

      九、你可能喜欢的Irrlicht插件

      正如在前面所介绍的,Irrlicht有一群勤奋的独立开发人员并为之产生了大量的插件,也用之开发了相当多的游戏。这些开发者中提出的许多的改进被再次集成到Irrlicht的随后的发行版本中。下面我列举其中的几个例子,我想这会吸引许多颇有前程的开发者感兴趣:

      ·OCTTools,是一套用于Irrlicht的工具,由Murphy McCauley所创建,用于操作OCT文件相关的:输出器,加载器,甚至更多。

      ·ICE(Irrlicht通用引擎)是一个开发框架,它提供了一个工程的轮廓实现,从而加快了新工程的开发。

      ·MIM,由Murphy McCauley所创建,是一个非常有用的基于XML的文件格式,可用于Irrlicht的加载器,转换器及其各种工具。

      ·My3D是一个开发工具包,它能够使你把来自于各种3D包(3DStudio MAX,Giles,等等)中的灯光贴图场景直接输出到Irrlicht中。

      ·Dusty引擎允许程序员创建"任务"-这些"任务"可以完成程序员想做的任何事情。之后,这些任务被添加到一棵普通的任务树上去,而每个任务可以有它们希望数目的孩子任务。任务"组"允许游戏设计者在一棵完整的树上执行普通的操作,例如暂停,继续或破坏等。 

      ·Irrlicht RPG(Erring Light)是一个3D 绕行走游戏引擎,最初是针对RPG类游戏开发的。

      ·2D 图像和精灵类组成了一个很有用的库,它扩展了Irrlicht的2D能力。

      ·Zenprogramming站点,提供第一个针对Irrlicht的非正式的外部地形生成器,此处也提供很多相关的教程。

     

     

    展开全文
  • C++游戏引擎开发

    千次阅读 2019-02-01 15:42:59
    C++游戏引擎开发
                   

    游戏引擎开发

    用C++实现跨平台游戏引擎开发

      你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它。

      1. 3D游戏引擎的简短历史

      在游戏开发中,从一开始就确定正确的开发平台是很重要的。是否你的游戏支持Windows,Linux和OS X?是否你的游戏开发只使用OpenGL就足够了?OpenGL是十九世纪九十年代初期设计的,起初只运行于价值约$25,000的Unix CAD工作站上,后来移植到Windows和其它一些低端平台上。与此同时,随着游戏工业的发展,图形加速器价格从$2,000剧跌到你今天看到的价值约$150的大众市场价格。

      确实,许多人都会援引在1996年用OpenGL开发成功的革命性的游戏Quake,作为以上急速发展现象的直接的原因。然而,成功的Quake级的游戏开发标准要求更多:世界级音频支持,网络连接,用户输入设备支持,以及实时的管理能力等。既需要实现跨平台支持又能使游戏效果激动人心,要实现这样的解决方案最好建立一个体面的游戏开发站台。

      2. 用于C++,Java和其它开发语言的简单DirectMedia层

      对,历史就是这样有趣,但并不是每一部游戏都要做成Quake的克隆品。一直被业界许多人吹捧有着许多优点的选择是简单DirectMedia层(SDML)。这是一套跨平台的多媒体库,它提供对于音频,键盘,鼠标,游戏杆,OpenGL和2D视频帧缓冲的低级存取。SDML支持几乎我能想像出的每一个平台,包括Linux,Windows,所有的MacOS变异物,WinCE,Dreamcast还有另外一些操作系统。它被广泛应用于开发MPEG播放器,硬件仿真器,和许多流行的游戏,包括获奖的运行于Linux平台的Civilization:Call to Power。

      SDML用C写成,但生来就与C++一起工作,已经绑定到了另外许多语言,包括Ada,Eiffel,Java,Lua,ML,Perl,PHP,Pike,Python和Ruby。SDML的应用环境简直就没有什么限制,而且它碰巧是我最喜爱的开源飞行模拟器GL-117(见图1)的开发引擎。事实上,513游戏的当前开发已经基于SDML引擎而且被注册到了SDML的主页。


    图1.GL-117中的一个视图


      3. 通道视觉效果演示程序

      研究游戏引擎的最好方法是看一些示例程序代码。简单地看一下图2中用SDML实现的2D通道类型演示图,你就能发现你仅用几行代码所能完成的工作。你可以使用该实例作为一个保护屏程序,音乐可视化动画效果,等等。篇幅所限,我已经整理了实际的绘制代码。请跟随我的注释分析下面对SDML的工作原理的描述:

    #include "Tunnel.h"
    // SDL 相关变量定义
    SDL_Surface *screen,*bBuffer,*Image;
    SDL_Rect rScreen,rBuffer;
    int main (int argc, char **argv)
    {
     int flag = SDL_SWSURFACE;// 请求一个软件表面.
     //软件表面处于系统内存中,
     // 一般不如硬件表面速度快
     #ifdef WIN32
     int fullscreen = MessageBox(NULL, "Show Full Screen (y/n):","Screen Setting", MB_YESNO);
     if (fullscreen==IDYES) {
      flag |= SDL_FULLSCREEN; // 如果用户需要,接管整个屏幕
     }
     #endif
     Tunnel_Timer(); // 读取起始的系统时钟值
     SDL_Init( SDL_INIT_VIDEO ); // 初始化视频子系统
     //把屏幕设置到 320x240,32位颜色
     screen = SDL_SetVideoMode( 320, 240, 32, flag);
     // 如果可用的话,为屏幕表面请求硬件缓冲
     bBuffer = SDL_CreateRGBSurface( SDL_HWSURFACE, screen->w,screen->h,screen->format->BitsPerPixel,
        screen->format->Rmask,
        screen->format->Gmask,
        screen->format->Bmask,
        screen->format->Amask);
     // 这是种子图像,一旦开始它就会盘旋起来
     Image = SDL_LoadBMP( "tunnel_map.bmp" );
     Image = SDL_ConvertSurface(Image, screen->format, SDL_HWSURFACE);
     rBuffer.x = 0;
     rBuffer.y = 0;
     rBuffer.w = bBuffer->w;
     rBuffer.h = bBuffer->h;
     // 忽视大多数事件, 包括 鼠标动作, 并取消光标
     SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
     SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
     SDL_ShowCursor( SDL_DISABLE );
     Tunnel.Set( 320, 240 ); // 通道将填充整个的缓冲区
     Tunnel.Precalc( 16 ); //内部的圆圈直径
     while (SDL_PollEvent(NULL)==0) {
      float fTime = Tunnel_GetTime();
      //在修改前,必须锁定表面,特别当缓冲区处于图形硬件内存中时
      SDL_LockSurface(bBuffer);
      SDL_LockSurface(Image);
      Tunnel.Draw(bBuffer, Image, 180*sin(fTime), fTime*100);
      SDL_UnlockSurface(bBuffer); // 在更新以后你可以开锁
      SDL_UnlockSurface(Image);
      // 把缓冲区中的数据输出到屏幕绘图区域并强迫进行重画
      SDL_BlitSurface( bBuffer, NULL, screen, &rBuffer );
      SDL_UpdateRect( screen, 0, 0, 0, 0 );
     }
     Tunnel.Free();
    }

     


    图 2. 演示旋转和扭曲的2D通道


      4. 对另外一些游戏引擎的探索

      让我们看一下另外一些开源的游戏引擎。

      a) ALLEGRO(Allegro低级游戏开发例程)

      Allegro是一个开源的可移植的库,主要针对视频游戏和多媒体编程。Allegro由Shawn Hargreaves(近来称为Climax)创建,现在成长为一个能够跨越许多操作系统如Linux,Windows,MacOS,MS-DOS和许多另外的流行平台等的游戏系统。

      除了具有一个高级的2D图形库,它能容易地存取鼠标,键盘,游戏杆和高精度定时器中断。Allegro并没有包装或替换OpenGL,但是通过参观他们广阔的开发站点(http://www.allegro.cc/),你能学习怎样把OpenGL集成到Allegro游戏程序中。

      大约有700种不同的游戏工程,与Allegro一起发行,其中最为杰出的两类是街机游戏和谜题游戏。我特别地喜欢经典的街机游戏Zaxxon(见图3)的重制品。


    图3.酷毙的Zaxxon的重制品


      b) Irrlicht:点燃快速实时的3D引擎

      这个Irrlicht 引擎是一个跨平台,高性能实时引擎,用C++写成。你可以选择Direct3D,OpenGL或基于软件的着色技术。高端特点包括动态阴影,粒子系统,人物动画,进门和出门技术和碰撞检测(见图4)。Irrlicht支持Windows和Linux并提供到语言Java,Perl,Ruby等的绑定。业界先驱Nikolaus Gebhardt在他的朋友的少部分帮助下完成的这个引擎工。


    图4.在Irrlicht中的一个十分逼真的场景


      c) ClanLib:为多玩家游戏设计的引擎

      ClanLib提供了一个平台独立的接口来书写游戏-它们有一个共同的到低级库如DirectX和OpenGL的接口。借助于ClanLib,你只需编写少量代码即可在Windows,Linux和OSX系统上开发游戏程序。ClanLib包括一个广泛的声音库,2D碰撞检测,动画,GUI框架和网络库。图5显示了游戏XenoHammer中的一个场景。


    图5.XenoHammer屏幕快照
    用C++实现跨平台游戏开发之Allegro引擎

    要:本文重点讨论开源游戏开发库Allegro(Allegro低级游戏例程),同时涉及到一些深度技术并提供了一个简单的示例程序,帮你进一步确定它是否是适合你的开发平台。

      一、 一个适于多环境的引擎

      Allegro最开始被研发于八十年代后期古老的Atari ST平台上,随后被快速地移植到流行的DJGPP环境(一个在九十年代早期流行的32位的MS-DOS扩展程序)。此后,Allegro被移植到最为流行的Windows C++开发环境中,包括VS,MinGW,Cygwin和Borland C++。另外的支持它的平台包括Linux,BeOS,QNX,Mac OSX以及几乎任何其它带有X11库的Unix平台上。

      Allegro能着色到各种类型的位图和硬件加速的环境中,例如DirectX,XWindows,SVGAlib,FreeBE/AF,CGDirectDisplay,QuickDraw,等等。Allegro并不想提供它自己的3D环境或模拟器,但是OpenGL可以被容易地集成,这是通过使用AllegroGL库-它提供了一个类似于GLUT的接口(包括扩展管理)-实现的。

      二、 性能概要

      在进一步使用API开发前,让我们看一下Allegro提供的总体功能:

      ·具体到像素级的绘图函数,包括平坦阴影,gouraud阴影,纹理贴图,z缓冲的多边形和圆绘制,填充,贝塞尔样条曲线,图案填充,精灵,blitting(位图复制),位图计算缩放和旋转,半透明/光效果以及比例字体支持的文本输出

      ·FLI/FLC(在计算机生成的动画方面,这种格式比MPEG有更高的压缩性能)动画播放器

      ·播放后台MIDI音乐,可达64种同时的声音效果,并能录制样本波形和MIDI输入(声音平台支持,包括WaveOut,DirectSound,OSS,ESD,CoreAudio和QuickTime,等等)

      ·容易地存取鼠标,键盘,游戏杆等设备,还支持高分辨率定时器中断,包括一个DOS版本的垂直折回中断模拟器

      ·读/写LZSS压缩文件的例程

      ·数学函数,包括定点算术,表查找和3D矢量/矩阵/四元数操作

      ·GUI对话框管理器和文件选择器

      ·内建地支持16位和UTF-8格式的Unicode字符

      三、 使用引擎

      使用Allegro进行开发,就象在许多其它游戏场合下一样,游戏的总体结构都包括游戏开始前的初始化,游戏循环以及游戏完成后的清理。初始化意味着既包含Allegro启动代码也包含在开始的位置实现基本地装载或生成你的游戏级别。在创建你的初始化代码时,启动Allegro基本上没有什么代价付出(见图1).

      如果你需要很多屏幕相关的真实性能,建议你首先礼貌地用get_gfx_mode_list()函数查询一下最大可用方式:

    #include <allegro.h> //必须放于系统头文件的引用之后
    set_color_depth(32); // 缺省情况下使用8位颜色
    if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
     abort_on_error("Couldn’t set a 32 bit color resolution");
    }


      set_gfx_mode()的最后两个参数用于指定虚拟缓冲区的大小-我们的图形屏幕存储于其中。这可以使创建一个卷边游戏-其中地形是连续移动的-变得容易。例如,你可能要使虚拟缓冲区,比方说,宽出20%以留出足够的空间来平滑卷动新的精灵和地形。

     四、 一个完整的Allegro实例

      本教程将使用Kee-Yip Chan的SnookerClone演示程序,它是基于James Lohr的另一个具有相同名字的演示程序。图1显示了演示程序的基本屏幕快照。


    图1.Kee-Yip Chan的"SnookerClone"演示程序

      这个工程向你展示了许多不同的Allegro技术,包括动画,键盘输入和鼠标输入,碰撞和游戏物理知识(例如重力)。它利用了三个主要的元素:一个有8个扶手的旋转的车轮,一个用箭头键来控制的大红球,还有一些从顶部往下坠落的蓝球。车轮以接触方式推动红球,而当红球碰上蓝球时,它们之间相互影响。

      下列是完整的Allegro演示程序的代码:

    1 #include <allegro.h>
    2 vector<Point> g_points; //aka球上点的列表
    3 vector<Joint> g_joints; //物理对象列表,如车轮和缓冲器
    4 kVec g_accControl;
    6 int main(void)
    7 {
    8  allegro_init(); // 初始化allegro.
    9  install_keyboard(); // 启动键盘.
    10 install_mouse(); // 启动鼠标.
    11 install_timer(); //过程show_mouse()所需要;
    13 // 创建一个800x600的非全屏窗口.
    14 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
    16 set_window_title("Kee-Yip Chan’s Snooker Clone");
    17 text_mode(-1); // 文本将被画在透明的背景之上
    19 BITMAP* buffer = create_bitmap(SCREEN_W, SCREEN_H);
      //创建一张位图用于双缓冲.
    21  // 初始化数据.
    22 create_joints(g_joints); //注册车轮、地板和缓冲器的硬编码的屏幕位置
    25 // 创建顶点以组成aka球: 玩家所用球和三个蓝球
    26 // 的位置, 速度, 大小和质量.
    27 g_points.push_back(Point(kVec(100, 300),kVec(0, 0),16, 10));
    // 玩家.
    28 g_points.push_back(Point(kVec(50, 40), kVec(0, 0),12, 5));
    // 中等的球.
    29 g_points.push_back(Point(kVec(80, 40), kVec(0, 0) 12, 5));
    //中等的球.
    30 g_points.push_back(Point(kVec(110, 40),kVec(0, 0),6, 1));
    // 小球.
    32 //主循环,在按ESC键后退出
    33 while(!key[KEY_ESC]) { //检查输入.
    34  if(key[KEY_UP])
    35   g_accControl.y = -0.07; //Jet pack.向上加速
    36  if(key[KEY_LEFT])
    37   g_accControl.x = -0.07; //左走.向左加速
    38  if(key[KEY_RIGHT])
    39   g_accControl.x = 0.07; //右走.向右加速
    41   static bool leftMousePressed = false,
        rightMousePressed = false;
    42  if(mouse_b & 1) { //鼠标左键按下
    43   if(!leftMousePressed){
    44    leftMousePressed = true; // 创建一个新球.
    45    g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 12, 5));
    46   }
    47  }
    48  if(!(mouse_b & 1))
    49  //保证不重复鼠标按键
    50  //否则,就会出现许多的新球
    51  leftMousePressed = false;
    52  if(mouse_b & 2) { //鼠标右键按下
    53   if(!rightMousePressed){
    54    rightMousePressed = true; // 创建一个新球
    55    g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 6, 1));
    56   }
    57  }
    58  if(!(mouse_b & 2))
    59   //保证不重复鼠标按键
    60   //否则,就会出现许多的新球.
    61   rightMousePressed = false;
    63   doPhysics();
    65   // 着色:如果我们能再次使用缓冲区,则清除它;
        //否则,旧图像将滞留显示
    66   //用白色进行清除.
    67   clear_to_color(buffer, makecol(255, 255, 255));
    68   for(unsigned i = 0; i < g_points.size(); i++) {
         //画点.
    69    //画一个实心球
    70    circlefill(buffer, //画向缓冲区
    71    g_points[i].position.x,g_points[i].position.y,// aka 球的中心点的位置
    72    g_points[i].size, // 半径.
    73    (i == 0) ? makecol(255, 0, 0) : makecol(0, 0, 255)); //红色如果是玩家;否则为蓝色
    75    // 画一个轮廓球.
    76    circle(buffer, //画向缓冲区
    77     g_points[i].position.x,g_points[i].position.y, // aka 球的中心点的位置.
    78     g_points[i].size, // 半径.
    79     makecol(0, 0, 0)); //红色如果是玩家;否则为蓝色.
    81   }
    83   // 画接合点
    84   for (unsigned i = 0; i < g_joints.size(); i++)
    85    line(buffer, //画向缓冲区
    86     g_joints[i].p1.x, g_joints[i].p1.y, // 点 1.
    87     g_joints[i].p2.x, g_joints[i].p2.y, // 点 2.
    88     makecol(0, 0, 0)); // 黑颜色.
    89    );
    91   // 打印指令.
    92   textout(buffer, font, "Left Mouse Button - new big ball Right Mouse Button - new small ball",
    93     125, 1, makecol(0, 0, 0));
    95   textout(buffer, font, "Arrow Keys - move red ball",
    96     300, 592, makecol(0, 0, 0));
    98   show_mouse(buffer); // 画鼠标光标.
    100   draw_sprite(screen, buffer, 0, 0);// 把缓冲区中的数据画向屏幕.
    101  } // while循环结束
    103  return 0;
    105 }END_OF_MAIN();

      33-101行包括了典型的游戏编程循环模式。游戏继续进行直到玩家按下ESC键退出为止。34-39行支持同时进行的键盘输入,因为你可以按下向上和向左箭头键来获取粗略的斜向运动。

      在41-61行,鼠标动作被捕获到全局变量mouse_b(用于按钮),mouse_x和mouse_y。如果你一直在使用一滚轮鼠标,你还可以使用变量mouse_z。我们对反向弹跳逻辑进行了一点硬编码以确保每次鼠标按下事件只有一个球下落。

      第63行调用doPhysics(),其目的是旋转车轮的线段,更新球位置,检测球碰撞和适当地改变它们的方向矢量。这个模块(350行的数学代码)有点深入了些,但它确实是一个一流的实现,值得你深入研究。

      余下的代码,65-101行,开始着色,在典型的示例程序中这属于常规实现部分。这里的着色用典型的双缓冲区技术,下一次屏幕变化被计算出来并进行脱屏绘制并在最的一毫秒进行缓冲交换(第100行)。这确保了视觉的连续性又减少了烦人的闪烁-对象看上去是随机地绘制的。在着色代码部分,对line()和circlefill()的调用是相当直接的:circlefill()以x,y,半径和填充颜色作为参数。

      textout_ex()函数的功能稍强于textout()(示于92-96行),允许你指定前景和背景颜色。Allegro提供例程以直接从GRX格式.fnt文件,8x8或8x16 BIOS格式.fnt文件,位图图象以及数据文件格式中装入字体。作为选择,你能导入一种大范围的Unicode字体,这可以通过写一个.txt脚本-它为每一范围的字符指定相应的不同的源文件-来实现。如果你想要支持TrueType,那么你需要AllegroTTF或相同功能的插件。
    最后,在第100行的draw_sprite()实现一个覆盖性复制新生成的位图到第14行创建的屏幕对象上。覆盖性复制意指只有非透明的颜色像素被复制。在本例中,我确信它已被退化成一个"blit"(块复制)转储。

      五、 Allegro的音频

      这个snooker演示程序只涉及到了一些最基本的图形和I/O函数,但是并没有用到Allegro的音频开发包。该包中的MIDI混频,音响效果和录音API,其效果达到或超过几乎每一个我所见过的专业的声音库。Allegro音频应用软件大量存在,包括WinCab-一个MP3和OGG Vorbis音乐唱片机,还有LouTronic Rhythm Box-一个鼓声生成合成器,它具有可全面融合到一起的snare鼓,低音鼓和hi hat的效果。下面我们简单地回顾Allegro音频API的一小部分。

      每一个使用音频的程序都应该调用reserve_voices()来指定数字和MIDI声音驱动程序分别使用的声音的数目。接下去,你能控制这些音频轨道的混合.

      你可以非常容易地象下面这样插入一个音轨:

    MIDI *midFile = load_midi("myfile.mid’);
    play_midi(midFile, TRUE);//连续循环

      对于更复杂的需要,你可以安装三个钩子函数之一,它们可以使你拦截MIDI玩家事件。如果被设置为非NULL,这些例程将在每次MIDI消息,元事件和系统独占的数据块中被分别调用。

      Allegro的数字音频系统被设计为从最基本的配置到可高度扩展的。你能容易安装读取器和写入器来处理新的或者不同的音频文件类型, 例如:

    register_sample_file_type("mp3",load_mp3,NULL);//安装MP3读取器

      当正播放数字音频时,你可以随时编辑它。下列代码改变将在播放一个样本参数时改变该样本(用于操作循环播放的声音):

    void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);

      你能改变音量,平移音频数据并清除循环标志,在下次执行到循环末尾时,这将停止该样本。如果在播放相同样本的好几个副本,这会调整它遇到的第一个副本。如果该样本没有播放,对它没有任何影响。

     

    用C++实现跨平台游戏开发之Irrlicht引擎

      Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。通过使用Direct3D(Windows平台),OpenGL 1.2或它自己的软件着色程序,可以实现该引擎的完全跨平台。尽管是开源的,该Irrlicht库提供了可以在商业级的3D引擎上具有的艺术特性,例如动态的阴影,粒子系统,角色动画,室内和室外技术以及碰撞检测等(见图1)。


    图1.Irrlicht 3D引擎

      Irrlicht是一个德国神话故事中的一种动物的名字,它能够发光和飞翔,可以在大部分的沼泽地附近发现它。单词"Irrlicht"是两个德国单词("irr"意思是疯狂的;而"Licht"意思是光)的组合。在英语中,它被译为"鬼火"。

      Irrlicht十分幸运地为一个巨大的活跃的开发团队以大量的工程所支持。然而,因为Irrlicht主要由游戏名家Nikolaus Gebhardt所设计,所以该游戏在设计上十分连贯。你可以在网上到处发现有Irrlicht的增强程序,如可选用的地形生成器,入口生成器,输出器,world层生成器,相关教程和编辑器等。而且,它独立地创建了到Java,Perl,Ruby,BASIC,Python,LUA甚至更多种语言的绑定。而最为重要的是,它是完全自由的。

      二、 Irrlicht特性

      在深入分析API之前,请让我更具体地介绍一下Irrlicht提供给了3D游戏开发者哪些功能:

      ·一个可以运行于Linux以及Windows 98,ME,NT,2000和XP(MacOS在计划之中)等操作系统之上的引擎

      ·针对Direct3D 8生成器或Direct3D 9生成器(可选)提供了Anti-aliasing支持

      ·可换肤的GUI环境(包括一个很酷的具有金属质地的带阴影的皮肤),给一些老式的对话框加上漂亮的外观

      ·场景管理系统,它允许无缝的室内/室外过渡

      ·角色动画系统,带有骨骼和变形目标动画功能

      ·一个特殊的效果系统,包括粒子效果(雨,烟,火,雪,等等),告示板,灯光贴图,环境,地图,模板缓冲区阴影,雾,纹理动画,视差贴图,凹凸贴图,还有更多

      ·内建的材质支持,包括支持Pixel and Vertex Shaders版本1.1到3.0,ARB Fragment and Vertex程序以及HLSL(GLSL正在计划中)

      ·.NET语言绑定,这使得引擎可用于所有的.NET语言例如C#,Visual Basic.NET以及Delphi.NET

      ·一内建的平台独立的软件生成器,特性有:z-缓冲,Gouraud阴影,alpha混合和透明性,还有快速的2D绘图(见图2)

      ·你久已期待的2D绘图功能,例如alpha混合,基于关键色的位图复制,字体绘制,以及混合3D与2D图形

      ·能直接导入常见的建模文件格式:Maya,3DStudio Max,COLLADA,DeleD,Milkshape,Quake 3 levels,Quake2 models,DirectX,Pulsar,My3DTools,FSRad以及Cartography Shop

      ·能直接从BMP,PNG,Photoshop,JPEG,Targa和PCX导入纹理

      ·快速而易用的碰撞检测与响应

      ·为快速的3D运算和容器模板库进行了优化处理

      ·直接读取档案(可能是压缩的,如.zip文件)

      ·集成了快速的XML分析器

      ·为实现容易的本地化开发提供Unicode支持


    图2:基于Irrlicht的游戏Yet Another Space Shooter(YASS),这里显示的是一个静态游戏帧中的令人吃惊的着色效果
      三、 在Irrlicht中的特殊效果

      在本文的例子中,我将向你展示怎样使用模板缓冲区影子技术,还有粒子系统,告示板,动态光以及水表面场景结点等技术。参见图3。


    图3.结合动态的光和水进行的场景着色

      Irrlicht引擎自动地检查是否你的硬件支持模板缓冲;而如果不支持,则不启动阴影。在这个演示程序中,在方法createDevice()中的’shadows’标志被置位,以产生从一个动画角色投下的动态影子。如果这个实例程序在你的PC上运行太慢,可以把这个标志设置为false或者干脆再买一块更好些的图形加速卡。

      为能够使用Irrlicht.DLL文件,你需要链接到Irrlicht.lib库文件。你可以在工程设置对话框中设置这个选项;但是为了容易实现,你可以使用一个pragma预编译注释命令。方法createDevice()负责实例化根对象-它使用引擎完成一切事情。参数如下:

      ·deviceType:设备类型。当前你可选取Null设备以及软设备,如DirectX8,DirectX9或OpenGL。

      ·windowSize:要创建的窗口的大小或全屏幕模式。这个例子中使用512x384。

      ·bits:每像素位数(当在全屏幕情况时)。仅允许值为16或者32。

      ·fullscreen:指定是否你想使设备运行于全屏幕方式。

      ·stencilbuffer:指定是否你想使用模板缓冲区以用于绘制阴影。

      ·vsync:指定是否你想启动vsync(仅在全屏幕情况),可选。

      ·eventReceiver:一个接收事件的对象,可选。

      为适合于本实例环境,你将装载一个3D Studio Max文件(一幢房子)。该房子看起来并没有什么特别的,但是Irrlicht引擎能为你创建一个相当酷的纹理贴图。只需使用造型操纵器并为之创建一个planar纹理贴图即可:

    #include <irrlicht.h>
    #include <iostream>
    using namespace irr;
    #pragma comment(lib, "Irrlicht.lib")
    int main()
    {
     //让我们假定用户在本例中使用OpenGL
     //当然,也可以指定DirectX 8, 9, 等等.
     video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
     //创建设备,如果创建失败立即退出。
     IrrlichtDevice *device = createDevice(driverType,
     core::dimension2d(640, 480), 16, false, true);
     if (device == 0)
      return 1;
     video::IVideoDriver* driver = device->getVideoDriver();
     scene::ISceneManager* smgr = device->getSceneManager();

      我对从这个导入文件产生的发射光线颜色的效果并不满意。下列代码显示怎样实现这些步骤:

    scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds");
    smgr->getMeshManipulator()->makePlanarTextureMapping(
    mesh->getMesh(0), 0.008f);
    scene::ISceneNode* node = 0;
    node = smgr->addAnimatedMeshSceneNode(mesh);
    node->setMaterialTexture(0, driver->getTexture("wall.jpg"));
    node->getMaterial(0).EmissiveColor.set(0,0,0,0);

      四、 水动画

      你将添加的第一个特殊的效果是水动画。为此,WaterSurfaceSceneNode导入一个造型文件并使之象水表面一样地波动。如果你让这个场景结点使用一种相当好的材质如MT_REFLECTION_2_LAYER,那么它看起来相当酷:

    mesh = smgr->addHillPlaneMesh("myHill",
    core::dimension2d(20,20),
    core::dimension2d(40,40), 0, 0,
    core::dimension2d(0,0),
    core::dimension2d(10,10));
    node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30);
    node->setPosition(core::vector3df(0,7,0));
    node->setMaterialTexture(0,driver->getTexture("water.jpg"));
    node->setMaterialTexture(1,driver->getTexture("stones.jpg"));
    node->setMaterialType(video::EMT_REFLECTION_2_LAYER);

      作为输入造型,你可以创建一个陡峭的平面造型,但是你也可以为此使用任何其它的造型。你甚至能重用room.3ds输入文件(它看上去确实很奇怪)。该实例还用一个普通的石头纹理模型来绘制所有另外的表面。

      五、透明的告示板和灯光

      第二个特殊的效果是很基本的但是非常有用:一个透明的告示板,伴之有一个动态的灯光。为产生这种效果,你只需要产生一个灯光场景结点,并让它四处飞行;而且,为了让它看起来更酷一些,可以把一个告示板场景结点依附到它上面:

    //创建灯光
    node = smgr->addLightSceneNode(0, core::vector3df(0,0,0),
    video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f);
    scene::ISceneNodeAnimator* anim = 0;
    anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),250.0f);
    node->addAnimator(anim);
    anim->drop();
    // 把告示板依附到灯光
    node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50));
    node->setMaterialFlag(video::EMF_LIGHTING, false);
    node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
    node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp"));

     

     六、 粒子系统

      下面介绍的这个特别效果更有趣:一个粒子系统。在Irrlicht引擎中,粒子系统既是组件化的,也是可扩展的,但是仍然易于使用。你只需要简单地把粒子发射器放到一个粒子系统场景结点,这样以来粒子看上去没有产生源。这些发射器可以据需要进行灵活配置,并经常带有许多参数,如粒子方向,粒子数量,以及粒子颜色等。

      当然,发射器类型有区别(例如,一个点发射器能够使粒子从一个固定的点上发出粒子)。如果该引擎提供的粒子发射器还不能满足你的要求,你可以容易地创建你自己的发射器。这只需简单地从IParticleEmitter接口派生一个新类并使用setEmitter()方法把它依附到粒子系统上去即可。

      下一个实例将创建一个盒子粒子发射器。你可能已经猜出,它从一个跳跃的盒中随机生成粒子。由参数来定义盒子,粒子的方向,每秒产生粒子的最小和最大数目,颜色以及粒子的最小和最大生命周期。

      一个完全由发射器组成的粒子系统将是令人生厌的,因为缺乏真实感。因此,Irrlicht支持粒子影响器-它负责在粒子到处飞扬时予以修整。一旦添加到粒子系统上,它们就能模仿另外的更真实的效果,象重力或风。在本例中的粒子影响器只是简单地修改粒子的颜色来产生一种淡出效果。

      可能你已经猜出,粒子影响器是通过派生IParticleAffector接口实现的,然后通过使用addAffector()方法把它添加到粒子系统上去。在你为该粒子系统设置了一种好看的材质后,你就有了一个看上去相当酷的野外宿营火的效果。通过调整材质,纹理,粒子发射器,还有影响器参数,你能容易地创建烟雾,下雨,爆炸,下雪等效果:

    scene::IParticleSystemSceneNode* ps = 0;
    ps = smgr->addParticleSystemSceneNode(false);
    ps->setPosition(core::vector3df(-70,60,40));
    ps->setScale(core::vector3df(2,2,2));
    ps->setParticleSize(core::dimension2d(20.0f, 10.0f));
    scene::IParticleEmitter* em = ps->createBoxEmitter(
    core::aabbox3d(-7,0,-7,7,1,7),
    core::vector3df(0.0f,0.03f,0.0f),
    80,100,
    video::SColor(0,255,255,255), video::SColor(0,255,255,255),
    800,2000);
    ps->setEmitter(em);
    em->drop();
    scene::IParticleAffector* paf =ps->createFadeOutParticleAffector();
    ps->addAffector(paf);
    paf->drop();
    ps->setMaterialFlag(video::EMF_LIGHTING, false);
    ps->setMaterialTexture(0, driver->getTexture,"particle.bmp"));
    ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

      七、 影子投射

      最后但也不容忽视一个问题是,你需要为一个动画角色产生一个动态的影子。为此,你装载一个Quake2.md2模型文件并把它放到你的world上去。为了创建影子,你只需要调用方法addShadowVolumeSceneNode()。你可能通过调用ISceneManager::setShadowColor()来控制影子的颜色;注意,这仅是全局可调整的,并影响所有的影子。好,下面就是你的产生动态影子效果的代码:

    mesh = smgr->getMesh("../../media/faerie.md2");
    scene::IAnimatedMeshSceneNode* anode = 0;
    anode = smgr->addAnimatedMeshSceneNode(mesh);
    anode->setPosition(core::vector3df(-50,45,-60));
    anode->setMD2Animation(scene::EMAT_STAND);
    anode->setMaterialTexture(0, driver->getTexture("../../media/Faerie5.BMP"));
    anode->addShadowVolumeSceneNode();
    smgr->setShadowColor(video::SColor(220,0,0,0));

      八、 游戏循环

      最后,你能进入由device->run()方法控制的游戏循环。该循环将不断运行,直到通过获取一个关闭窗口事件(例如在Windows操作系统下的ALT-F4击键)来退出设备。你必须在一个beginScene()和endScene()命令对之间绘制每样东西。beginScene()用指定的一种颜色清屏,如果需要的话,可以同时清除深度缓冲区。然后你就可以让场景管理器和GUI环境来绘制它们的内容。随着调用endScene(),每一样东西都被绘制到屏幕上去。在本例中,你还可以动态地在标题栏上显示帧每秒(FPS)数,这对于严肃的游戏开发者是十分重要的事情:

    scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
    camera->setPosition(core::vector3df(-50,50,-150));
    int lastFPS = -1;
    while(device->run())
    {
     driver->beginScene(true, true, 0);
     smgr->drawAll();
     driver->endScene();
     int fps = driver->getFPS();
     if (lastFPS != fps)
     {
      core::stringw str = L"Campfire FX example [";
      str += driver->getName();
      str += "] FPS:";
      str += fps;
      device->setWindowCaption(str.c_str());
      lastFPS = fps;
     }
    }
    device->drop();

      结束循环后,你必须删除先前用createDevice()方法创建的Irrlicht设备。通过使用Irrlicht引擎,你应该删除所有你用以’create’开头的方法或函数创建的所有对象。你可以通过简单地调用device->drop()来删除该设备对象。

      九、你可能喜欢的Irrlicht插件

      正如在前面所介绍的,Irrlicht有一群勤奋的独立开发人员并为之产生了大量的插件,也用之开发了相当多的游戏。这些开发者中提出的许多的改进被再次集成到Irrlicht的随后的发行版本中。下面我列举其中的几个例子,我想这会吸引许多颇有前程的开发者感兴趣:

      ·OCTTools,是一套用于Irrlicht的工具,由Murphy McCauley所创建,用于操作OCT文件相关的:输出器,加载器,甚至更多。

      ·ICE(Irrlicht通用引擎)是一个开发框架,它提供了一个工程的轮廓实现,从而加快了新工程的开发。

      ·MIM,由Murphy McCauley所创建,是一个非常有用的基于XML的文件格式,可用于Irrlicht的加载器,转换器及其各种工具。

      ·My3D是一个开发工具包,它能够使你把来自于各种3D包(3DStudio MAX,Giles,等等)中的灯光贴图场景直接输出到Irrlicht中。

      ·Dusty引擎允许程序员创建"任务"-这些"任务"可以完成程序员想做的任何事情。之后,这些任务被添加到一棵普通的任务树上去,而每个任务可以有它们希望数目的孩子任务。任务"组"允许游戏设计者在一棵完整的树上执行普通的操作,例如暂停,继续或破坏等。

      ·Irrlicht RPG(Erring Light)是一个3D 绕行走游戏引擎,最初是针对RPG类游戏开发的。

      ·2D 图像和精灵类组成了一个很有用的库,它扩展了Irrlicht的2D能力。

      ·Zenprogramming站点,提供第一个针对Irrlicht的非正式的外部地形生成器,此处也提供很多相关的教程。

     

     

               

    再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

    展开全文
  • 现在2D电脑游戏都用什么游戏引擎开发? 除了cocos2dx和unity。 想用C++开发单机游戏,直接用Win32 API或者dx感觉好麻烦
  • 三维游戏引擎开发-渲染

    万人学习 2015-04-12 20:28:28
    介绍移动设备,介绍一款游戏引擎具备的要素,并依次进行开发实现,采用标准C++语言进行开发,需要有扎实的C++基础
  • 浅析游戏引擎开发

    千次阅读 2008-09-11 17:30:00
    第25 卷第1 期Vol125 No11长春师范学院学报(自然科学版)Journal of Changchun Normal University(Natural Science)2006 年2 月Feb12006浅析游戏引擎开发翟军昌(渤海大学公共计算机教研部, 辽宁锦州 121000)[摘 要]...
     第25 卷第1 期
    Vol125  No11
    长春师范学院学报(自然科学版)
    Journal of Changchun Normal University(Natural Science)
    2006 年2 月
    Feb12006
    浅析游戏引擎开发
    翟军昌
    (渤海大学公共计算机教研部, 辽宁锦州 121000)
    [摘 要] 该引擎的开发技术主要是使用C + + 语言, DirectX811 开发包与软件工程思想, 并综合运用
    了计算机图形学, 人工智能等知识。该引擎的主要工作是进行游戏中的数字建模、碰撞运算、物体成
    像、玩家角色控制等操作, 以及播放正确的音量和声音输出等必要的功能。
    [关键词] DirectX开发包; 地图编辑器; 角色扮演; 游戏引擎
    [中图分类号] TP317    [文献标识码] A    [文章编号] 1008 - 178X(2006) 01 - 0055204
    [收稿日期] 2005 - 12 - 26
    [作者简介] 翟军昌(1978 - ) , 男, 辽宁丹东人, 渤海大学公共计算机教研部教师, 从事计算机教学研究。
    1  引言
    电脑游戏作为一种娱乐方式越来越为人们所接受。对于电脑游戏来说, 游戏引擎是用于控制游戏功能的
    主程序, 如接受玩家控制信息的输入, 选择合适的声音以合适的音量播放等。2D 游戏或者3D 游戏, 不管游
    戏是怎样的形式(是角色扮演游戏、即时策略游戏、冒险解谜游戏或是动作射击游戏) 都有类似的起控制作
    用的代码。游戏引擎相当于游戏的框架, 框架打好后, 关卡设计师、建模师、动画师可往里填充内容。
    2  需求分析
    游戏引擎是一个很复杂的系统, 在这个设计中主要涉及到了以下几项功能:
    (1) 光影处理: 光影处理是用来处理游戏场景中光源对游戏中的人、地、物所影响变化的效果。
    (2) 物理系统: 用于模拟现实生活中的物体物理运动的一个系统。
    (3) 碰撞检测: 碰撞检测在游戏引擎中如此重要, 原因是现实生活中随处都有碰撞的发生。
    (4) 画影成像: 这是游戏引擎一项必不可少的功能, 否则在游戏中将看不到游戏的图像。
    (5) 输入与输出: 提供给玩家与游戏交互的功能, 这也是游戏与电影的区别。
    3  系统设计
    311  功能设计
    作为一个游戏引擎, 它必须是可用的、稳定的、可维护的。它的主要功能有如下几点:
    (1) 图像处理: 曲线绘制, 图像成像, 阴影生成, 粒子效果。
    (2) 输入处理: 鼠标和键盘数据处理, 游戏文件装载, 脚本读取。
    (3) 输出处理: 游戏信息输出, 玩家信息显示, 游戏存档建立, 音乐、音效输出, 图像输出。
    (4) 游戏逻辑处理: 控制剧情发展, 控制人物移动, 控制画面显示。
    312  结构设计
    游戏引擎开发采用的是三层结构模型:
    第一层是游戏引擎的基础, 它包括图像处理系统, 输入输出系统和音乐、音效系统。
    第二层是接口层, 设定上层与底层的访问接口。
    采用接口技术的好处就是更新底层实现的时候, 只要接口不被修改, 那么就不需要改动上层代码, 实现
    系统层次化结构提高了系统的可维护性与可重用性。
    ·55 ·
    第三层是游戏工具库, 在这里提供了游戏开发的一些辅助工具, 主要是封装了一些对底层实现的操作。
    它包括地图编辑器、脚本解析器、人物对话模块、角色类、NPC 类和物品类等等一些在游戏中用到的模块。
    313  游戏引擎的IPO 图
    图1  IPO 图
    图2  引擎整体结构图
    4  系统实现
    411  引擎开发基础和开发环境配置
    41111  引擎开发工具的选择
    在本次开发游戏的引擎开发中, 我们使用DirectXSDK开发包与VC + + 610 编译器。
    41112  游戏开发的核心知识
    游戏开发需要多方面的知识, 它包括很多非计算机专业和计算机专业方面的知识。开发一个游戏引擎,
    最基本的数据结构的知识是必不可少的, 如队列、堆栈、数组、链表、树、递归等等。
    数字建模是数学的术语, 也是计算机游戏的术语。一般情况下游戏中的每一个对象, 人物、动物和植物
    包括水、气体等非生物都要进行数字建模。
    412  引擎图像子系统的实现
    41211  采用图片拼接的方式来编辑地图, 将待绘页面分成n 个单元格, 在每个单元格中贴入我们想要的对
    象部分, 贴入后设置该图块的属性。
    41212  图像子系统的功能分析
    需求: 实现2D 贴图、地图合成、序列动画、基本图形图像绘制、屏幕渲染、画面显示、粒子系统。
    413  引擎的输入输出子系统与声音控制子系统
    ·56 ·
    41311  输入输出方式
    在windows 中获取鼠标和键盘信息是使用消息方式来获取的。在游戏中, 同样也是使用消息方式来获取
    键盘和鼠标信息。因为, 游戏的输入不仅由用户来提供操作键盘和鼠标消息, 有时候比如在剧情发展的时
    候, 需要虚拟键盘和鼠标消息来自动化游戏的进行; 有时我们要对键盘和鼠标的消息进行处理来实现一些效
    果, 比如当鼠标移动到屏幕的边缘时, 我们要滚动地图。这样就必须实现实时的截获鼠标和键盘消息, 然后
    处理。
    41312  输入输出子系统的实现步骤
    在这里使用的是DirectX 的DirectInput 库来完成输入消息截取的。游戏的运行过程大致可以分成擦除、
    移动、绘制、等待、重复这几个步骤。
    确定了在什么位置获取输入后, 接下来就要看具体的实现过程了。DirectInput 和DirectDraw 一样是虚拟
    设备, 也就是说不管底层的硬件是如何实现的, 只要符合标准的接口, 都可以通过DirectInput 来获取输入。
    DirectInput 的实现过程是Win32 应用程序→Direct 输入→HEL (硬件仿真层) 或HAL (硬件抽象层) →硬件设
    备驱动→设备。理论上DirectInput 可以支持所有的输入设备如鼠标、键盘、游戏摇杆、方向盘、踏板等, 但
    在本文中用到的只有键盘和鼠标, 所以只要获取键盘和鼠标消息即可。
    下面是设置DirectInput 的基本步骤:
    (1) 通过调用DirectInput8Create ( ) 来创建IDirectInput 接口, 返回值是IDirectInput8 接口。
    (2) 查询设备的GUID
    (3) 调用CreateDevice () 传递一个GUID : GUID SysKeyBoard 主键盘的GUID ; GUID SysMouse 主鼠标的
    GUID。
    (4) 设置设备的协作等级, 通过调用IDirectInputDevice8 : : SetCooperativeLevel () 来完成。
    (5) 调用SetDataFormat () 来设置每一个设备的数据格式。
    (6) 使用IDirectInputDevice8 : : SetProperty () 设置你想要的任何设备的性能。
    (7) 调用IDirectInputDevice8 : : Acquire () 来获取设备, 即与设备关联。
    (8) 调用IDirectInputDevice8 : : GetDeviceState () 来获取设备的数据, 在这里有两种方式实现数据采集方
    式, 一是直接模式; 二是缓存模式。
    41313  声音子系统实现的步骤
    实现音乐和音效处理, 我们用到的是Directx 中的DirectSound 和DirectMusic 库。DirectSound 是控制音效
    的, DirectMusic 是控制音乐播放的, 它是一种新的基于DLS 数据的实时音乐编排和回访技术。
    操作DirectSound :
    (1) 初始化DirectSound , 声明DirectSound 对象, 调用DirectSoundCreate ( ) 创建DirectSound 对象。
    (2) 设定协作等级, 调用SetCooperativeLevel () 函数, DirectSound 一共有四个协作等级: 普通级、优先
    级、排他级和Write Primary 级。
    (3) 建立缓冲, 声明DirectSound 缓冲, 调CreateSoundBuffer () 来创建缓冲对象。
    (4) 把声音写入缓冲, 锁定( Lock () ) 、写入、解锁( Unlock () ) 。
    (5) 控制声音播放: 播放声音, 调用play () 函数; 停止播放声音, 调用stop () 函数; 控制音量, 调
    SetVolume () 函数; 调整频率, 调用SetFrequency () 函数; 改变声道平衡, 调用SetPan () 函数。
    414  游戏工具库开发
    41411  地图编辑器与脚本解析器的概述
    地图编辑器与脚本解析器是游戏开发的重要工具, 它们综合利用底层的操作来实现游戏开发过程中比较
    高级的功能。
    41412  地图编辑器的作用与功能介绍
    地图编辑器主要的功能是创建、编辑和保存游戏场景地图文件。游戏场景地图一般分为三层结构, 地面
    层、物体层、天空层。地面层是用来贴入游戏场景的最底层图片的, 如土地, 沙漠, 草地这些都可以归结到
    ·57 ·
    地面层; 物体层在这里不单单是一层, 物体层可分为上层和下层, 上层的物体可以遮挡人物, 下层的物体可
    以阻挡人物, 所以在设计中把人物定位在物体的下层; 天空层是用来作效果处理的, 如想实现天黑效果, 你
    不得不在物体层的上面加上一张黑色图片。创建一张游戏场景地图主要有以下几个步骤: (1) 装载进入背景
    图; (2) 显示背景图; (3) 在图上画出格子; (4) 在某一格子贴入确定的景物; (5) 设置景物属性; (6) 保
    存地图
    41413  地图编辑器技术实现
    41414  脚本解析器技术实现
    5  测试
    在游戏引擎开发完之后, 游戏的创作就由设计师与美工来完成。首先, 创作游戏剧本, 确定了剧本之
    后, 我们就要对剧本进行分镜处理, 确定在什么场景出现什么人物, 和什么样的人物有什么样的对话; 其
    次, 使用地图编辑器来制作游戏场景地图; 最后, 编写游戏的脚本文件, 编写时要确定关卡和事件发生地
    点, 人物对话就按分镜处理后的剧本就可以了。
    6  结论
    综上完成了一个通用的2DRPG游戏引擎的基本功能。该引擎的主要特点是采用了模块化设计思想来构
    建引擎的底层程序, 因此该引擎具有较强的扩展性和可维护性。该引擎的工具库具有高度的可重用性, 只需
    经过少许的改动就可以适应新格式地图的编辑。该游戏引擎是按照网络游戏引擎设计的, 所以游戏引擎可以
    进一步的升级为一个网络游戏的引擎, 用于网络游戏客户端程序的开发。如果对引擎的底层图形系统进行优
    化, 可以将引擎升级为215D 的引擎。本文限于篇幅部分环节省略, 部分程序代码没有给出。
    [参考文献]
    [1 ]Andre LaMothe. Tricks of the Windows Game Programming[M] .中国电力出版社,2004.
    [2 ]唐明理. 学VC 编游戏[M] . 四川电子音像出版中心,2004.
    [3 ]Stephen Prata(美) . C + + Primer Plus[M] . 人民邮电出版社,2002.
    [4 ]John Vlissides. DesignPatterns[M] .机械工业出版社,1995.
    [5 ]荣钦科技. 游戏设计概论[M] . 北京科海电子出版社,2003.
    [6 ]Stephen C. Dewhurst. C + + 程序设计陷阱[M] . 中国青年出版社,2003.
    Analyzing the Development of Game Engine
    ZHAI Jun - chang
    (Public Computer Teaching & Research ,Bohai University ,Jinzhou 121000 ,China)
    Abstract :The development technology of this engine mainly uses the C + + language ,the DirectX8. 1 SDK,contains the
    thought of software engineering ,and utilizes the knowledge of computer graphics ,artificial intelligence ,and so on. The main
    task of this engine is to implement physical modeling ,clash checking ,object imaging ,player controlling ,music playing ,
    sound outputting and so on.
    Key words :directXSDK;map editor ;role player game ;game Engine
    ·58 ·
    展开全文
  • 从超级大白到游戏引擎开发工程师,我经历了什么

    千次阅读 多人点赞 2020-06-30 08:53:27
    从超级大白到游戏引擎开发工程师,我经历了什么 写在前面 大学四年经历总结 知识准备 项目经验与实习经历 简历 其它 论目标与方向的重要性 写在前面 本人目前为即将毕业的大四毕业生,但限于自己实力有限,接下来所...

    写在前面

    本人目前为即将毕业的大四毕业生,但限于自己实力有限,接下来所讲述的内容均为自己的个人心得,如有不足之处还请指点。本文主旨在于帮助那些想要从事游戏开发的有梦想的小伙伴做一些思想指导,希望能提供或多或少的帮助,同时也作为自己的大学经验总结

    个人校招经验总结请看:

    参加数十次校招后,我做了以下总结(游戏开发岗)

    大学四年经历总结

    本人为双非大学本科学生,大学就读软件工程专业,由于自己非常喜欢动漫和游戏,在高中的时候便有了自己的目标,当考上大学后决定选择与动漫和游戏最贴近的专业,但由于自己非艺术生,因此选择了软件工程。这是我选择软件工程专业的原因。

    虽然有比较明确的方向,但是大一刚刚接触软件相关的东西(代码)就发现,自己对电脑简直一窍不通,大一学的第一门语言是C#,除了C#,其它学科基本都能拿到优秀以上的成绩,但仅仅专业课险些挂科,由此可见我当初的编程实力如何。甚至怀疑自己是不是适合做软件开发,同样也对自己的未来有些迷茫,最严重的时候竟然对代码产生了恐惧心理。自己的导师也曾认为我不会成为她眼里重点扶持的“人才”。

    但是由于自己性格原因,天生不服输,或者说自己的目标非常明确,我就不信自己做不到。于是在大一下半年学习C++的同时,我开始在网上大量搜集相关语言教程,别人或许看一遍就会,我当时甚至看了n遍也才大概理解编程语言的基础语法。我觉得自己和别人比的弱点在于,高中之前基本没接触过电脑,完全不懂电脑软件怎么运行的。虽然自己起步慢一些,但我不想就此放弃,毕竟我是属于“后发制人”类型的。就是这样强迫自己一遍一遍看相关教程,C++那门课的成绩终于拿到了优秀。这个过程说起来简单,但却着实让我废了不少心思,真的。

    专业成绩有了一点起色之后,我就开始尝试去做自己喜欢的事——开发游戏。虽然这么说,对于当时的我来说仍然是一件非常困难的事,游戏怎么做出来的,和代码有什么关系,我当时什么都不知道,甚至没听过Unity这个词。当时没有一个人帮助我,没办法,还是得靠自己,找网上的教程吧,于是从大一暑假,我开始接触到了Unity。

    刚开始接触Unity的时候,我发现,嗯,完全不懂什么东西,即便我学过C#,有一点软件基础。当时硬是在完全不懂代码是什么意思的情况下跟着网课做了一个小游戏出来,现在想想真是佩服自己哈哈。虽然会C#,但是Unity编写的代码我完全没看过,后来过了一段时候才知道那个叫API,吐了,当时自己有多菜简直不忍直视。。。

    硬记API肯定是记不住的,但是当时好多Unity的功能都不清楚,不知道该从哪学起,而且问题是没人教我呀。做个小游戏出一堆Bug,还不知道问题在哪,真是哭了,鬼知道自学到底有多难,而且在Unity学习群里总有一堆人说Unity简单,UE4难,这真是想要打击死我呀,Unity那里简单了,难死了好吗,对于我这个新手来说。在陷入不知如何学习Unity的困境时,我的转折点出现了······

    有一次学校科协在一次活动中展示了VR眼镜,对于刚接触Unity两三个月的我来说,这个东西简直就是宝贝,我立刻就上前询问这个眼镜是不是学校有相关的研发实验室,因为有VR眼镜的地方,肯定有人会Unity,这样如果我能加入的话,或许能让自己快速掌握Unity。

    其实我一直认为机会是由自己创造的。正因为这次偶然看到VR眼镜,我加入了我们大学虚拟现实实验室学习,平时在由我们大学的一位博士成立的公司工作,重点研究虚拟现实,我是怎么进去的呢,说起来也简单,询问VR眼镜的出处后,我向实验室投出了自己的第一份简历,内容如下:
    在这里插入图片描述
    嗯,,,,怎么说呢,这个无论怎么看都不算是简历,技术含量几乎为零,虽然很难拿得出手,但如果连试都不试就轻易放弃这个机会,这一定不是我,而且一个刚刚大二的学生会这些或许已经不容易了。于是我投递了属于自己的第一份“简历”,出人意料的是,我靠这个简历拿到了自己的第一个‘offer’,加入了我们大学一位博士成立的初创公司,在他的指导下开始学习虚拟现实相关的技术(使用Unity)。

    在博士的指导下,我有了更明确的方向性,最重要的是,其它小伙伴都在使用Unity做项目,这让我感觉到一种归属感——我不再是一个人了。有时候孤独是一件很可怕的感受,他会让你感到无助,人是群居动物,需要一种叫“安全感”的东西,在博士的帮助下,我有了这种安全感,让我能坚持做自己喜欢的事。

    曾在实验室工作到深夜返回校园:
    曾在实验室工作到深夜的校园
    博士教会了我很多东西,他带我参加各种虚拟现实类竞赛,辅导我完成项目设计,就这样,我在大二上半年寒假和他一起参加了一次国际比赛,并参与答辩,那是我第一次坐飞机,也是第一次参加大型比赛,第一次上了中央新闻的一个镜头,总之,受益匪浅。

    曾参加的比赛现场:
    在这里插入图片描述
    在这里插入图片描述
    我渐渐意识到做项目对于熟悉工具的重要性,如果让我现在学一个新的工具,我一定会从实际项目入手,去熟悉它的操作。于是在大二下半年,我决定靠自己的能力参加比赛,不过不是创新创业竞赛了,而是游戏开发比赛,以此提升自己的编程能力。

    给我印象最深的就是在大二下半年参加的完美世界游戏创意GameJam,也是我第一次完全靠自己的能力参加比赛。(后话是完美世界也是我目前所在的公司,而且实习过程中参与的项目正是那次比赛的孵化项目。)我有幸通过审核并参加了成都赛区比赛,在那几天里认识了一群和我有着相同梦想的小伙伴,让我意识到自己并非孤军奋战,经历了三天三夜的创作,我参与完成了自己的第一款小游戏——《光与影》,我的队友是来自同一所动画学院的学生,他们都很优秀,虽然自己参与的项目未获奖,但从那以后,我对于Unity的理解变得更加深入具体了。
    参赛现场,深夜中开发游戏的参赛者们:
    在这里插入图片描述
    在经历完美世界的GameJam后,我的实力大涨(对比以前),原因就是做了自己的游戏,代码也完全是按照自己的思路完成的,那个时候的水平大概能做轻量级小游戏了。

    我并未因为自己实力有一点提升就骄傲自满,因为接下来有两个重量级的比赛:腾讯高校游戏创意设计大赛和网易高校游戏创意设计大赛。这两个比赛时间相近,一般参加比赛的同学只会选择其中一个项目参加,而我两个比赛都报名了,并且因此结识一堆志同道合的伙伴,他们都非常优秀,他们有进腾讯,网易,搜狐畅游,巨人网络的,由此可见,有梦想并且愿意为止拼搏努力的结果在大部分情况都会是好的

    为了完成这两个比赛,重要的是取得名次,拿到offer,我以第一位目标,竭尽全力完成自己的工作,因为要同时兼顾两个项目,我不得不用一整天的时间开发游戏,写代码,当时从早上八点开始,一直做到晚上12点,连续肝了一个月后,我成功完成了两款游戏的开发,并提交了项目。用于参加网易比赛的作品名字叫《山海鲲》,参加腾讯比赛的作品名字叫《移动迷宫》,移动迷宫是我找了一位美术共同完成的,我担任策划和程序工作。都说本科如果写够20000行代码就能达到平均水平,如果是按这个标值来算的话,我在参加完这几次比赛就达到这个标准了。

    我知道作品《山海鲲》做的不太好,所以重点完成腾讯比赛项目,毕竟腾讯的比赛含金量也更高。当时对自己的作品还是挺满意的,如自己所料,游戏通过了初赛,如果进入复赛,就能去腾讯总部参加决赛了,然而这并非一帆风顺,作品未通过复赛,当时的自己深受打击,真的是期望越大,失望越大,我在收到比赛结果后好久都蹲在原地站不起来,有人可能认为这有点小题大做,但是如果从我的角度思考的话,每天做十几个小时,坚持一个月完成的项目被别人否定确实不是很好受,当时受到了较大打击,但自己终需要面对现实。

    本人第一款用心之作《移动迷宫》:
    在这里插入图片描述
    如果因为一两次失败就轻易放弃,那一定不是我,而且如果放弃太早,你永远也不知道自己会错过什么。我随时关注各个游戏公司举办的游戏创意设计大赛,尽可能多交朋友,多增加经验,但是又想在目前的技术水平上有所突破,因此接下来还有很多需要自己学的东西,还有很多事要做,之后我有参加了吉比特的游戏比赛,当然结果还是重在参与了,在之后我决定要进一步提升自己的编程水平。

    因为之前重点关注比赛和项目经验,自己的算法能力比较薄弱,数据结构还理解的很浅,甚至没搞懂动态规划那些东西的意思。但是目前不知不觉已经大三了,大三下半年是实习的黄金时刻,或许不能通过比赛拿到offer了,我应该靠编程能力冲击大厂。毕竟自己一直以进腾讯为目标的。

    在这之后,我开始关注大厂校招需要的能力和招聘时间等信息,生怕自己错过那些想去的公司的招聘,同时重新彻底学习C#,C++和数据结构,计算机网络,操作系统等大学基础知识,注意我是什么时候开始的:大三上半年寒假。重温这些知识真的太重要了,我甚至觉得之前的都白学了,或者说只理解了其中的皮毛,这次复习使我的编程能力(算法方面)有了一个层次的提升,之前感觉特别难的算法题,现在基本都能搞定,当然,复习的过程必须要刷题,但不是以数量为主,我一共刷了不到100道算法题,但却涉及到几乎所有常见类型的题,同时有思路的基本就不做了,剩下的就是经常巩固那些思想,记住一个例题就好了。就这样,忙碌了一个寒假,我开始准备迎接大厂 的春招面试题了。

    在大三下半年的时候,我参加了数十次笔试,但因为当时实力不足,好多题都不会,不过重点是秋招,现在最重要的是总结面试题和面试经验,就这样到了春招结束阶段,我依然没有通过一次笔试,但是却基本摸透了游戏开发岗位的重点考察知识了,接下来就往这个方向学就行了。虽然这么说,这对我的打击依然很大,因为当时的自己非常担心自己能不能冲进游戏大厂,甚至能不能进入游戏行业,而我需要做的不是望而却步,而是迎难而上,目标越难实现,才越有意义。使我惊讶的是,我在春招即将结束的时候,通过了字节跳动和完美世界两家大厂的面试通知。

    通过这两家企业的笔试,让我感受到了自己的努力成果,没想到自己第一次面试就是国内大厂,我很害怕无法通过面试,而且自己有预感无法通过第一次面试,于是一直提示自己,最重要的是总结经验,然后决战秋招。

    不知道是不是第一次面试太紧张了,面试的形式是视频面试,问我的问题也很简单,就是我当时满脑子都是空白,不管怎么写都写不出答案,结果可想而知。失望是有的,但最重要的是总结经验,这次面试一点也不难,没有通过真的纯是因为经验不足。于是我反复看自己的面试过程表现(自己录屏),下一次面试绝对不能犯同样的错误。

    怀着依然紧张的心情,我开始了完美世界的面试。

    首先是模板式开头:自我介绍,我把自己反复改过后熟记的自我介绍说了一遍之后,面试官并没有急着问问问题,反而是问我为什么要加入游戏行业,他问我的这个问题正是我所想表达的一点,于是把自己的内心真实想法说了一遍,然后又告诉他我的大学经历和选择游戏开发的过程,在分享完我的经历之后,我完全没有紧张感了,这使我抓住了面试的节奏,于是接下来面试官所问我的问题我都回答上来了,(虽然有的可能不准确),他当时主要问我的知识包括计算机图形学和算法题,Unity这些工具基本不问,(详细的内容我会在下一篇博文详细介绍我的笔试面试经验,这里不做过多说明)。就这样,通过近一个小时的面试后,我大概能感觉到,这次面试我能通过。

    结果如自己所料,HR在第二天中午通知我面试通过了,准备和我预约下一次面试时间,就这样,我怀着更加紧张激动的心情预约了下一次面试时间。

    因为离下一次面试还有两三天时间,因此我在这两三天时间里拼命记之前遇到的每一个面试题答案,然后还重新看了一遍数据结构,操作系统,计算机图形学这些知识,当然,最重要的还是算法题,能刷多少就刷多少。

    很快就迎来了我的第二次面试,这一次面试官和上次不同,直接开始问我算法题和那些基础知识,幸运的是,他问我的题竟然是我这两三天刷过的!!,然后很顺利的回答上了他的问题,算法题之后就是计算机图形学,这时候我就意识到计算机图形学在游戏开发中的重要地位了,虽然这门课不是我大学必修,但是我之前在各个大厂招聘上看到了这个技能,于是课下自己学了计算机图形学,没想到会这么重要。和上次面试一样,我顺利回答出了面试官的问题,最后又聊我为什么想做游戏之类的话题,当然这方面是我的擅长点,所以一个小时的面试顺利结束,接下来就是等待通知结果。

    大概过了三四天后,HR通知我面试通过,岗位是游戏引擎开发,问我什么时候能来公司实习。

    我终于看到自己努力的成果了,而且还是我最想成为的游戏引擎开发工程师。

    但好景不长,学校要在大三下半年统一组织学生去企业实训,这使我面临要放弃在完美世界实习的岗位,当时的我甚至想逃课去实习,但是我做不到。这是我第一个想要的offer,但却不得不亲手放弃,或许这就是我不想再读研的原因之一吧。

    我按照学校的要求,参加一所企业的校企培训,当然,所学的东西和游戏一点关系没有,但是既然来了,我不能就这样白白浪费这次机会,学校的培训也不是说一点价值没有,只是它能帮助大部分学生找到一份工作,因为参加培训,我失去了黄金实习期,意想不到的是,完美世界HR知道我的情况后,竟然同意我晚些去实习,这确实是喜出望外的,然而,那个时候已经是到了找正式offer的时候了,同时,腾讯和网易的游戏创意设计大赛又开始了。

    不管在什么时候,我都会有自己的目标,这是我的优点:总会让自己忙起来。在企业培训的这段时间里,我想做的有三件事:

    1. 学习培训内容,以防止无法进入游戏行业,这是最坏的打算了;
    2. 参加游戏比赛,争取这次通过比赛拿到大厂offer;
    3. 准备游戏公司面试,熟练掌握春招总结的算法和所需技术;

    这三点是需要同时进行,但是给我的时间不到三个月,不管怎么说,人的经历是有限的,我不能把这三件事都完美完成,于是只能减少最不重要的事所消耗的时间,那就是培训内容了。在白天企业培训的时候,当所学的东西基本都知道的时候,我会把时间腾出来做游戏项目,早上和晚上的时候会刷算法题,参加游戏公司笔试和总结面试经验。当时忙到什么程度呢,可以用没有时间玩游戏来形容。

    就这样,我同时报了腾讯和网易的比赛,并且按时提交了参赛作品,这也是我大学以来最后的两次比赛。

    参加网易高校游戏创意设计大赛作品:《第二人格》
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    腾讯高效游戏创意设计大赛参赛作品:QQ球,大学最后参赛作品
    在这里插入图片描述
    虽然两个游戏都是自己的用心之作,但还是只通过了初赛。

    对现在我来说,比赛的结果已经不重要了,这些小游戏让我的大学生活充实而又充满回忆。

    紧接着自己的最后目标就很明确了:通过秋招找到一份游戏开发offer,这是一个不光要拼实力的过程,还要拼自己的耐力;在周围同学一个个找到自己想要的offer的情况下,很少有人能够不担忧自己的处境。幸好自己在春招的时候有所准备,否则自己真的可能会面临“失业”的风险。经过自己的努力,我拿到了几个大厂的offer,大概包括:多益网络,网龙,猎豹移动,taptap(心动网络),盛趣游戏等,还有一些小一点的公司(关于笔试和面试经验我会单独出一片博文做详细说明,这里不做介绍)。但通过比较,还是完美世界的最有吸引力,因为完美世界的岗位是游戏引擎开发,这样我所接触到的技术会和游戏客户端开发有较大差异。于是我想冒一个险:放弃这些offer,转去完美世界实习(不确定能否转正)。

    其实当时的做法实属有些冒险,因为我在没有和任何公司签订三方就贸然拒绝掉这些已经拿到的offer,确实是不合理的举动,但是我又不想做毁约的事,因此当时内心非常矛盾,不过从后话来说,当时做这样的决定是正确的:在完美世界转正比较容易,而且自己所做的工作还有薪水都是找到的offer中最佳的,现在想想,自己的秋招之路也没有那么顺利,但最终的结果确实是最优的了。很幸运自己做出了正确的选择

    从大三到 大四即将毕业,我的第一个offer是完美世界给的(实习),最后一个也是(转正)。很高兴认识你,完美世界。

    参加社团活动,担任班干部

    关于游戏,我想说的就告一段落了。大学是自己曾经最想进入的地方,我想在这里做自己喜欢的事,除了游戏,我在大一的时候竞选班委,成为班级学习委员,同时还加入了社团,分别是街舞和网球,虽然这两项自己都不是很擅长,但却给自己的大学生活增添了不少乐趣,我喜欢音乐,喜欢和大家一起训练,享受在冬天的时候,穿着半袖但依然满头大汗地跳着舞;我喜欢网球,我希望自己能成为大学里的“网球王子”,但因为学习游戏开发,我不得不在大二的时候把时间多分给学习游戏上。但不管怎么说,自己的大学生活真的很充实。

    自己所在的街舞团:
    在这里插入图片描述

    论目标与方向的重要性

    最近临近毕业,我的很多朋友都和我讨论过未来该做么走的问题,有的犹豫不知该考研还是找工作,有的因为保研差了几名,一战失误而不知要不要二战,有的没有找到好的工作而不知该怎么办,有的不知道要选择去哪里发展·····其实每个人都要面对他自己的问题,谁也不知道选择走那条路才是最佳方案,就比如说,曾经有很多人劝过我不要进入游戏行业:加班多压力大,这是事实,我也很清楚,但有时候我就会问自己:现在的生活你满意吗,你在做你自己想做的事吗,你喜欢游戏吗,你有梦想吗,你还是曾经的那个自己吗?现在的我可以很自信的回答:我在做自己喜欢的事,我不会后悔以前的决定,我还是曾经的我。

    在和朋友们谈到那些问题时,我总会告诉他们一句相同的话:你自己要走什么路完全由你自己决定,如果一直犹豫不决,你不光会后悔之前没做出正确的决定,以后的你还会后悔现在没做出正确的决定。

    有方向是非常重要的,如果没有目标,再努力也不过是无用功,大学时要明确自己的方向,大学之后更应如此。

    虽说自己的大学成绩还不错,但是我并未想过保研或者考研,因为我深知即便读研,也无非是自学自己喜欢的东西,就像大学时自己所经历的一样,我并不是否认读研的意义,只是我很清楚自己接下来要走的路是什么,就像大学的时候一样。

    大学成就

    从大一到大四,我做到了很多同学没做到的事:做了5款以上小游戏,都是用来参加比赛的作品;通过英语四六级,拿到了几次国家级比赛奖项,一共读了200+本书(虽然大部分都是与游戏开发相关)通过了几个大厂面试,拿到不错的offer,毕业前获得了优秀毕业生称号。总体来说,取得的成绩基本能让自己满意了。

    被游戏填满的大学生活:
    在这里插入图片描述

    遗憾与不足

    在别人眼里,我有梦想,我在做自己喜欢的事,学校里拿到了一堆奖项,最后获得优秀毕业生称号;拿到了比较理想的offer,做别人羡慕的工作。但是,我的大学是完美的吗,肯定不是,遗憾是有的,而且有很多:因为受到疫情的影响,我没想到自己大四一年只在学校待了一天(党员转正时离开实习岗位,请假一天),之后就再也没机会返校了,我并不喜欢收到学校的约束,但我喜欢学校的图书馆,再多看两本图书;喜欢学校的实验室,再和伙伴们参加一次比赛,无论结果如何;喜欢和朋友们一起旅游,一起看电影,一起聚餐,一起毕业。而现在,我只能让我的同学帮我邮递毕业证,然后悄无生气地从大学消失;

    我想通过自己的努力冲进腾讯,但腾讯拒绝了我;我想在大学谈一次恋爱,但是喜欢的那个人拒绝了我;我想做一款自己的游戏,但是我现在还没有能力一个人完成;我想大学能过得轻松一点,多和同学出去玩,但是游戏填满的我的大学;我想继续作为一名学生学习知识,但是我毕业了。

    大学四年总结

    回想自己大学四年时间,过的很充实,有自己的作品,做了自己喜欢做的事,,拿到了较满意的offer,从大一到大四,自己变强了,但还没变秃。

    我不求自己在各方面都出众,但我希望自己能在自己喜欢的领域创出自己的一片天地,每个人都希望自己能够不平凡,但是却生活在这个平凡的世界里。 人活着,有梦想是一件很不容易的事,坚持更不容易,希望在未来的某一天,自己回首往事,最后发现,我还是那个曾经的天真的有梦想的少年。

    有人说,大学毕业了,青春就结束了,我的青春还在吗,我不知道,我只知道自己不能停下脚步,自己还有很多事要做,还有很多东西要学,还有很多经历要体验。

    接下来如果有机会的话,我可能会选择继续深造,当然是和游戏有关的专业了,但是从目前来看,我的学生时代要到此结束了,那么,是时候离开大学这个新手村了,江湖再见,后会有期。

    展开全文
  • 准备写个游戏引擎开发文档

    千次阅读 2010-07-19 17:00:00
    El游戏引擎开发文档即将发布
  • 3D游戏引擎开发

    千次阅读 2020-03-06 14:23:51
    在软件开发中,游戏开发这个方向看起来目标很明确,但其实是个领域很广的方向,入门的时候如果得不到指点一二,很容易误入歧途,相反,如果走这条路之前能得到前人的一些指路,是可以事半功倍的。 一 平台与编程...
  • 一些Cocos游戏引擎开发工具

    千次阅读 2018-01-20 14:33:15
    Cocos引擎 常用的工具 合图工具TexturePacker ...这篇摘要主要来讲讲一些实用的游戏开发方面的工具,本期以cocos引擎为主。 Cocos引擎 介绍引擎的垃圾话就不说了,自行百度,我相信没多少人想看。
  • 三维游戏引擎开发-图形理论基础

    万人学习 2015-05-16 17:00:44
    通过学习,掌握三维图形学的基本理论,三维数学知识,并根据数理进行实践,纯软件编码方式(不调用OpenGL,DX,或者相关图形库)实现一个简单的三维场景,巩固三维理论,为后续课程打下基础。
  • 用C++实现跨平台游戏引擎开发

    万次阅读 2008-10-29 06:39:00
    游戏开发系列 用C++实现跨平台游戏引擎开发  你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地...
  • 跨平台游戏引擎开发

    千次阅读 2015-07-23 18:13:15
    目前移动平台开发涉及Andoird,ios,windows-phone,blackberry等多个平台,每个平台的开发接口都不同,同一款游戏要想部署到不同平台需要大量的重复劳动,严重影响开发成本,跨平台游戏引擎能使用统一的开发接口,能...
  • Java 2D 游戏引擎开发(一)

    千次阅读 热门讨论 2017-11-11 22:02:43
    不过很可惜,一直没有找到一个合适的java写的2d游戏引擎。前几天偶然发现了一本书,科学出版社出版的《Java游戏编程》,译自David Brackeen的同名作品。这本书较为细致地从awt动画讲起,一直讲到用java写3d引擎。扫...
  • 就像在汽车中,引擎完成主要的...为了让游戏开发更加简单容易,主要的开发者开始授权他们的基本游戏引擎,如 Unreal。而且,随着手机和平板游戏的出现,所需预算比以前更少,对 JAVASCRIPT 和HTML5 游戏引擎的需求大
  • Python游戏引擎开发(一):序

    万次阅读 2015-08-31 22:54:36
    首先开发Swift需要一台mac,对于我这个寒士而言,过于奢华了一些;Java吧,又感觉太胖了,不够苗条,身材不好,也看不上。最后遇到了Miss Python,先前也和她打过交道,不过感觉语法怪怪的,总是出现>>>这类符号...
  • 所以我们的引擎开发的第一个阶段就是创建窗口和重绘界面。 在上一章《序》中我们讲到本次开发用到了PyQt,也就是Qt的Python版。在开始实现引擎功能之前我们要先了解一下Qt,这里先了解渲染机制。 在Qt中,绘画用到的...
  • 【Cocos2d-x游戏引擎开发笔记(26)】中文和自定义字体

    万次阅读 多人点赞 2013-08-04 00:47:05
    【Cocos2d-x游戏引擎开发笔记(2)】在屏幕上渲染文字 中有介绍,下面来看看怎么样从XML文件中读取中文。   在TestCpp里有源代码XML的内容按照下面的方式组织: chinese 关卡 step 步 beststep 最佳成绩: ...
  • Python游戏引擎开发(一):序 Python游戏引擎开发(二):创建窗口以及重绘界面 Python游戏引擎开发(三):显示图片 Python游戏引擎开发(四):TextField文本类 Python游戏引擎开发(五):Sprite...
  • Python游戏引擎开发(二):创建窗口以及重绘界面 Python游戏引擎开发(三):显示图片 Python游戏引擎开发(四):TextField文本类 Python游戏引擎开发(五):Sprite精灵类和鼠标事件 动画的原理 ...
  • 使得运动的物体有尾巴的效果,可以使用CCMotionStreak...这里我使用【Cocos2d-x游戏引擎开发笔记(12)】粒子系统实现与用户交互的特效的例子,使得效果更加的酷。 在头文件中加入: CCMotionStreak* strike; 然后
  • 说起这个Sprite啊,涉及过2D游戏研究领域的看官应该都听说过它。它中文原意是“精灵”,不过在不同人的眼中,它所表示的意义不同。比如说在cocos2d中,它可以是一张图片。不过在flash中,Sprite是一个类似于“层”的...
  • 博主在大学里学的专业就是软件开发与游戏设计,所以对于游戏这个行业一直都有着浓厚的兴趣,却因为 ... 最开始研究过一段时间的AndEngine游戏引擎,但是它的性能让我实在是不敢恭维,而且还有一些bug待完
  • VOLCANO是一款MMORPG(大型多人在线角色扮演)3D网络游戏的开发引擎,用作支持用户快速并简单地开发具有真实游戏环境和丰富游戏玩点的游戏,具有完全自主的知识产权,且未参考或使用任何开源游戏引擎. VOLCANO引擎分为...
  • 首先要给大家说明的是:软件工程知识,就是利用好现有游戏引擎这样省时省力比如吉利吉利系统就是开源免费的,做自己的引擎也是好主意,这样可以充分享受DIY的乐趣! 我最近回味魔兽学院 MAN AT WORK !2永远的羁绊 这个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 116,675
精华内容 46,670
关键字:

游戏引擎开发