【译】什么是游戏开发实体系统框架(一)

什么是游戏开发实体系统框架(一)

原文链接:http://www.richardlord.net/blog/what-is-an-entity-framework

原文很长,译文将分开几部分,此为第一部分。



上周我发布了Ash(一个Actionscript 游戏开发的实体系统框架),后来很多朋友问我说:“什么是实体系统框架(entity system framework)?”。下面是我对此做出的非常长的解答(译者注:确实有些啰嗦。。。):

实体系统目前已经越来越流行,比如众所周知的Unity、较少人知道的Ember2Xember和我自己的Ash。它们流行的原因很简单:简单的游戏框架、简明的代码模块以及简易的使用。

这篇文章我将向大家展示,传统的游戏逻辑(game loop)是如何进化为一个实体框架的。由于目前我正在使用Actionscript做开发,所以文章中的实例代码都是用Actionscript的,但是此框架对所有语言都适用。

关于示例

贯穿全文,我将会使用一个简单的Asteroids游戏作为示例,Asteroids就像一个简化版的大型游戏,麻雀虽小五脏俱全,包含一套典型的系统:刷新系统、物理系统、AI系统、输入系统、NPC系统。

游戏主循环(The game loop)

要了解为什么要用实体系统,首先我们需要明白传统的游戏循环是如何工作的。Asteroids游戏的主循环可能是这样工作的:

function update( time:Number ):void
{
  game.update( time );
  spaceship.updateInputs( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.updateAI( time );
  }
  spaceship.update( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.update( time );
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.update( time );
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.update( time );
  }
  collisionManager.update( time );
  spaceship.render();
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.render();
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.render();
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.render();
  }
}

这个主循环会以一个特定的周期被循环调用来更新游戏状态,通常是60次/秒或者30次/秒。一般在主循环里我们会处理各种重要的游戏逻辑,比如更新游戏中的各种物件、检测他们之间的碰撞、绘制等等。

上面的代码是一个非常简单的主循环,因为:

1. 游戏本身很简单

2. 游戏只有一种状态

在过去,我曾经在一个电视游戏的主循环一个函数中,塞进了超过3000行的代码。这让它看起来一点都不优美,一点都不简明。这就是过去我们编写游戏的方式,并且不得不伴其一生。

实体系统框架起源于一次对游戏主循环重构的尝试。它假设游戏主循环就是一个游戏的核心,并且在现代游戏框架中简化游戏主循环比其他任何事情都重要,比如比将视图和控制分离更重要。

进化过程(Processes)

进化第一步,要回想一个模块被调用的过程(think about objects called processes)。这件模块可以被初始化、被更新、被销毁。这样的过程接口看起来可能是这个样子的:

interface IProcess
{
  function start():Boolean;
  function update( time:Number ):void;
  function end():void;
}

我们可以通过分解不同的过程来简化主循环,比如渲染过程、运动过程、碰撞处理等。然后我们可以创建一个过程管理器(process manager)来管理这些过程。

class ProcessManager
{
  private var processes:PrioritisedList;

  public function addProcess( process:IProcess, priority:int ):Boolean
  {
    if( process.start() )
    {
      processes.add( process, priority );
      return true;
    }
    return false;
  }

  public function update( time:Number ):void
  {
    for each( var process:IProcess in processes )
    {
      process.update( time );
    }
  }

  public function removeProcess( process:IProcess ):void
  {
    process.end();
    processes.remove( process );
  }
}

这是一个略显简单的过程管理器。这里要重点强调的是,我们必须保证各个过程的调用是按正确的顺序进行的(由add方法中的priority参数决定),并且我们必须处理一个过程(process)被从update循环中移除的情况。这样的话,你可能会想到,如果我们的游戏主循环被分解为多个子过程,那么过程管理器的update方法也就等价于过去的游戏主循环,子过程的集合也就变成了游戏的核心(the core of the game)。

绘制过程(The render process)

让我们以绘制过程为例。我们可以把过去游戏主循环中有关绘制的代码拉取出来,放进一个单独的过程,看起来像这样:

class RenderProcess implements IProcess
{
  public function start() : Boolean
  {
    // initialise render system
    return true;
  }

  public function update( time:Number ):void
  {
    spaceship.render();
    for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
    {
      flyingSaucer.render();
    }
    for each( var asteroid:Asteroid in asteroids )
    {
      asteroid.render();
    }
    for each( var bullet:Bullet in bullets )
    {
      bullet.render();
    }
  }

  public function end() : void
  {
    // clean-up render system
  }
}

使用接口

但是这并不是特别有效。我们仍然需要手动处理各种不同类型的类的刷新。如果我们有个所有可刷新类通用的接口,代码将会更一步的简化。

interface IRenderable
{
  function render();
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;

  public function start() : Boolean
  {
    // initialise render system
    return true;
  }

  public function update( time:Number ):void
  {
    for each( var target:IRenderable in targets )
    {
      target.render();
    }
  }

  public function end() : void
  {
    // clean-up render system
  }
}

然后我们的spaceship类的部分代码将会变成这样:

class Spaceship implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;

  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}

这里的代码是以2D游戏为例,但是3D游戏的原理是一样的。我们需要绘制图片,进而需要绘制图片所需要的位置和旋转信息,然后,render方法处理刷新的实现。

To be continued...



以上是此篇译文的第一部分,时间关系先写到这里,下篇继续,敬请期待。

【译】什么是游戏开发实体系统框架(一)

时间: 2024-10-14 07:46:43

【译】什么是游戏开发实体系统框架(一)的相关文章

【译】什么是游戏开发实体系统框架(终)

今天朋友提醒我说,我要翻译的这篇文章已经被翻译了,我一看,还真是,翻译的还不错.本着不重复造轮子的原则,本系列就不再往下翻译了(虽然只翻译了一点点...),大家如有兴趣请参看下面的译文: http://blog.csdn.net/aisajiajiao/article/details/19011259 但是翻译工作还是要继续的,下篇将进行一个flappy bird的教程翻译,敬请期待... [译]什么是游戏开发实体系统框架(终)

Unity3D游戏开发 地形系统(四)

http://mahaile.blog.51cto.com/2891586/771167 上一章我们讲解了 如何创建一个简单的游戏世界 这一章我们来 看看unity3d中的地形系统 废话少说 赶紧开始吧,,哈哈   首先创建一个新的场景    点击菜单栏中的 Terrain-> create Terrain 菜单       完成后如 下图       创建地形系统的时候 unity会按默认的 宽高 图像分辨率,纹理分辨率 等创建一个地形  不过不怕 这些我们都可以修改滴    如果需要在gam

[Android游戏开发]游戏框架的搭建

通常情况下,游戏开发的基本框架中,一般包括以下模块: 窗口管理(Window management):该模块负责在Android平台上创建.运行.暂停.恢复游戏界面等功能. 输入模块(Input):该模块和视窗管理模块是密切相关的,用来监测追踪用户的输入(比如触摸事件.按键事件.加速计事件等). 文件输入输出(File I/O):此模块用来读取assets文件下图片.音频等资源. 图像模块(Graphics):在实际游戏开发中,这个模块或许是最复杂的部分.它负责加载图片并把它们绘制到屏幕上. 音

草莓果园游戏开发系统源码开发

草莓果园游戏开发系统源码开发(微or电 158.1500.1390 小凡团队)草莓果园开发系统,草莓果园模式开发系统,草莓果园平台开发系统,草莓果园软件定制开发,草莓果园app开发. 草莓果园这个拆分盘简单的说就是:原始股就是果实.通过种植产生利息,利息大概一天有3.0%-3.6%左右,地里种植的果实x每日利率=每日收益(即每天产生的化肥).如果发展直推会员,那么每一位直推会员每天得到的利息的10%是领导的奖金.除了开地所需的最低果实(普通地块每块地最低种300果实,金地块每块地种3000)永久

【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)

1. SurfaceView 游戏框架实例 实例效果:就是屏幕上的文本跟着点击的地方移动,效果图如下: 步骤: 新建项目“GameSurfaceView”,首先自定义一个类"MySurfaceView",此类继承SurfaceView,并实现android.view.SurfaceHolder.Callback 接口,代码如下 package com.example.ex4_5; import android.content.Context; import android.graphi

Cocos2d-x lua游戏开发之安装Lua到mac系统

注意:mac ox ,lua version :5.15 下载lua官网的lua, 注意:最好是5.15以下,5.2的lua不支持table的getn()方法,这让我情何以堪.(获取table长度,相当与cout,size,length) 下载解压, cd 目录 make macosx sudo make install (是的,就是小写的install,虽然文件夹下的是INSTALL) ook,进入命令行,输入lua 看下,效果 Cocos2d-x lua游戏开发之安装Lua到mac系统,布布

青蛙王国系统养殖游戏开发

青蛙王国系统,青蛙王国理财系统,青蛙王国系统养殖游戏开发,咨询微信/电话:156-2272-1962. 玩家投资青蛙王国 游戏只需330元,30元是平台收取的注册费用,简单可以理解为租赁费用,300元作为会员开通一个基础青蛙池的基数,简单可以理解为开一个最低限度的青蛙池需300元,养300只青蛙形成一个青蛙池,根据当天的 拆分开率,拆分率为2%,则第二天产生300*2%=6只青蛙,刚开始通常每天可通过投放蝌蚪产生6.7只青蛙,1只青蛙1元.通过每天倍增,青蛙的基数就越来越大,每天繁殖的的青蛙就越

cocos2dx游戏开发——微信打飞机学习笔记(二)——游戏框架

一.游戏的基本框架: WelcomeScene    ——>    GameScene   ——>   GameOverScene ||                                       ||                                    || ∨                                      ∨                                   ∨ WelcomeLayer            

【读书笔记-《Android游戏编程之从零开始》】3.Android 游戏开发常用的系统控件(Button、Layout、ImageButton)

3.1 Button Button这控件不用多说,就是一个按钮,主要是点击后进行相应事件的响应. 给组件添加ID属性:定义格式为 android:id="@+id/name",这里的name是自定义的,不是索引变量."@+"表示新声明,"@"表示引用,例如:"@+id/tv" 表示新声明一个id,是id名为tv的组件:"@id/tv" 表示引用id名为tv的组件. 给按钮添加点击事件响应  想知道按钮是否被