• About
    • Resume
A Game Developer also plays some guitar

[译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章

May 5, 2013 10:27 pm / Benny Chen

[译者的话(新浪微博@滚石,欢迎大家一起讨论)]
由于公司目前没有专业的技术美术(Technical Artist),在最近的项目开发中碰了不少壁。于是我就特地做了一些关于美术方面优化的研究,听了一些讲座,阅读了一些文章,你即将阅读的这篇就是其中之一,我觉得不错,并在阅读中获得了共鸣,所以也就决定将这片文章翻译为中文。一来希望在公司中,对于我们的美术设计师作为一个参考,另外分享出来也希望,如果能有那么一点点帮助到跟我们遇到同样困扰的团队或者美术或者任何同仁们,我将万分荣幸。

由于我是一个程序猿,所以翻译中难免有些话或者美术专业术语译的比较二的地方,还请谅解。

原文地址:Optimising Your Mobile Game (Less Lag, More Awesome)

———————————————————————-

你是否曾经开发了一个手机游戏,在你把它递交给reviewer时,本来满心希望它像百米冲刺一样高速运行,结果却步履蹒跚,甚至最后慢得跟爬行一样。

这很烂,不是么?我们意识到这本来是可以避免的,但很多小的错误和疏忽不断堆积,最终造成了程序的瘫痪:它太慢了!

介于我们一直这么粗心犯错,我们一定是忘了给自己的”角色属性表“加上预知未来的能力了

如果一直这样,那我们开发的游戏——AlieNation,将变得根本不能玩。幸运的是,我们停止了错误,并开始搜集大家的想法,对游戏进行优化(优化成为了我们开发中的新王牌武器!)

alienation

为什么我们从2D转向3D

考虑到从测试玩家和本地媒体获得的认可,我们决定创建一个3D摧毁型游戏(destruction game),以填补市场上的空白。很惊讶大多数的摧毁型游戏都是2D的,但3D才是摧毁型游戏应该的样子,因为3D版本的感觉是如此的棒。当然,你需要做更多的工作来优化你的美术流水线(art pipeline)。

高效和优化让我在一些甚至不知晓的领域中感觉到从容温暖,所以在这里有一些事情要和你们分享,我铭记它们于脑中,并且一直提醒我的团队遵循它们,以保证我们的3D游能够持续运行流畅。

何时选择3D(何时保留2D)

作为一个3D游戏美术,我得到的第一个关键教训就是,让所有的东西尽可能的保持低模——不要使用额外的不必要的顶点,如果你确实要让你的模型拥有精度,把它放置在贴图中。比如说,我们的建筑物都是用简单的方块创建而成,然后贴上带有质感的细节纹理。

当我们要为Vogel教授(它只在我们游戏的GUI和HUD中出现)建模时,首先尝试的是3D模型,但是最终,我们还是把它分解为像Flash中那样的多层2D平面。它运行非常流畅,看上去也更棒,事实最终的结果比用3D模型赞非常多!使用带有动画的2D平面,可以很容易的创造细节,使得Vogel教授看起来非常酷,并吻合整个游戏的艺术风格。

现在每次我看到它时(下图的左下角就是Vogel教授),还会忍不住幸福热泪 ;-(

vogelingame

不要在贴图(纹理)优化上偷懒!

贴图大小是最容易被大多数美术设计师忽视优化的,要知道,贴图会占用非常非常多的空间!

通过跟几个设计师聊天,我发现他们中很多人都习惯于创建他们觉得舒适的尺寸,比如512×512,这符合常理,没什么错误,但唯一的问题就是,设计师不会在导出贴图之前,将它们降低到一个更加合理的尺寸。

一个更小更高效的贴图文件,在放置到游戏中后,可以和一个超大的贴图文件看起来效果一样好!但是如果设计师所有的工作都是在错误的贴图尺寸中进行的,很不幸,所有设计师花费了大量时间绘制的漂亮美术细节,在游戏中被降低尺寸后,会被无情的抹杀

为了完全避免这个问题,我建议设计师应该在降低尺寸后对贴图做一些额外处理,亦或者是在创建时直接使用和在游戏中一样的分辨率。因为这样的话,设计师才能够精确掌控贴图中的每一个像素点。

文件格式,贴图重用和Shaders

PNG相比于其它很多格式没那么“邪恶”。相比于JPEG的有损压缩,它的压缩是无损的;它虽然对于Alpha透明的处理不像TGA那么出色,但是它既压缩文件同时又能保证足够好的Alpha映射,确实比其它的格式胜出一筹。

texfilesize

很多团队的教训是类似的:

不合理的贴图尺寸 + 不合理的文件格式 = 占用了太多的纹理空间 = 更慢的游戏 = 找到纹理并降低尺寸 = 丢失细节 = 浪费时间 = 非常沮丧的美术设计师 = 非常愤怒的美术总监

另外一个关于贴图非常有用的建议是——尽可能的重用它们。很显然,这个不光对贴图,对其它任何游戏资源都应该如此。在我们创建Alienation的过程中,我们没有创建新的贴图用于几乎很难被看到的武器和金属物体上,而重用了建筑物的贴图用在这些非常小而琐碎的物体上。只需要一点UV技巧,你永远不会发觉它们的贴图其实是被重用的。

非常重要的一点,你要选择合适的Shader程序。当然,法线高光Shader(Bumped Specular Shader)用到物体上时,看起来太他妈的赞了,但是应该使用特定的手机定制shader,让游戏更高效。在Unity中,这比较容易做到,因为Unity内置了一整套专门针对手机的shader。

什么时候采用Alpha贴图,什么时候使用Mesh(网格模型)

Alpha贴图的卓越优点是它可以让一个物体的部分透明,非常容易,并且也相对的比较经济(cheaply)[作者注:这里说“经济”是相对的,是从处理消耗(processing cost)的角度说的。每一个像素,多边形,shader,light,粒子和骨骼,都会消耗你的游戏的处理性能。]

然而,在有些情况下,mesh比alpha贴图要更高效。举例说,当我们为汽车创建一个轮子时,为了表现轮子中间的缺口,建立轮子的网格模型要比使用贴图+透明的方式,来得高效的多。

我意识到,在这里我有点自相矛盾了,因为之前我说过,要把更多的细节放在贴图中,而不是网格模型上。记住一点,没有绝对的优化技术,如果你拥有这样的能力可以在特定时候选择使用最合理的优化技术,就造就了你不仅仅是一个游戏美术设计师,而且是一个伟大的牛逼的设计师

thumbsup

粒子系统,draw calls,还有物理

对于任何游戏,视觉上的反馈(visual feedback)对于吸引玩家是异常重要的。如果对于玩家的操作缺少反馈,游戏会变得非常无聊,令人昏睡。

说到反馈:粒子效果是一个非常好的给玩家传递信息的方式。可能是一个子弹打到墙上产生的火花粒子效果,又或者是子弹射击一个纳粹分子的血溅粒子效果。

但是对于粒子,有些事情很容易犯错。第一点是对于粒子的贴图大小,对于贴图大小问题,本文的前半部分已经提到,如果你跳过了那部分,强烈建议你回到前面去看一看,我保证那部分内容能让你马上在贴图优化上变成一个更性感的人(而不是一个胡乱贴图的人):D

对于粒子系统的第二点是,很多人没有意识到,增加粒子个数,根本不会增加粒子效果的牛逼度——只会让游戏变得更慢。一个人可以用两种方式创建粒子效果:第一种是用尽可能少的发射数量,来达到一个最好的效果;另一种人就是搞2000个粒子,然后…慢慢跑吧…

你很少在现实游戏中见到过一个发射器包含2000个粒子效果,唯一的原因就是draw calls。

draw call是针对场景中每一个不同的物体而创建的(多一个draw call就会多增加一点游戏的处理时间)。对于粒子系统而言,在draw call上,很容易超载。

我喜欢制作一些粒子效果,但是每当我看到一些初级的设计师,看到一个漂亮而高效的粒子效果问:“只有10个粒子?太少了,这个如果用2000个粒子会更好”,我就巨他妈的沮丧,甚至肉体难受

particles

对于上图,厄….这…..你为什么要这么搞,非常差劲的初级美术。

物理

没有什么比准确的射击到一个建筑物,并看到它优雅壮丽的倒下更酷了。

为什么会这样?所有的这一切都是因为甜美而性感的物理系统。

当说到物理系统时,程序猿可是这方面的专家。所以接下来的一段话,可能是一种程序猿专用的非常难以解析的语言,所以如果您是一位美术,在这里就忍忍吧

在每一帧,物理系统都会更新很多次,物理会更新受其影响物体的位置,速度和其他一切跟运动相关的属性。每一帧物理的更新次数会直接影响到游戏的运行速度。所以加快游戏运行的一个方式就是减少每一帧物理系统被更新的次数。

这当然是一种可以尝试的方式,但是带来的坏处是会影响你的物理系统的准确性,所以平衡好每帧的更新次数,以获得最佳并最高效的物理效果是非常重要的。

一个例子,当我们减少了每帧物理更新的次数时,我们游戏中的一个球体可能穿过了一道墙,这…我觉得球穿墙可是不真实的,你呢?

所以要调节到一个最优的物理更新帧率是不容易的,这可花了我们公司的程序猿们好一段时间。

光照和天空盒

两件事情我会快速过下——光照和天空盒。

关于天空盒,很称奇的一点是其实你根本不需要使用它们作为天空!(我对吗?!?!)

一个非常棒的方式是在天空中包含背景艺术(background art),这使得能很经济简单的加入非常多的背景艺术和气氛到游戏中。

光照有点神秘,所以我直接了当,对于手机,最好使用平行光(directional light),或者如果你够幸运,加几盏点光(point light)也可以。在Alienation游戏中,在对light做了日以继日的研究后(我撒谎了,其实我就是google了一下unity light;-)),我发现聚光灯(spotlight)在手机游戏上是最消耗性能的光源,慎用。

结束这一切

本文中提到的所有建议,独立采纳其中的一条并不会让你的游戏马上得到改观。

但是如果你综合采纳所有的这些优化,你的游戏品质一定会马上得到质的提高,到时候,嗯哼,等着幸福的哭吧~

——————————————————————————

[译者的话]
个人觉得,这些建议非常好,并在游戏开发中时刻提醒自己遵循它们。但是因为大家开发的游戏都是各式各样的,使用的引擎也完全不同。不要把某种优化建议当成教条,应该选择最适合你们团队的。尽量多使用游戏引擎的profiling,以及时观察分析游戏中影响游戏系能的因素,而不要教条式的麻木follow各种优化建议。

Posted in: 3D, Game Programming, Some Experiences, Uncategorized, Unity

新浪微博API for MOAI

November 13, 2012 1:54 pm / Benny Chen

最近一个星期干了一件事情,因为游戏的需要,为Moai引擎集成了新浪微博的API,这样也算为开源又一次出了份力。

最近一年基本上是游走于游戏的脚本层,很久没有碰引擎代码了,这一周的工作充满了怀旧感,虽然复杂度不算高,但还是勾起了不少当年开发游戏引擎的记忆。

check it out from https://github.com/bennychen/moai-dev, branch: sina_weibo

同时该branch也集成了另一位Moai开发者的截屏API, from http://getmoai.com/forums/post4555.html

如何使用[sample code]


MOAISim.openWindow ( "test", 320, 480 )

viewport = MOAIViewport.new ()
viewport:setSize ( 320, 480 )
viewport:setScale ( 320, 480 )

layer = MOAILayer2D.new ()
layer:setViewport ( viewport )
MOAISim.pushRenderPass ( layer )

gfxQuad = MOAIGfxQuad2D.new ()
gfxQuad:setTexture ( "moai.png" )
gfxQuad:setRect ( -64, -64, 64, 64 )

prop = MOAIProp2D.new ()
prop:setDeck ( gfxQuad )
prop:setLoc ( 0, 80 )
layer:insertProp ( prop )

font = MOAIFont.new ()
font:loadFromTTF ( "arialbd.ttf", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.?!", 12, 163 )

textbox = MOAITextBox.new ()
textbox:setFont ( font )
textbox:setRect ( -160, -80, 160, 80 )
textbox:setLoc ( 0, -100 )
textbox:setYFlip ( true )
textbox:setAlignment ( MOAITextBox.CENTER_JUSTIFY )
layer:insertProp ( textbox )

--MOAISinaWeiboIOS.init( "you app id", "you app secret", "your callback url" )

function openCompileDialog( txt, imgFileLoc )
	MOAISinaWeiboIOS.compileDialog( txt, imgFileLoc )
	MOAISinaWeiboIOS.setListener( MOAISinaWeiboIOS.DIALOG_POST_CANCEL_CLICKED, function()
		print( "user clicked cancel post" )
		MOAIFileSystem.deleteFile( imgFileLoc )
	end )
	MOAISinaWeiboIOS.setListener( MOAISinaWeiboIOS.REQUEST_RESPONSE_WITH_RESULT, function()
		print( "post successuflly" )
		MOAIFileSystem.deleteFile( imgFileLoc )
	end )
end


function test()
	local frameBounds={
		left=0, 
		top=0, 
		width=1024, 
		height=768
	}

    local tmpFilename=MOAIScreenShotIOS.snapshotToFile( MOAIScreenShotIOS.PORTRAIT, frameBounds )
    print( "Saved at location: ", tmpFilename );
	print( MOAIFileSystem.checkFileExists( tmpFilename ))

	if ( not MOAISinaWeiboIOS.isAuthValid() )
	then
		MOAISinaWeiboIOS.login()
		MOAISinaWeiboIOS.setListener( MOAISinaWeiboIOS.DIALOG_LOG_IN_CANCEL, function() 
			MOAIFileSystem.deleteFile( tmpFilename )
		end )
		MOAISinaWeiboIOS.setListener( MOAISinaWeiboIOS.SESSION_DID_LOGIN, function()
			print( "successfully logged in" )
			openCompileDialog( "test", tmpFilename )
		end )
	else
		print( "already logged in, post" )
		openCompileDialog( "test", tmpFilename )
	end
end

timer = MOAITimer.new()
timer:setSpan( 1 )
timer:setListener( MOAIAction.EVENT_STOP, test )
timer:start()

Posted in: Game Programming, iOS, Lua / Tagged: lua, Moai, weibo, 微博, 新浪

稍后继续

October 12, 2012 11:49 pm / Benny Chen

这里已经荒废了一年有余,但我还活着。

一年里发生了很多事情,稍后回来。

Posted in: Something In The Way

Unity Developer ++

October 4, 2011 11:44 am / Benny Chen

去新公司工作已经有一个月了。通过这一个月时间的努力,使得这个世界上又多了一位Unity Developer – ME!

这一个月围绕Unity 3D引擎基本上做了这样一些事情:

  • 前两个星期用Unity完成了一个基本的demo;
  • 利用Unity的shader system完成物体的silhouette outlined effect,目前效果已经实现,但是在算法的优化和实现上还有一些问题。在国庆前给Unity公司的Ole发了邮件请求帮助算法的优化,Ole告诉我有解,但因为正忙于一年一度的Unite Conference,所以还没有时间给我详细回复。稍后应该会有一篇文章描述更多的实现细节;
  • 基于Unity的GUI system,完成了一些GUI animation,最重要的是实现了方便GUI animation的一些Utility class – Sprite2D, Sprite2DGroup。

另外的一些事情:

  • 开始使用Evernote,并且马上爱上它,太赞了!
  • 仍在挣扎适应公司同事不同国家的英文口音 >_<
  • 公司的五人足球队成立了,并且在第一场对英国大使馆的比赛中,我上演了帽子戏法(^^)

PS:今早不到10点就跑到了中关村的Starbucks,享受包场=.=

Posted in: Unity / Tagged: 3D, unity

Another Thread @ Moai Forum

October 4, 2011 11:07 am / Benny Chen

Does Moai support an API like ‘setTimeout’?

http://getmoai.com/forums/moai-sdk-developer-support/does-moai-support-an-api-like-settimeout/

Me
Hi,
Does Moai support an API like JavaScript’s setTimeout, which schedules a function execution after a specified time. I noticed there is a Moai class called MOAITimer, so I’m wondering if this class could be used for this purpose? I know a ‘setTimeout’ function could be easily realized on Lua level using MOAISim:getElapsedTime() and Lua’s ‘pcall’ function, but I’m just lazy and wonder if there is a shortcut that Moai has provided?
Thank you~

Josh
Moai doesn’t support that, but for convenience I’ll share the Lua function I use for this exact purpose:
(Hide some code)
EDIT: updated while investigating bug mentioned below. Will ensure this code works once bug is fixed.

Me
Thank you for the sharing, but the function gives the following error after I run:

cannot use ‘…’ outside a vararg function near ‘…’

I think ‘…’ are also needed for “function()” in the 5th line, so I added it.
However, after I ran the following code

function printAStr( str )	
    print( str )
end
callWithDelay( 1, printAStr, "helloWorld" )

It prints “userdata: 0x3192c4” instead of “helloWorld”, any clue for this? I think the core issue is how to pass arguments to the callback function of timer’s listener?

Josh
I made two mistakes in my function, which I have corrected above. You are correct I forgot to pass the … properly, and I also forgot that the timer listener callback receives the timer as the first parameter, which is why you were seeing the userdata print out in your test.

Me
seems still unworkable for the arguments pass…
Ok, so my question is how to pass arguments to callback function of timer’s listener?

Josh
It looks like there may be a bug in the listener with the last release. I’ve opened a bug on the issue. I also realized yet another error in my above code, and have corrected it. Hopefully that’s the last edit I have to do.

Patrick
Thanks for finding the bug. Won’t be able to get to it for a day or so. Sorry for the trouble!

Patrick
OK, finally had time to look at this. It looks like it’s working correctly. The code I used is below.

MOAISim.openWindow ( "test", 320, 480 )
function callWithDelay ( delay, func, ... )
  local timer = MOAITimer.new ()
  timer:setSpan ( delay )
  timer:setListener ( MOAITimer.EVENT_TIMER_LOOP,
    function ()
      timer:stop ()
      timer = nil
      func ( unpack ( arg ))
    end
  )
  timer:start ()
end

function printAStr ( str ) print( str ) end
callWithDelay ( 1, printAStr, "helloWorld" )

Me
It works! Thanks a lot

Posted in: Game Programming, Lua / Tagged: callWithDelay, lua, Moai, setTimeout

1st Day of Golden Week

October 1, 2011 11:51 pm / Benny Chen

黄金周第一天,将之前开发的Pacman移植到了iPad上。因为Moai引擎,移植变得很容易,只需要把input层做一些修改。我的第一个iOS上的game demo就此诞生

已经将代码更新到了github – https://github.com/bennychen/Moai-based-Pacman

Posted in: Game Programming, iOS, Lua / Tagged: ios, ipad, Moai, pacman

为SyntaxHighlighter添加新语言

September 4, 2011 1:36 pm / Benny Chen

因为经常要在博客里贴一些Lua代码,但是所使用的SyntaxHighlighter插件默认不支持Lua语言,所以去研究了一下如何为SyntaxHighlighter添加并激活一个新的语言,这里将过程和有同样需求的童鞋分享。(因为我添加的是Lua语言,下面的过程描述会以Lua为例,在添加你所需要的语言时,你只要将相应的项更换为你的自定义设置即可)

1. 从这篇博客里寻找所需要的语言:http://www.undermyhat.org/blog/2009/09/list-of-brushes-syntaxhighligher/;
2. 下载对应的shBrushXXX.js脚本,比如我下载的是shBrushLua.js,它看起来像这样:

SyntaxHighlighter.brushes.Lua = function()
{
	var keywords =	'break do end else elseif function if local nil not or repeat return and then until while this';
	var funcs = 'math\\.\\w+ string\\.\\w+ os\\.\\w+ debug\\.\\w+ io\\.\\w+ error fopen dofile coroutine\\.\\w+ arg getmetatable ipairs loadfile loadlib loadstring longjmp print rawget rawset seek setmetatable assert tonumber tostring';

	this.regexList = [
		{ regex: new RegExp('--\\[\\[[\\s\\S]*\\]\\]--', 'gm'),		css: 'comments' },
		{ regex: new RegExp('--[^\\[]{2}.*$', 'gm'),			    css: 'comments' },	// one line comments
		{ regex: SyntaxHighlighter.regexLib.doubleQuotedString,     css: 'string' },    // strings
		{ regex: SyntaxHighlighter.regexLib.singleQuotedString,     css: 'string' },    // strings
		{ regex: new RegExp(this.getKeywords(keywords), 'gm'),		css: 'keyword' },	// keyword
		{ regex: new RegExp(this.getKeywords(funcs), 'gm'),		    css: 'func' },		// functions
		];
}

SyntaxHighlighter.brushes.Lua.prototype	= new SyntaxHighlighter.Highlighter();
SyntaxHighlighter.brushes.Lua.aliases = ['lua'];

3. 使用FTP工具登陆到WordPress空间,进入到wp-content/plugins目录,新建一个目录,取一个有意义的名字,比如syntaxhighlighter-lua;
4. 将shBrushLua.js上传到新创建的目录;
5. 在该目录创建一个另一个shBrushLua.php文件,添加如下内容:

<?php
/*
Plugin Name: SyntaxHighlighter Evolved: Lua 
Description: Adds support for the Lua language to the SyntaxHighlighter Evolved plugin.
Author: Benny 
Version: 1.0.0
*/
 
// SyntaxHighlighter Evolved doesn't do anything until early in the "init" hook, so best to wait until after that
add_action( 'init', 'syntaxhighlighter_lua_regscript' );
 
// Tell SyntaxHighlighter Evolved about this new language/brush
add_filter( 'syntaxhighlighter_brushes', 'syntaxhighlighter_lua_addlang' );
 
// Register the brush file with WordPress
function syntaxhighlighter_lua_regscript() {
    wp_register_script( 'syntaxhighlighter-brush-lua', plugins_url( 'shBrushLua.js', __FILE__ ), array('syntaxhighlighter-core'), '1.1.1' );
}
 
// Filter SyntaxHighlighter Evolved's language array
function syntaxhighlighter_lua_addlang( $brushes ) {
    $brushes['lua'] = 'lua';
    return $brushes;
}
?>

6. 文件都准备完了,OK,进入到WordPress后台管理的Plugins下,应该能看到新添加的一项syntaxhighlighter-lua,激活它。

Done! It should work now!

其实新添加的js和php文件也可以放到SyntaxHighlighter插件本身的目录下,但是让它独立成插件的好处是,当SyntaxHighlighter升级时,你的个人配置不会因为覆盖而丢失。

Posted in: Some Experiences / Tagged: lua, new brush, plugin, syntaxhighlighter, wordpress, 新语言, 添加

基于Lua的State Pattern

September 4, 2011 12:56 pm / Benny Chen

代码来自于最近写的Pacman,更多请查看 – https://github.com/bennychen/Moai-based-Pacman

class.lua实现了在Lua中创建类的模拟,非常方便。class.lua参考自http://lua-users.org/wiki/SimpleLuaClasses

-- class.lua
-- Compatible with Lua 5.1 (not 5.0).

function class(base, init)
   local c = {}    -- a new class instance
   if not init and type(base) == 'function' then
      init = base
      base = nil
   elseif type(base) == 'table' then
    -- our new class is a shallow copy of the base class!
      for i,v in pairs(base) do
         c[i] = v
      end
      c._base = base
   end
   -- the class will be the metatable for all its objects,
   -- and they will look up their methods in it.
   c.__index = c

   -- expose a constructor which can be called by <classname>(<args>)
   local mt = {}
   mt.__call = function(class_tbl, ...)
   local obj = {}
   setmetatable(obj,c)

-- below 2 lines are updated based on the Comments from 'http://lua-users.org/wiki/SimpleLuaClasses'
--   if init then
--      init(obj,...)
   if class_tbl.init then
      class_tbl.init(obj,...)
   else 
      -- make sure that any stuff from the base class is initialized!
      if base and base.init then
      base.init(obj, ...)
      end
   end
   return obj
   end
   c.init = init
   c.is_a = function(self, klass)
      local m = getmetatable(self)
      while m do 
         if m == klass then return true end
         m = m._base
      end
      return false
   end
   setmetatable(c, mt)
   return c
end

State基类,包含三个stub函数,enter()和exit()分别在进入和退出state时被执行,onUpdate()函数将会在state被激活时的每帧被执行。

require "class"

State = class()

function State:init( name )
	self.name = name
end

function State:enter()
end

function State:onUpdate()
end

function State:exit()
end

StateMachine类,该类集成了Moai的MOAIThread类。MOAIThread类似于Lua中的coroutine,但是在Moai中被yield的MOAIThread,会在game loop的每帧中被自动resume,见StateMachine:updateState函数,利用此特点,来实现每帧执行State:onUpdate函数。

require "State"

StateMachine = class()

function StateMachine:init()
	self.currentState = nil
	self.lastState = nil
end

function StateMachine:run()
	if ( self.mainThread == nil )
	then
		self.mainThread = MOAIThread.new()
		self.mainThread:run( self.updateState, self )
	end
end

function StateMachine:stop()
	if ( self.mainThread )
	then
		self.mainThread:stop()
	end
end

function StateMachine:setCurrentState( state )
	if ( state and state:is_a( State ) )
	then
		if ( state == self.currentState )
		then
			print( "WARNING @ StateMachine::setCurrentState - " ..
				   "var state [" .. state.name .. "] is the same as current state" )
			return
		end
		self.lastState = self.currentState
		self.currentState = state
		if ( self.lastState )
		then
			print( "exiting state [" .. self.lastState.name .. "]" )
			self.lastState:exit()
		end
		print( "entering state [" .. self.currentState.name .. "]" )
		self.currentState:enter()
	else
		print( "ERROR @ StateMachine::setCurrentState - " ..
			   "var [state] is not a class type of State" )
	end
end

function StateMachine:updateState()
	while ( true )
	do
		if ( self.currentState ~= nil )
		then
			self.currentState:onUpdate()
		end
		coroutine.yield()
	end
end

如何利用State和StateMachine类的示例,首先定义两个state。
SampleState.lua

require "State"

State1 = class( State ) 

function State1:init()
	State.init( self, "State1" )
end

function State1:enter()
	self.i = 0
end

function State1:exit()
	self.i = 0
end

function State1:onUpdate()
	print( self.name .. " is updated" )
	self.i = self.i + 1
	print( "self.i=" .. self.i )
	if ( self.i == 10 )
	then
		print( state2 )
		SM:setCurrentState( state2 )
		self.i = 0
	end
end

-----------------------

State2 = class( State ) 

function State2:init()
	State.init( self, "State2" )
end

function State2:onUpdate()
	print( "State2 is updated" )
end

test.lua

require "StateMachine"
require "SampleState"

SM = StateMachine()
SM:run()
state1 = State1()
state2 = State2()
SM:setCurrentState( state1 )
Posted in: Game Programming, Lua / Tagged: finite state machine, FSM, lua, state pattern, 状态模式

Class Diagram of Pacman

September 4, 2011 12:22 am / Benny Chen

贴上Pacman的类图,关于这个项目,见我的上一篇博客。

Posted in: Game Programming / Tagged: class diagram, Moai, pacman, 类图

基于Moai的Pacman

August 29, 2011 10:49 pm / Benny Chen

最近一两个星期,在业余时间利用Moai引擎重写了当年曾经用DirectX实现过的Pacman游戏。基于Lua的代码基本上是重写,只是保留使用了之前的2D资源。重写的目的一是通过这个来熟悉Moai引擎,二是希望用一个比较好的OO结构来重新实现Pacman,三则纯粹因为好玩。

把所有的代码,资源和文档都已经上传到了github,github真的是个好东东。

https://github.com/bennychen/Moai-based-Pacman

介绍:

This is a prototype game based on the Moai game platform – http://getmoai.com. With various APIs for drawing and handling different 2D elements that Moai has supported, it clones a 2D Pacman game.

I programmed the game for several objectives. Firstly, because I am just new to Moai, I try to familiarize myself with Moai’s various APIs and game development based on it. I did encounter some issues when programming the game. Some were because I am a newbie for Moai, and some were testified later that were from Moai engine itself. Although the process was time-consuming, but to my pleasure, this is somewhat a contribution to the open source Moai engine itself. I feel a great joy to be part of it. Secondly, the whole game is based on OO. So I tried to program the whole game with a decent OO structure. Most importantly, some of the Lua classes or files, hopefully, can be reused in my other future potential games.

All in all, I programmed Moai-based Pacman for fun and share my code, related game assets and documents here. If there can be any help for you who are interested in Moai and OO game programming, that would be my best honer.

Posted in: Game Programming, Lua, My Projects / Tagged: 2d, github, Moai, oo, pacman

Post Navigation

← Older Posts
 

LinkedIn

Milan Petrovic

Categories

  • In My Life (25)
    • A Day in the Life (8)
    • English Learning (2)
    • Learn a Word (7)
    • Something In The Way (8)
  • Music Heaven (8)
    • Guitar (1)
    • In Concert (1)
    • Lyrics (3)
  • OK Computer (54)
    • 3D (3)
    • C++ (10)
    • Computer Graphics (15)
    • Game Programming (23)
    • iOS (6)
    • Linux (1)
    • Lua (9)
    • My Projects (3)
    • Some Experiences (9)
    • Talking in Code (2)
    • Unity (2)
  • Quotations (2)
  • Uncategorized (1)
  • Visca Barça (24)
    • FCB BJ (5)

Recent Posts

  • [译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章
  • 新浪微博API for MOAI
  • 稍后继续
  • Unity Developer ++
  • Another Thread @ Moai Forum
  • 1st Day of Golden Week
  • 为SyntaxHighlighter添加新语言
  • 基于Lua的State Pattern
  • Class Diagram of Pacman
  • 基于Moai的Pacman

Recent Comments

  • 约修亚_RK on 为SyntaxHighlighter添加新语言
  • 爱装的小男孩 on 小心DLL链接静态库时的内存错误
  • happyfire on Game Loop的几种实现方式
  • William on 新浪微博API for MOAI
  • Benny Chen on 新浪微博API for MOAI
  • your man on 新浪微博API for MOAI
  • 你家男人 on 稍后继续
  • 逍遥 on 关于对std::vector的遍历
  • papa on Unity Developer ++
  • T客网 ︱ Techpot » Blog Archive » iOS开发与OpenGL ES相关问题整理(1) on iOS开发与OpenGL ES相关问题整理(1)

Tags

2d 3D 3dsmax 3ds max air Apply architecture Asia tour barca Beijing bilbao binary search blocked bob boost bruce springsteen C++ capo CGContextDrawImage Champions League Change DLL DX10 eval exporter flash framework frustum culling game game engine iniesta ios linux lua Moai opengles pacman plug-in plugin 北京 导出插件 崩溃 巴萨 游戏引擎 踢球
© Copyright 2024 - A Game Developer
Infinity Theme by DesignCoral / WordPress