说说flash游戏,引擎(一)分层结构
14:54 , Qizhi
接触商业游戏开发有一段时间了,泛泛纪录一些心得而已。
不论任何语言、任何游戏类型的引擎,不外乎以下这些功能:
1、输入、输出
2、逻辑控制 (逻辑、AI)
3、图形与渲染 (成像、物理、光影等)
由于Flash Player已经集成了输入输出控制,所以略过。优秀的引擎应该做到,这三个系统互相独立。尤其是,图形与逻辑的独立。
关于逻辑层,尤其是web game或social game,还要考虑逻辑由前端(flash)完成,还是后端语言完成的选择。两种选择各有优劣。优先选择前端则会为服务端节省大量资源,但是如果游戏希望在其它平台部署(比如IPhone),那意味着重复开发不可避免。Playfish的系列Social game都逐渐将逻辑由客户端实现,而服务端则只负责数据的持久化。
图形与逻辑在Flash游戏开发里是最常被混淆的。我参考过大量游戏的Source Code,类似“class Entity extends Sprite”的语句十分常见,将数据模块和显示模块混淆。我的意见是,一个游戏的Entity只存储其属性,而逻辑与控制应该交由相应的渲染层控制,我的一种结构(不同的游戏模式有不同的解决方案)如下:
1、EntityParams,存储一类Entity的配置、属性,方便序列化与反序列化。
2、Entity, 游戏元素的基类。
3、RenderClass,Entity的渲染单元
4、EntityFactory, 根据EntityParam生产各种Entity,并且指定其渲染模式的工厂。
比如拆出来一段配置:
<EntityParams alias="com.twofish.engine.entity.EntityParams">
<Type>Entity1</Type>
<MaxSpeed>300</MaxSpeed >
<CustomClass>com.twofish.engine.entity.Entity</CustomClass >
<RenderClass>com.twofish.engine.render.SpriteRenderer</RenderClass >
</EntityParams >
对应EntityParams配置,装配出Type为Entity1,MaxSpeed为300的Entity,其渲染方式为SpriteRenderer。如此,当有新的元素时,服务端只需要写入对应类型的meta数据,客户端修改一下配置文件即可,主程序完全没必要更新。由于控制逻辑和渲染逻辑独立,开发完成后,日常的维护和更新就变的相对轻松,更重要的是,这是一种能省很多钱的结构。
FPS指引擎每秒渲染的帧数,我们没必要追求高FPS,因为FPS在我的设计里有两个概念:一个是Flash Player自身FPS,另一个是游戏World的FPS。这两个应该独立。理由是:高性能。Flash Player高FPS下同时渲染多个DisplayObject,尤其是MovieClip时十分吃力。经过我的观察,人眼只需要FPS 15即可流畅的观察到动画过程。FPS 25已经时电视级的了。所以在把Flash Player的FPS控制的很低时,游戏数据、逻辑的运算(即引擎的FPS)就可以使用相对顺心一些。这也是我不赞同“class Entity extends Sprite”写法的原因。除了剔除不需要渲染的元素外,对于Flash Player本身的渲染模式,我们没有任何优化的入口,Adobe已经帮我们做的足够好了。但是对于游戏逻辑,我们还有很多很多压榨的手段。
以后会慢慢写一些关于数据结构、资源管理、版本管理、国际化、缓存、等角引擎、AI方面的经验
不论任何语言、任何游戏类型的引擎,不外乎以下这些功能:
1、输入、输出
2、逻辑控制 (逻辑、AI)
3、图形与渲染 (成像、物理、光影等)
由于Flash Player已经集成了输入输出控制,所以略过。优秀的引擎应该做到,这三个系统互相独立。尤其是,图形与逻辑的独立。
关于逻辑层,尤其是web game或social game,还要考虑逻辑由前端(flash)完成,还是后端语言完成的选择。两种选择各有优劣。优先选择前端则会为服务端节省大量资源,但是如果游戏希望在其它平台部署(比如IPhone),那意味着重复开发不可避免。Playfish的系列Social game都逐渐将逻辑由客户端实现,而服务端则只负责数据的持久化。
图形与逻辑在Flash游戏开发里是最常被混淆的。我参考过大量游戏的Source Code,类似“class Entity extends Sprite”的语句十分常见,将数据模块和显示模块混淆。我的意见是,一个游戏的Entity只存储其属性,而逻辑与控制应该交由相应的渲染层控制,我的一种结构(不同的游戏模式有不同的解决方案)如下:
1、EntityParams,存储一类Entity的配置、属性,方便序列化与反序列化。
2、Entity, 游戏元素的基类。
3、RenderClass,Entity的渲染单元
4、EntityFactory, 根据EntityParam生产各种Entity,并且指定其渲染模式的工厂。
比如拆出来一段配置:
<EntityParams alias="com.twofish.engine.entity.EntityParams">
<Type>Entity1</Type>
<MaxSpeed>300</MaxSpeed >
<CustomClass>com.twofish.engine.entity.Entity</CustomClass >
<RenderClass>com.twofish.engine.render.SpriteRenderer</RenderClass >
</EntityParams >
对应EntityParams配置,装配出Type为Entity1,MaxSpeed为300的Entity,其渲染方式为SpriteRenderer。如此,当有新的元素时,服务端只需要写入对应类型的meta数据,客户端修改一下配置文件即可,主程序完全没必要更新。由于控制逻辑和渲染逻辑独立,开发完成后,日常的维护和更新就变的相对轻松,更重要的是,这是一种能省很多钱的结构。
FPS指引擎每秒渲染的帧数,我们没必要追求高FPS,因为FPS在我的设计里有两个概念:一个是Flash Player自身FPS,另一个是游戏World的FPS。这两个应该独立。理由是:高性能。Flash Player高FPS下同时渲染多个DisplayObject,尤其是MovieClip时十分吃力。经过我的观察,人眼只需要FPS 15即可流畅的观察到动画过程。FPS 25已经时电视级的了。所以在把Flash Player的FPS控制的很低时,游戏数据、逻辑的运算(即引擎的FPS)就可以使用相对顺心一些。这也是我不赞同“class Entity extends Sprite”写法的原因。除了剔除不需要渲染的元素外,对于Flash Player本身的渲染模式,我们没有任何优化的入口,Adobe已经帮我们做的足够好了。但是对于游戏逻辑,我们还有很多很多压榨的手段。
以后会慢慢写一些关于数据结构、资源管理、版本管理、国际化、缓存、等角引擎、AI方面的经验
Aug
10
2009
Actionscript3单例模式对象的释放控制
22:15 , Qizhi
单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。通常定义一个单例类,使用类的私有静态变量指向类的唯一实例,并用一个公有静态方法获取该实例。如下面的类定义:
package com.moorwind
{
public final class Singleton
{
//Other members.
private static var _instance:Singleton;
public function Singleton(enforcer:SingletonEnforcer)
{
if(!enforcer)throw new Error("Singleton Error");
}
public static function getInstance():Singleton
{
if(!_instance)_instance = new Singleton(new SingletonEnforcer());
return _instance;
}
}
}
class SingletonEnforcer{}
单例类Singleton有以下特征:
1.它有一个指唯一实例的静态指针_instance,并且是私有的。
2.它有一个公有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。
3.它的构造函数使用了包内类的,这样就不能从别处创建该类的实例。
大多时候,这样的实现都不会出现问题。但是_instance指向的空间什么时候释放呢?更严重的问题是,这个实例的析构操作什么时候执行?如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面所示的代码无法实现这个要求。我们需要一种方法,正常地删除该实例。
C++中的析构函数可以帮助C++完美的实现这个功能,苏林的文章就写到了实现方法。Actionscript3只好采用一种很不优雅的方式,手工析构这个实例。
package com.moorwind
{
public final class Singleton
{
private static var _instance:Singleton;
public function Singleton(enforcer:SingletonEnforcer)
{
if(!enforcer)throw new Error("Singleton Error");
}
public static function getInstance():Singleton
{
if(!_instance)_instance = new Singleton(new SingletonEnforcer());
return _instance;
}
public static function destroy():void
{
_instance = null;
}
}
}
class SingletonEnforcer{}
//-----------------------------------------------------test:
package {
import com.moorwind.Singleton;
import flash.display.Sprite;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
public class SingleTest extends Sprite
{
private var instance:Singleton;
private var id:int;
public function SingleTest()
{
runTest();
id = setTimeout(testDestroy, 2000);
}
private function runTest():void
{
instance = Singleton.getInstance();
}
private function testDestroy():void
{
trace("destroy");
instance = null;
Singleton.destroy();
clearTimeout(id);
}
}
}
问题是,都要手工析构了,还创建单例干嘛...设计模式的滥用。
package com.moorwind
{
public final class Singleton
{
//Other members.
private static var _instance:Singleton;
public function Singleton(enforcer:SingletonEnforcer)
{
if(!enforcer)throw new Error("Singleton Error");
}
public static function getInstance():Singleton
{
if(!_instance)_instance = new Singleton(new SingletonEnforcer());
return _instance;
}
}
}
class SingletonEnforcer{}
单例类Singleton有以下特征:
1.它有一个指唯一实例的静态指针_instance,并且是私有的。
2.它有一个公有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。
3.它的构造函数使用了包内类的,这样就不能从别处创建该类的实例。
大多时候,这样的实现都不会出现问题。但是_instance指向的空间什么时候释放呢?更严重的问题是,这个实例的析构操作什么时候执行?如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面所示的代码无法实现这个要求。我们需要一种方法,正常地删除该实例。
C++中的析构函数可以帮助C++完美的实现这个功能,苏林的文章就写到了实现方法。Actionscript3只好采用一种很不优雅的方式,手工析构这个实例。
package com.moorwind
{
public final class Singleton
{
private static var _instance:Singleton;
public function Singleton(enforcer:SingletonEnforcer)
{
if(!enforcer)throw new Error("Singleton Error");
}
public static function getInstance():Singleton
{
if(!_instance)_instance = new Singleton(new SingletonEnforcer());
return _instance;
}
public static function destroy():void
{
_instance = null;
}
}
}
class SingletonEnforcer{}
//-----------------------------------------------------test:
package {
import com.moorwind.Singleton;
import flash.display.Sprite;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
public class SingleTest extends Sprite
{
private var instance:Singleton;
private var id:int;
public function SingleTest()
{
runTest();
id = setTimeout(testDestroy, 2000);
}
private function runTest():void
{
instance = Singleton.getInstance();
}
private function testDestroy():void
{
trace("destroy");
instance = null;
Singleton.destroy();
clearTimeout(id);
}
}
}
问题是,都要手工析构了,还创建单例干嘛...设计模式的滥用。
Jul
27
2009
SWF中的ScriptLimits标签
15:08 , Qizhi
今天读SWF file format spec,注意到一个tag——ScriptLimits 很有意思。很久很久以前,as2的时候,flash的递归被限制为256级。实际上,这个限制正是通过这个tag描述的。该标签包含两部分:MaxRecursionDepth和ScriptTimeoutSeconds,分别表示最大递归深度和脚本超时,类型均为UI16,表示可取值范围为0 ~ (2^16)-1之间,即,最大递归深度可以被设置为65535级(递归应当被避免),脚本超时也可以如此之长(千万别这么写,谋杀浏览器)。官方文档:
The MaxRecursionDepth field sets the ActionScript maximum recursion limit. The default
setting is 256 at the time of this writing. This default can be changed to any value greater
than zero (0).
The ScriptTimeoutSeconds field sets the maximum number of seconds the player should
process ActionScript before displaying a dialog box asking if the script should be stopped.
Flex中,Application和WindowedApplication都有两个对应的属性:scriptRecursionLimit(default 1000)和scriptTimeLimit(default 60)。
The MaxRecursionDepth field sets the ActionScript maximum recursion limit. The default
setting is 256 at the time of this writing. This default can be changed to any value greater
than zero (0).
The ScriptTimeoutSeconds field sets the maximum number of seconds the player should
process ActionScript before displaying a dialog box asking if the script should be stopped.
Flex中,Application和WindowedApplication都有两个对应的属性:scriptRecursionLimit(default 1000)和scriptTimeLimit(default 60)。
Jul
21
2009
http://www.moorwind.com/as3app/unity/test1.html
w/s/a/d或者方向键控制方向,鼠标控制视角。3D场景比较大,约1.6M。
这个场景全部是使用编辑器绘制的,一句脚本都还没写。新买的Macbook Pro MB470, 正在适应MAC下的开发。
关于Unity3D,在3D性能方面已经大大超越Flash,或者说已经不再一个数量级。
Windows版
http://panther.unity3d.com/download_unity/UnitySetup-2.5.0.exe
Mac版
http://download.unity3d.com/download_unity/unity-2.5.0.dmg
Jul
9
2009
Flash Builder文件系统不同步解决
12:54 , Qizhi
Jul
2
2009




