版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Get Started开始PushButton,首先你需要下载当前的最新版本( Eclipse,让我觉得舒服)。解压后我们找到PushButton的类库所在,在Bin文件夹中我找到了PBEngine.swc(这花了我一阵时间来研究swc在flash中的职责),也就是我们需要引用的类库文件。我在上面提到过,并没有发现有些帖子博客中提到的Manager.air,在这里我们直接在Flex中新建一个Flex项目,在建立时在lib文件夹中引入PBEngine.swc,到这里我们的准备工作就基本结束了。 为了证明我们的操作成功与否,我们需要做一些测试证明一下。我们在 <mx:Applica
2、tion xmlns:mx=" layout="absolute" applicationComplete="appComplete()" width="480" height="384" backgroundGradientAlphas="1.0, 1.0" backgroundGradientColors="#A53EE1, #C8C8C8"
3、>标签中设置了应用程序结束时调用的 appComplete方法,在这个方法中我们需要调用 protected function appComplete():void Global.startup(this);用Matthew Casperson的话就是,当我们要用PushButton做什么事情之前,首先一定要调用Global.startup(this);这是一切的基础。然后让我们做一个简单的动画(一个屏幕上的圆,来完成我们第一期的练习)。 首先,在PushButton中,所有的东西都称之为”Entity“ 翻译成实体也好,所以,要显示一个圆,我们需要两个
4、实体,首先我们需要一个类似于舞台类似于场景的东西我们称之为 ”Scene“(这在以后的例子中仍然会用到),然后需要一个圆,放到这个"Scene"中去。 在PushButton中,组件构成了实体,实体就像一个空的盒子一样,每放入一个组件,盒子将拥有一个新的功能和特点。PushButton并没有采用传统的继承的设计模式,并没有在创建一个实体的时候创建一个类,而是实现了一个接口Entity的一个对象,并包含了实现其他功能接口的组件,由实体包裹着组件(模块化的思想渐渐付出水面,但是精彩的还在后面,这种模块化让你想到了什么?XML?)。 我们创造了一个工厂类来产生
5、我们需要的实体,以供在应用程序入口Main.mxml中调用 1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Application 3 xmlns:mx=" 4 layout="absolute" 5 applicationComplete=&quo
6、t;appComplete()" 6 width="480" 7 height="384"> 8 9 <mx:Script>10 <!CDATA11
7、; 12 import com.pblabs.engine.core.*;13
8、 14 protected function appComplete():void15 16 &
9、#160; Global.startup(this);17 18 EntityFactory.createScene("scene");19&
10、#160; EntityFactory.createPlayer("player", "scene");20 21
11、0; 22 >23 </mx:Script>24 25 </mx:Application>26 在 EntityFactory中,我们先创建Scene。 1 package 2 3 &
12、#160; import mx.core.*; 4 5 import com.pblabs.engine.core.*; 6 import com.pblabs.engine.entity.*; 7 import com.pblabs.renderin
13、g2D.*; 8 import com.pblabs.rendering2D.ui.*; 9 10 import flash.geom.Point;11 12 public class EntityFactory13
14、; 14 static protected const SCENE_SPATIAL_COMPONENT:String = "Spatial"15 static protected const SCENE_RENDERER_COMPONENT:String
15、= "Renderer"16 17 static public function createScene(name:String):IEntity18 19
16、60; var Scene:IEntity = allocateEntity(); 20
17、60; Scene.initialize(name); 21
18、160; 22 var Spatial:BasicSpatialManager2D = new BasicSpatialManager2D();
19、 23 Scene.addComponent( Spatial, SCENE_SPATIAL_COMPONENT );
20、 24 25 var Renderer:Scene2DComponent = new Scene2DComponent();
21、; 26 Renderer.spatialDatabase = Spatial;
22、 27 28
23、160; var View:SceneView = new SceneView(); 29
24、60; View.width = Application.application.width;
25、0; 30 View.height = Application.application.height; &
26、#160; 31
27、; Renderer.sceneView = View;
28、; 32 33 Renderer.position = new Point(0,0);
29、; 34
30、60; Renderer.renderMask = new ObjectType("Renderable"); 35 36 &
31、#160; Scene.addComponent( Renderer, SCENE_RENDERER_COMPONENT ); 37 38
32、60; return Scene; 39 在类的数据成员我们发现了两类组件的标记常量,一个叫"Spatial",一个叫"Renderer",由于我并没有从事过动画创作和任何游戏开发,我只能在开发中逐渐理解他们的含义,最简单的理解就是Spatial组件负责空间上的事务,如位置(position),大小(size)等等,而 Renderer组件则负责处理渲染事务,关于什么叫渲染
33、我并没有专业开发人员更理解,不过它决定了物体的形状,外貌等等。在创建Scene时,需要特殊注意的是,实体Scene的组件Render同样需要一个View来将Scene渲染上去,这个时候我们需要创建一个SceneView如上代码所示。然后我们需要创建Player,也就是那个球。 1 static public function createPlayer(name:String, scene:String):IEntity 2
34、0; 3 var entity:IEntity = allocateEntity();
35、0; 4 entity.initialize(name);
36、60; 5 6 var Spat
37、ial:SimpleSpatialComponent = new SimpleSpatialComponent(); 7 8 Spatial.spatialManager = Name
38、Manager.instance.lookupComponentByName(scene, SCENE_SPATIAL_COMPONENT) as ISpatialManager2D; 9
39、 10 Spatial.objectMask = new ObjectType("Renderable"); &
40、#160; 11 Spatial.position = new Point(0,0);
41、0; 12 Spatial.size = new Point(50,50);
42、60; 13 14 entity.addComponent( Spa
43、tial, "Spatial" ); 15
44、160; 16 var Render:SimpleShapeRenderComponent = new SimpleShapeRenderComponent(); 17 &
45、#160; 18 Render.showCircle = true;
46、 19 Render.radius = 25;
47、; 20 Render.po
48、sitionReference = new PropertyReference("Spatial.position"); 21 22 entity.addComponent( Rende
49、r, "Render" ); 23 24 return entity;25 26 27
50、60; 28 读者会发现和Scene的创建非常的类似,在Spatial决定了大小和位置后,Render中指定了这是显示一个圆,并描述这个圆的半径是25,在这里我们需要注意的是在Render的定义中,我们需要与Spatial的属性进行关联, 比如这里我们需要这个物体的空间位置,所以出现了 Render.positionReference = new PropertyReference("Spatial.position"); 在后面我们还会遇到和大小相关联等等。 运行在Fl
51、exBuilder中运行我们的项目,您会得到一个圆,这时候,恭喜你,您已经迈出了第一步。 我很喜欢PushButton,希望您也可以继续。以上部分内容,来自 Matthew Casperson的博客Demo代码下载页面上一期我们说到了PushButton游戏引擎的helloworld,我们在一张幕布上成功画出了一个圆,这一节,我们要做的就是让这个圆动起来。这对我来说是激动人心的(因为我原本只是写写简单的交互JS),上一节我们讲到PushButton最大的特点就是以组件为中心,一个实体好比一个空箱子,放在里边好多各种功能的石头,这个箱子就具有了各种各样的功能,这些有魔力的石头
52、,也就是我们所说的组件。所以当我们要做这样一个应用时,你可能会自然的想到,要被鼠标控制,这样的一个功能,是不是一个组件的?you're right ,my friend。 复制内容到剪贴板 代码:package import ponents.*; import com.pblabs.engine.entity.*; import com.pblabs.engine.core.*;
53、 import flash.geom.Point; public class KeyboardController extends TickedComponent public var PositionReference:PropertyReference = null;
54、; public var Speed:Number = 0; protected var xMovement:Number = 0; protected var yMovement:Number = 0; public override funct
55、ion onTick(tickRate:Number):void var position:Point = owner.getProperty(PositionReference);
56、 if (InputManager.isKeyDown(InputKey.RIGHT) xMovement += Speed * tickRate;
57、 while (xMovement >= 1) position.x += 1;&
58、#160; xMovement -= 1;
59、0; else if (InputManager.isKeyDown(InputKey.LEFT) xMovem
60、ent -= Speed * tickRate; while (xMovement <= -1)
61、0; position.x -= 1; xMovement += 1;
62、60; if (InputManager.isKeyDown(InputKey.DOWN)
63、0; yMovement += Speed * tickRate; while (yMovement >= 1)
64、60; position.y += 1;
65、; yMovement -= 1;
66、160;else if (InputManager.isKeyDown(InputKey.UP) yMovement -= Speed * tickRate;
67、 while (yMovement <= -1) position.y -= 1;
68、 yMovement += 1;
69、60; 看了上面的代码,我们的目光会锁定在这个类继承的这个叫 TickComponent,这是一个比较关键的组件,在我看来,既然FLEX没有时间轴的概念,那么Tick这个概念就很重要了,这对于你在每一个tickRate时间点上都可对相应的实体进行检测和控制,此篇就是对键盘的简单控制。键盘控制的细节就不做多讲解,xMovement/yMovement在我理解就是一个缓冲,让你的每一次键盘操作更流畅而不僵硬。这里我们第一次在组件中看到owner的
70、身影,他代表对该实体的引用(也就是说每个石头上有这么个标记要owner,指明放石头的盒子),通过owner可以访问很多实体的属性,比如现在我们说的这个position,还有未来要接触比较关键的线速度(linearVelocity)。我们写完这个组件后需要把它加入到我们原本编辑好的圈圈实体内,像添加其他组件一样 复制内容到剪贴板 代码:var Input:KeyboardController = new KeyboardController(); Inpu
71、t.PositionReference = new PropertyReference("Spatial.position"); Input.Speed = 50; entity.addComponent(Input, "Input");组件实体的结构化很彻底,有没有又让你想
72、起什么?XML?运行实例,你会发现,小圈圈已经可以跟上你的大脑畅游了下一期我们将尝试让我们的角色变得更有趣一些,把圆圈变成会动的小人?上一节我们说到了键盘控制,能让我们的下圈圈动起来,这让我着实的兴奋。那么这一节,我们让我们的圈圈消失掉,取而代之的是类似于“合金弹头”的人物造型,每一次接近于现实游戏的进步都让我感觉到兴奋,让我们看看该如何操作。我们看一下我们原本实体里的 render组件1 var Render:SimpleShapeRenderComponent = new SimpleShapeRenderComponent();
73、;2 3 Render.showCircle = true;
74、0; 4 Render.radius = 25;
75、0; 5 Render.positionReference = new PropertyReference("Spatial.position"); 6 7 entity.addComponent( Render, "Render" );
76、0;平淡无奇,只能看出是一个圆,半径为25像素。我们来稍微改动一下,恐怕我们再也不需要这个圆了1 var Render:SpriteRenderComponent = new SpriteRenderComponent();2 3 Render.loadFromImage = "./media/idleright.png"
77、;
78、; 4 Render.positionReference = new PropertyReference("Spatial.position"); 5 6
79、0; entity.addComponent( Render, "Render" ); 从代码上看很容易看出我们替换成了一张图片,图片如下,这很酷,很“合金弹头”。 到这可能我们预期的目的已经达到了,的确,你的想法是对的。但是,作为素材,加载的速度是很重要的,放在文件中被下载固然是一种天经地义的做法,但是在这里,PushButton提供给了我们一种新的做法,将图片加载到flash中,使加载速度更快捷(当然这是我的理解,Matthew Casperson也的的确确是这样说的,具体如何实现的,在这里我仍然无
80、法回答,也无法验证,欢迎专家来讲解将图片加载到FLASH里的原理)。这里我将这些资源理解为嵌入式资源。 1 package 2 3 import com.pblabs.engine.resource.ResourceBundle; 4 5 public class Resources extends ResourceBundle
81、0;6 7 Embed(source="./media/idleright.png", mimeType="application/octet-stream") 8 public var ImgIdleRight:Class;
82、 9 10 11 很明显,com.pblabs.engine.resource.ResourceBundle的这个ResourceBundle起到了这个作用,我们看到了图片被Embed,而且还设置了mimeType.这和重要,在以后的学习过程中,无论声音(mp3文件),图片,以至于我们未来遇到的最重要的xml都将以这种方式嵌入到我们的游戏中去。而这些XML将构成我们以后游戏的主
83、框架,也就是表示层和控制层相分离,这种业务分离是很重要的,无论你在从事网站开发还是其他方面的开发,都至关重要。这些将在以后的章节中介绍,现在我们将用as代码实现一个简单游戏,而后,我们将业务分离采用xml+as的方式构筑我们的游戏,这也符合大多数开发模式。 下一期我们将会使这个角色动起来,Animation,这是很有意思的一件事,就好比你控制的人物在空闲时候自己会擦擦枪,跑起来把枪抗在后背上?这次继续来说这个Animation的概念,这对于我这个对游戏从未接触的人是一次全新的接触,因为曾经玩过的游戏,那些自己会动起来的人物,从来没想过是如何做的,比如我们的这个游戏人物,当我键盘空闲时
84、候,希望他做着身子上下颤抖的动作。经过一番学习,才接触到,这是一个PNG里六个连续静态图像()循环连播形成的,在PushButton中有专门处理这种png图片的东西,称之为divider。下面我就在原本的基础上加上我们的动画(Animation)。 1 var Animation:AnimationController = new AnimationController(); 2
85、160;Animation.spriteSheetReference = new PropertyReference("Render.spriteSheet"); 3 Animation.currentFrameReference = new PropertyReference("Render.spriteIndex");
86、 4 Animation.defaultAnimation = "IdleRight" 5 6
87、60; var IdleRightSpriteSheet:SpriteSheetComponent = new SpriteSheetComponent(); 7 IdleRightSpriteSheet.imageFilename = "./media/idleright.png"&
88、#160;8 9 10 var divider:CellCountDivider = new
89、160;CellCountDivider();11 divider.xCount = 6;12 IdleRightSpriteSheet.divider = divider;13 &
90、#160; 14 var IdleRightAnimation:AnimationControllerInfo = new AnimationControllerInfo();15
91、IdleRightAnimation.frameRate = 12;16 IdleRightAnimation.loop = true;17 IdleRightAnimation.spriteSheet = IdleRightSpr
92、iteSheet;18 Animation.animations"IdleRight" = IdleRightAnimation;19 20
93、160; entity.addComponent(Animation, "Animation"); 就这样我们给实体加入了Animation这一组件,AnimationController这一组件需要和Render的两个属性相连接即1 Animation.spriteSheetReference = new PropertyReference("Render.spriteSheet"); 2 &
94、#160; Animation.currentFrameReference = new PropertyReference("Render.spriteIndex"); 之后需要说明的是AnimationController.Animations是一个数组,你可以用Animation"key"=AnimationControllerInfoSample的形式定义多个AnimationControllerInfo。如本例中1
95、Animation.animations"IdleRight" = IdleRightAnimation;而AnimationControllerInfo这个东西,就记录了一个动画的全部,如frameRate频率,loop是否循环播放,以及SpriteSheetComponent(无论怎么翻译),它决定了你素材(如png)的来源,以及divider(xCount给出这个png一共有多少个连续图像)。你可以定义多个AnimationControllerInfo,用来描述角色不同的动作,最后设置一个默认的动作,本例中为1 Animation.def
96、aultAnimation = "IdleRight" 但是你要保证你的这个动作是注册过的。就这样我们的角色可以在空闲的时候发出颤抖动作了,这让我很兴奋,有了这些,我们可以让我们的角色有向左向右跑,甚至跳的动作,只要在相应的时间点上设置Animation就可以了,这是很奇妙也是相当有用的地方。下次我们会继续完善这个人物的各个Animation,。上次说到让一个角色动起来,也就是让他“浑身颤抖”,在动游戏中,我们更新角色动作是一件基本的事情,在PushButton中,处理动作变换是一件简单的事,上次我们创建了一个Ani
97、mationControllerInfo,并且让它成为了角色默认的Animation(Default Animation),我们只需要在现有的基础上添加若干个AnimationControllerInfo然后让它们互相切换就可以了.我没接触过其他的游戏引擎,不过这让我觉得自然和方便。 1 var IdleRightSpriteSheet:SpriteSheetComponent = new SpriteSheetComponent(); 2 &
98、#160; IdleRightSpriteSheet.imageFilename = "./media/idleright.png" 3 4
99、60; var divider:CellCountDivider = new CellCountDivider(); 5 divider.xCount = 6; 6 IdleRightSpriteShe
100、et.divider = divider; 7 8 var IdleRightAnimation:AnimationControllerInfo = new AnimationControllerInfo();
101、 9 IdleRightAnimation.frameRate = 12;10 IdleRightAnimation.loop = true;11
102、 IdleRightAnimation.spriteSheet = IdleRightSpriteSheet;12 13 Animation.animations"IdleRight"
103、;= IdleRightAnimation;14 /end of IdleRight15 var IdleLeftSpriteSheet:SpriteSheetComponent = new Spr
104、iteSheetComponent();16 IdleLeftSpriteSheet.imageFilename = "./media/idleleft.png"17 var divider2:CellCountDivider =&
105、#160;new CellCountDivider();18 divider2.xCount = 6;19 IdleLeftSpriteSheet.divider = divider2;20
106、160; 21 var IdleLeftAnimation:AnimationControllerInfo = new AnimationControllerInfo();22
107、160; IdleLeftAnimation.frameRate = 12;23 IdleLeftAnimation.loop = true;24 IdleLeftAnimation.spriteSheet = IdleL
108、eftSpriteSheet;25 Animation.animations"IdleLeft" = IdleLeftAnimation;26 /end of IdleLeft27
109、160; var RunLeftSpriteSheet:SpriteSheetComponent = new SpriteSheetComponent();28 RunLeftSpriteSheet.imageFilename = "./media/runleft.png"29
110、60; var divider3:CellCountDivider = new CellCountDivider();30 divider3.xCount = 12;31 &
111、#160; RunLeftSpriteSheet.divider = divider3;32 33 var RunLeftAnimation:AnimationControllerInfo
112、160;= new AnimationControllerInfo();34 RunLeftAnimation.frameRate = 12;35 RunLeftAnimation.loop = true;36
113、; RunLeftAnimation.spriteSheet = RunLeftSpriteSheet;37 Animation.animations"RunLeft" = RunLeftAnimation;38
114、0; /end of RunLeft39 var RunRightSpriteSheet:SpriteSheetComponent = new SpriteSheetComponent();40 &
115、#160; RunRightSpriteSheet.imageFilename = "./media/runright.png"41 42 var runRig
116、htDivider:CellCountDivider = new CellCountDivider();43 runRightDivider.xCount = 12;44 RunRightSpriteSheet.divider =&
117、#160;runRightDivider;45 46 var runRightAnimation:AnimationControllerInfo = new AnimationControllerInfo();47 &
118、#160; runRightAnimation.frameRate = 12;48 runRightAnimation.loop = true;49
119、0;runRightAnimation.spriteSheet = RunRightSpriteSheet;50 51 Animation.animations"RunRight" = runRightAnimation;52
120、60; / end of RunRight53 entity.addComponent(Animation, "Animation");54 /end of Animation 这着实是一个繁琐而体力的过程,这在以后的开发中会进行优化(利用结构化的XML直接构建) 。但是原作者在第一版的教程中全部使用了Actionscript,不过在第二版的教程中,作者使用了以xml为基础开发的类似于“小蜜蜂”的游戏,在这一期中,我们仍然需要机械的书写一些代码,就如上面贴出的一样。 在方向控制
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 打造一体化技术融合生态
- 采用合适相对孔径增强视频质量
- 2025年敬老院年度工作总结(2篇)
- 2025年度重大安全风险及管控措施专项培训考试题及答案
- 2025电气设计年终工作总结(二)
- 2025采购铝材合同铝材购销合同
- 2025年电气工程师年终工作总结(3篇)
- 2025科研工作人员劳动合同样本(合同示范例本)
- 2025年下半年商洛市洛南县县级事业单位招录硕士研究生招聘易考易错模拟试题(共500题)试卷后附参考答案
- 2025年下半年商丘市市直事业单位招考及易考易错模拟试题(共500题)试卷后附参考答案
- 2025年秋外研版(三起)(2024)小学英语三年级上册期中考试模拟试卷及答案
- 《2025年浙江公务员录用审计专业试卷(审计监督)》
- 厦门市总工会招聘工会专干和集体协商指导员笔试真题2024
- 地理环境保护与发展+课件-2025-2026学年八年级地理上学期(人教版2024)
- 2025-2026学年人教PEP版(2024)小学英语三年级上册期中检测试卷及答案
- 初中男生性教育指南
- 军队文职护理岗考试题库及答案解析
- 工程项目咨询与竣工验收报告范例
- 2025年中国长寿医学与抗衰产业白皮书-
- 椎管内硬脊膜外血肿护理
- 人教版(2024)七年级上册地理第三章《陆地和海洋》大单元教学设计
评论
0/150
提交评论