昨天我们正式提交了我们公司的第一款iOS游戏到AppStore,目前正在审核中。也是我个人的第二款iOS游戏(第一款是一款个人产品:Turtle Reaction,http://itunes.apple.com/cn/app/turtle-reaction/id446570380?l=en&mt=8)。
在打包的时候,我发现我的XCode虽然Archive成功,但是在Organizer里看不见。后来发现,应该是Xcode写入默认路径权限不够。所以解决起来很简单:
1. 点击Xcode的Preference。进入系统的设置界面。选择Locations选项卡。
2. 修改Archives Location,设置路径由默认路径为自己的自定义路径。
成功。
在打包的时候,我发现我的XCode虽然Archive成功,但是在Organizer里看不见。后来发现,应该是Xcode写入默认路径权限不够。所以解决起来很简单:
1. 点击Xcode的Preference。进入系统的设置界面。选择Locations选项卡。
2. 修改Archives Location,设置路径由默认路径为自己的自定义路径。
成功。
Sep
19
2011
flashyiyi同学写了一篇关于MVC与Flash的文章,http://www.infoq.com/cn/news/2011/04/flash-pragmatism-4。里面的观点大部分我是赞同的。很久前我越来越意识到,网上热热闹闹的各种MVC框架是否真的有那么灵?在使用PureMVC的几年里,越来越倾向于抛弃这些框架,他们的束缚真得是很让我不爽,尤其作为一名游戏程序员,MVC如何能与游戏层完美的结合起来一直没有较优美的答案。
首先,在我眼里MVC中的C,也就是Control,是我一直感觉存在争议的部分。在不采用Flex framework的情况下,大部分的游戏UI是由程序,或是美术在FLASH工具中创作的。这部分我们定义为View,只负责显示。那么PureMVC中的Mediator算做是什么呢?View,or Control?如果是Control,那么Command算做什么?我倾向于将Mediator直接归类为Control的一部分。极少采用Command的编写方式,原因为:
1. 采用Command来写,需要单独为每个控制行为定义对应的逻辑单元,而逻辑的控制需要有上下文(Context)。Mediator以中间人的身份正好是为协调多个单元而存在的,获得上下文是最简洁方便的,何必还要再发送一个通知,告诉那些不知道是大海里的哪一个的Command去做这些事?
2. 游戏是一种交互性很强、或着说,跑在flash里的应用绝大多数都是交互强交互的应用。这意味着会产生海量的交互逻辑,这些逻辑都要写成Command?太玩命了。这是因为这些行为一旦距离他的上下文数据远远的,维护工作只会变得更加复杂。何况他们的数量还很多。
3. 很多需要校验、存储的逻辑会交给server端去做,如果是单机应用,把server端相对独立、高度抽象的纯业务逻辑交给Command去完成比较恰当。
4. PureMVC中海一样的Notifications,包含的信息确缺乏强类型的支持。判断它的来源、携带的信息基本只能依赖调试器。这为团队的沟通反而带来了障碍。当然,这缺点即使换作Events机制也改善不了多少。
没有了Command的PureMVC,还是pure的PureMVC么?同样,我也不支持采用依赖注入方式管理依赖的MVC框架。我并不怕任何MVC框架带来性能上的损失,这不是最重要的,作为UI层的解决方案,作为每隔1s以上才需要更新一次的小压力,如果因为MVC框架带来了性能损失,那绝对是因为你跑在了286机器上的缘故。然而,我要关心的是为什么要用依赖注入?依赖注入这玩意把接口与接口的耦合降级到了配置文件中去解决,主要解决编译型语言在大型应用程序中编译时间过长、每次改动都需要重新编译的问题。我想,大家的程序还没膨胀到每次编译都要喝杯咖啡打发时间的地步。接口与接口的耦合已经是我能接受的最好耦合关系了,我不在乎多编译几次,何况大部分产品、策划的配置都写到了配置文件中,通过专门的工具去修改。
上面只是我对MVC框架有意见的地方。当然,它也是有积极的意义的。起码框架能告诉你代码应该怎么写,哪怕一开始你不知道怎么组织大中型应用程序;而且能告诉团队的成员,我们的代码基本是这么组织的,而且实际上大部分成熟的组织都是这么组织的,降低熟悉代码的成本。这一切的前提是,你有很多团队成员,你的代码很多或未来会变的很多。
没有了MVC框架,这一些当然也能运行的很好。以上的林林总总,基本只是围绕这MVC大圈圈。那么,背后是否还有更深层次的原因?我的意见是,这与面向对象的编程思想的本质有关。OOP主张我们的项目应该被设计为一个系统,系统内的对象们是互相有关系的,这或许是耦合产生的根源之一,让整个系统或者被过度设计,或者设计不当。从这点说,OOP是一个反模块化的编程思想。当然这就扯远了。
关于View,flex框架和flex编译器是一件优秀的工程。虽然我的游戏没用它,很多游戏估计都不会用它,但是通过xml配置界面排版、效果定义,让代码与视图干净的分离,是造福程序员的伟大工程。在这点上,包括Android的UI系统都走的是这条路线。这告诉我们,很多时候,我们是可以做的更好的(举例来说,让View更单纯,让代码更纯粹),比如Flex的编译器、比如Android的编译器...
首先,在我眼里MVC中的C,也就是Control,是我一直感觉存在争议的部分。在不采用Flex framework的情况下,大部分的游戏UI是由程序,或是美术在FLASH工具中创作的。这部分我们定义为View,只负责显示。那么PureMVC中的Mediator算做是什么呢?View,or Control?如果是Control,那么Command算做什么?我倾向于将Mediator直接归类为Control的一部分。极少采用Command的编写方式,原因为:
1. 采用Command来写,需要单独为每个控制行为定义对应的逻辑单元,而逻辑的控制需要有上下文(Context)。Mediator以中间人的身份正好是为协调多个单元而存在的,获得上下文是最简洁方便的,何必还要再发送一个通知,告诉那些不知道是大海里的哪一个的Command去做这些事?
2. 游戏是一种交互性很强、或着说,跑在flash里的应用绝大多数都是交互强交互的应用。这意味着会产生海量的交互逻辑,这些逻辑都要写成Command?太玩命了。这是因为这些行为一旦距离他的上下文数据远远的,维护工作只会变得更加复杂。何况他们的数量还很多。
3. 很多需要校验、存储的逻辑会交给server端去做,如果是单机应用,把server端相对独立、高度抽象的纯业务逻辑交给Command去完成比较恰当。
4. PureMVC中海一样的Notifications,包含的信息确缺乏强类型的支持。判断它的来源、携带的信息基本只能依赖调试器。这为团队的沟通反而带来了障碍。当然,这缺点即使换作Events机制也改善不了多少。
没有了Command的PureMVC,还是pure的PureMVC么?同样,我也不支持采用依赖注入方式管理依赖的MVC框架。我并不怕任何MVC框架带来性能上的损失,这不是最重要的,作为UI层的解决方案,作为每隔1s以上才需要更新一次的小压力,如果因为MVC框架带来了性能损失,那绝对是因为你跑在了286机器上的缘故。然而,我要关心的是为什么要用依赖注入?依赖注入这玩意把接口与接口的耦合降级到了配置文件中去解决,主要解决编译型语言在大型应用程序中编译时间过长、每次改动都需要重新编译的问题。我想,大家的程序还没膨胀到每次编译都要喝杯咖啡打发时间的地步。接口与接口的耦合已经是我能接受的最好耦合关系了,我不在乎多编译几次,何况大部分产品、策划的配置都写到了配置文件中,通过专门的工具去修改。
上面只是我对MVC框架有意见的地方。当然,它也是有积极的意义的。起码框架能告诉你代码应该怎么写,哪怕一开始你不知道怎么组织大中型应用程序;而且能告诉团队的成员,我们的代码基本是这么组织的,而且实际上大部分成熟的组织都是这么组织的,降低熟悉代码的成本。这一切的前提是,你有很多团队成员,你的代码很多或未来会变的很多。
没有了MVC框架,这一些当然也能运行的很好。以上的林林总总,基本只是围绕这MVC大圈圈。那么,背后是否还有更深层次的原因?我的意见是,这与面向对象的编程思想的本质有关。OOP主张我们的项目应该被设计为一个系统,系统内的对象们是互相有关系的,这或许是耦合产生的根源之一,让整个系统或者被过度设计,或者设计不当。从这点说,OOP是一个反模块化的编程思想。当然这就扯远了。
关于View,flex框架和flex编译器是一件优秀的工程。虽然我的游戏没用它,很多游戏估计都不会用它,但是通过xml配置界面排版、效果定义,让代码与视图干净的分离,是造福程序员的伟大工程。在这点上,包括Android的UI系统都走的是这条路线。这告诉我们,很多时候,我们是可以做的更好的(举例来说,让View更单纯,让代码更纯粹),比如Flex的编译器、比如Android的编译器...
Apr
14
2011
轻量级Android游戏引擎:libGDX-lite
11:16 , Qizhi
做android游戏我首选的游戏引擎是libGDX(http://code.google.com/p/libgdx/), 作者Badlogic Games是非常有爱的同学,写出了如此让人惊叹的高效渲染引擎。这个引擎让人惊叹的不只是他的性能,他干脆提供了PC上的backend支持,让你写得游戏不仅仅能跑在android上,还能跑在pc上。然而,有时我只想做一个简单的,能在android上卖钱的工具,所以这个引擎其它的模块对我而言,不是那么有吸引力。当然,我还想改改其中的一些代码,使之能更适合我的项目,那么,就有了这个简化版libGDX引擎,它只提供了以下几个核心的功能:
1. open GL es渲染,2D sprite以及sprite batch支持。采用c优化过的高效的图形渲染能力。删去了原有的3D支持。
2. 音乐、音效的播放、控制能力。删去了音乐采样、分析等功能。
3. 高效的数学库。
4. 针对android优化过的collection库以及其它一些帮助类。
5. Ant支持。
6. Box2D引擎被删除了。如果要做物理游戏,可以将相关的库在集成进来。
这样精简后的引擎紧紧占用600k出头,减少了一般以上的体积。项目的地址是:
http://code.google.com/p/libgdx-lite/
另外推荐一款texture atlas工具Texture Packer(http://www.texturepacker.com/features/),提供贴图的打包、像素抖动、压缩、PVRs格式支持等功能。详细情况可以参考How to Create and Optimize Sprite Sheets in Cocos2D with Texture Packer and Pixel Formats 这篇文章。虽然介绍的是iOS环境下的开发,Texture Packer其实是支持libGDX贴图配置和Cocos2D等很多引擎的。
1. open GL es渲染,2D sprite以及sprite batch支持。采用c优化过的高效的图形渲染能力。删去了原有的3D支持。
2. 音乐、音效的播放、控制能力。删去了音乐采样、分析等功能。
3. 高效的数学库。
4. 针对android优化过的collection库以及其它一些帮助类。
5. Ant支持。
6. Box2D引擎被删除了。如果要做物理游戏,可以将相关的库在集成进来。
这样精简后的引擎紧紧占用600k出头,减少了一般以上的体积。项目的地址是:
http://code.google.com/p/libgdx-lite/
另外推荐一款texture atlas工具Texture Packer(http://www.texturepacker.com/features/),提供贴图的打包、像素抖动、压缩、PVRs格式支持等功能。详细情况可以参考How to Create and Optimize Sprite Sheets in Cocos2D with Texture Packer and Pixel Formats 这篇文章。虽然介绍的是iOS环境下的开发,Texture Packer其实是支持libGDX贴图配置和Cocos2D等很多引擎的。
Apr
14
2011
Molehill API的发布使得利用硬件加速2d图形变为可能。写了一个比较粗糙的2D screen graph,放在了Google Code上:
https://code.google.com/p/molehill2d/

用法:
首先创建一个stage 3d,这一步和创建普通的3d应用相同。
stage.stage3Ds[0].viewPort=new Rectangle(0, 0, 1024, 1024);
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContextCreation);
stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO);
addEventListener(Event.ENTER_FRAME, onRender);
接下来就是直接使用我封装好的API即可:
scene=new DisplayContext3D(stage, stage.stage3Ds[0]);
for(var i:int = 0; i < 500; i ++)
{
var mc:TexturedMovie = new TexturedMovie(schools, 30);
mc.play();
mc.position = new Vector3D(Math.random()*1000 - 500, Math.random()*1000-500);
scene.addChild(mc);
}
鼠标事件也需要使用封装好的API来用:
royalcottage12 = new TexturedQuad(defaultTextureData, defaultTextureData.width, defaultTextureData.height);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_DOWN, onMouseDown);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_UP, onMouseUp);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_OUT, onMouseUp);
royalcottage12.x = 32;
royalcottage12.y = 144;
scene.addChild(royalcottage12);
注意3D编程和2D有很大不通,对3D api状态改变(贴图、顶点等)必须每帧尽可能的少,建议使用texture page等手段优化贴图资源。
https://code.google.com/p/molehill2d/

用法:
首先创建一个stage 3d,这一步和创建普通的3d应用相同。
stage.stage3Ds[0].viewPort=new Rectangle(0, 0, 1024, 1024);
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContextCreation);
stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO);
addEventListener(Event.ENTER_FRAME, onRender);
接下来就是直接使用我封装好的API即可:
scene=new DisplayContext3D(stage, stage.stage3Ds[0]);
for(var i:int = 0; i < 500; i ++)
{
var mc:TexturedMovie = new TexturedMovie(schools, 30);
mc.play();
mc.position = new Vector3D(Math.random()*1000 - 500, Math.random()*1000-500);
scene.addChild(mc);
}
鼠标事件也需要使用封装好的API来用:
royalcottage12 = new TexturedQuad(defaultTextureData, defaultTextureData.width, defaultTextureData.height);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_DOWN, onMouseDown);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_UP, onMouseUp);
royalcottage12.addEventListener(Mouse2DEvent.ON_MOUSE_OUT, onMouseUp);
royalcottage12.x = 32;
royalcottage12.y = 144;
scene.addChild(royalcottage12);
注意3D编程和2D有很大不通,对3D api状态改变(贴图、顶点等)必须每帧尽可能的少,建议使用texture page等手段优化贴图资源。
Feb
28
2011
很荣幸加入了2011年的Adobe Community Professional计划。籍此机会,我想说的是,我们公司还在招人,求贤若渴!期望走过路过的朋友不要错过,移步瞧瞧:http://www.happyelements.com/index.php/category/jobs/beijing-office/engineer
Jan
28
2011



