《ANDENGINE笔记.doc》由会员分享,可在线阅读,更多相关《ANDENGINE笔记.doc(67页珍藏版)》请在三一办公上搜索。
1、前言:Andengine学习翻译,原文:http:/www.matim-译者:moonlight Email: bespbreaker文中有不少不准确的地方,凑合看吧,希望对初学者有些帮助。一。开始: 1.andengine 介绍: Ae 是一个基于OPENGL的开源免费游戏引擎,作者是Nicolas Gramlich。该引擎封装了OPENGL的大多数重要功能,意味着即使你没有OPENGL编程经验,也可以使用该引擎来创建游戏,只要你有JAVA编程经验。 引擎的主要特点: 支持不同分辨率设备的缩放。 多点触摸支持 物理引擎-BOX2D(愤怒的小鸟也使用该引擎) TMX 瓦片地图支持 粒子系统 动
2、态壁纸扩展支持 使用AE的好处: 免费开源 游戏开发中的方方面面都被做好了 不需要OPENGL的经验 快速和良好的设计(注:引擎采用高内聚低耦合,模块分得很细) 相对来说大而活跃的帮助社区(注:www.andengine.org) 不错的引擎扩展(注:8还是9个扩展包) 大量的实例,告诉你引擎能做什么l 不足: 几乎没有代码文档 有时候速度比不上其他引擎 缺乏文档是初学者的最大困难不过实例,社区还有我的(作者的)这个网站也能给初学者极大帮助l 2.搭建开发环境:环境的搭建参造RealMayo的视频,里面说得很详细。l 3.重要概念: 本节描述引擎中的重要概念,简单地说就是引擎中最常用到的类和扩
3、展l 1.ANDENGINE-核心术语(byNicolas Gramlich + updates and addons) Engine: 引擎通过时间片来处理游戏,周期性地同步场景的绘制和更新。你也可以使用ENGINE的子类: LimitedFPSEngine 限定的FPS。(注:即固定的帧数,代码中还有一种是FixStepEngine 即固定步长,文中没有写。意思是每次更新传递的时间都是固定的,即使实际更新场景用的时间超过的了设定的,也会传入固定的时间。) IResolutionPolicy: IresolutionPolicy 接口实现是EngineOptions的一部分,它告诉引擎如何处
4、理不同设备的不同屏幕尺寸。I.E. RatioResolutionPolicy 在保持比例的情况下会最大化SurfaceView到屏幕的大小。这样屏幕上的东西不会发生变形。 RatioResolutionPolicy 保持比例 FillResolutionPolicy 填充屏幕,可能被拉伸 Camera: 相机就是定义场景中可显示的部分,通常一个场景有一个相机,Camera 的子类有更多功能: BoundCamera- 可以设定场景的边界。 ZoomCamera 可以缩放,定点缩放,滚动场景 Scene: 场景是绘制到屏幕上的所有对象的根容器,一个场景可以包含多层,每层容纳(静态或者动态地)一
5、定数量的实体(Entity)。Scene 有子类:HUD, MenuScene, CameraScene, 这些子类绘制在固定位置和摄相机镜头无关。 HUD- Head Up Display. 像游戏中的分数显示。(注:理解成电视频道的台标!) Entity: 实体就是可以被绘制的对象,如,精灵Sprites, 矩形Rectangles, 文字 Text 或 线条Lines等,每个实体都有,位置/旋转/缩放/颜色等等属性。 Sprite- 具有纹理(Texture)的实体(Entity) TiledSprite- 被切开了的精灵 AnimatedSprite- TiledSprite的扩展,可
6、以按指定的时间播放。 Texture: Texture 就是内存中图像的一个切片。在Android上纹理的宽和高应当是2的幂(但在ELES2中没有这个要求了,可以很好地减少内存使用。) AE 将许多ITextureSources 源组成一个纹理,可以更合理地使用内存空间。TextureRegion:TextureRegion 定义了Texture上的一矩形区域,用来定义精灵要绘制的部分。l 4.AndEngine 的官方例子:AE虽然缺乏文档,但是别担心,实例代码可以很好帮你理解引擎如何工作,这是链接:AndEngine Examples GitHub link l 5. GLES1 和GLE
7、S2的比较:有三个AE的版本,GLES1, GLES2, GLES2 Anchor Center。GLES1已经停止开发。虽然有人说GLES2比GLES1要慢(CLICK HERE)。但是还是强烈建议使用最新版本。l 6.GLES2 和 GLES2 Anchor Center 的不同:G2AC 最有意义的改变是坐标系统。原点在左下。原因是: 和原生OpenGL的坐标系统一致。 和cocos2d-iphoneandcocos2d-x的一致。注:我理解为就是数学上的笛卡尔坐标系 作者更容易更有效写引擎,使用AndEngineCocosBuilderExtension扩展包能读取从CocosBuil
8、der 导出的格式(COCOS有较多的工具)。 对需要滚屏的游戏更自然。另外一个变化是锚点(旋转,缩放等的中心)是个从0.0到1.0的相对量。总得来说,这有点像cocos-2d了。这不是什么坏事。为了更好理解G2AC的坐标系统如何工作,举个例子:假如上图是一个场景,摄像机宽高为800x480,则: 左下角(bottom left corner)为(0,0),左上(top left corner)为(0, 480) 左下角(bottom right corner)为(800, 0),右上(top right corner)为(800, 480) 场景中有image A, image B, 和 i
9、mage C 三张图。 image A 是50X50, 那么它的坐标应当是(25, 25)。 image B 是200x150 ,要放在屏幕中间,那么它的坐标就是(400,240) A 和B都是与场景关联(Attached), C 是与B关联,即在B的(0,0)点。二。实体无素介绍l 精灵(Sprites)如果在2D游戏开发中你还是新手,不知道什么样是精灵,我先简单给Sprite下个定义。精灵就是放在场景坐标(X,Y)位置的2D位图(Sprite is a 2D Bitmap, positioned on the scene by X, Ycoordinates.)在AE中,精灵是Entity
10、扩展,更复杂的精灵类可以让你使用切分和动画。1.创建精灵。Sprite 有很多个构造函数,这是其中最简单一个:Sprite yourSprite = new Sprite(x, y, textureRegion, vertexBufferObjectManager); 第一,二个参数指定精灵的坐标。 第三个参数是精灵的ITextureRegion(见loading resources) 第四个是顶点缓冲对象管理器,很常用,可以通过mEngine.getVertexBufferObjectManager();获得。你还可以指定精灵的宽和高,默认使用ITextureRegion中的尺寸。尽可能多地
11、定制Sprite,使用最相近的构造函数。2. 关联精灵把精灵关联到其它实体,比如Scene,如下:anyEntity.attachChild(yourSprite);3. 更多 撤销关联 控制可见性 设置旋转 删除精灵 click. 启用抖动显示(注:Dithering是一种欺骗你眼睛,使用有限的色彩让你看到比实际图象更多色彩的显示方式。通过在相邻像素间随机的加入不同的颜色来修饰图象,通常这种方式被用于颜色较少的情况下)click. Entity 修改器 click. 切片和动画精灵 click.l 切片和动画精灵 (TiledSprite & AnimatedSprite) 本节介绍两个重要
12、的Entity子类,略有不同。1.TiledSprite:在做按钮这些时候很有用,方便地创建按钮的不同状态(注:新的AE提供了ButtonSprite类来专门做按钮了)。你可以很方便地设置当前切片索引:yourTiledSprite.setCurrentTileIndex(index)2. AnimatedSprite:是TiledSprite的子类,可以让TiledSprite动起来。private void createTiledSprite() AnimatedSprite as = new AnimatedSprite(0, 0, tiledTextureRegion, vbo); l
13、ong frameDurration = 100, 100, 100; as.animate(frameDurration); scene.attachChild(as);上面的long有三个值因为,我的 tiledTextureRegion 有三个切片,猜对了,需要为每一个切片指定一个值。(注:每个切片播放后的延时)l 如何删除实体(How to remove Entities):对于不再需要的实体对象我们应当删除,按下面步骤来:ourEntity.detachSelf();yourEntity.dispose();l 将Entites作为层:Layers的概念在游戏开发中很有用,幸运的是,
14、在AE中,创建和管理层都很方便。为了创建一个新的层,我们只需简单地将一个Entity对象与场景关联,好了!第一层可以使用了!(注:这点与老版本有点不同,老版本把Layer独立出来了,有类似getTopLayer()函数)final int FIRST_LAYER = 0;final int SECOND_LAYER = 1;private void createLayers() scene.attachChild(new Entity(); / First Layer scene.attachChild(new Entity(); / Second Layer然后 通过:scene.getCh
15、ildByIndex(FIRST_LAYER).attachChild(yourEntity);再往第一层里添加东西!l 实体修改器(Entity Modifiers): 这个东西是用于将实体按照一定的数学函数作变化,f = E(x);参见org.andengine.entity.modifier 包获取更多信息。1.为一个Entity注册修改器:yourEntity.registerEntityModifier(new RotationModifier(3, 0, 360);这里注册了一个旋转修改器,有三个参数:持续时间,起始角度,终止角度。2.无限循环的修改器。不停地重复调用,可以理解为容
16、器yourEntity.registerEntityModifier(new LoopEntityModifier(yourModifier);3.修改器的监听器有时在执行修改器的某个时间需要执行一段特定的代码,这时候只需覆盖修改器中的某些函数就是了:RotationModifier yourModifier = new RotationModifier(3, 0, 360) Override protected void onModifierStarted(IEntity pItem) super.onModifierStarted(pItem); / Your action after s
17、tarting modifier Override protected void onModifierFinished(IEntity pItem) super.onModifierFinished(pItem); / Your action after finishing modifier ; yourEntity.registerEntityModifier(yourModifier);l 背景:1. 纯色背景:private void createBackground() scene.setBackground(new Background(Color.RED);背景将被设置为红色2.
18、视差背景 (parallax background)你也可以使用图片作为背景,这就是视差背景。不管摄像机如何变化,是否去删去,视差背景总是可见。private void createBackground() ParallaxBackground background = new ParallaxBackground(0, 0, 0); background.attachParallaxEntity(new ParallaxEntity(0, new Sprite(0, 0, background_region, vbo); scene.setBackground(background);Par
19、allaxBackground 可以关联一个 ParallaxEntity ,这里是一个背景精灵图片 。3.自动的视差背景AutoParallaxBackground是ParallaxBackground的子类,可以用来控制里面的实体,比如移动的去朵。但是不太灵活,推荐使用jaym分享的ParallaxLayer来实现达到很酷的效果!l 处理触摸操作:通过重写onAreaTouched, 你可以很容易地控制实体的触摸事件,这个例子中,我们创建一个新的精灵,注册触摸区域,过滤掉某些操作:final Sprite sprite = new Sprite(400, 420, 100, 50, vbo
20、) Override public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float X, float Y) if (pSceneTouchEvent.isActionUp() / execute action return true; ;scene.registerTouchArea(sprite);scene.attachChild(sprite);记住在场景中注册触摸区域,不然没有作用。 IsActionUp 意思是在用户手指离开屏幕时候更多触摸条件: isActionCancel isActionDown isAction
21、Move isActionOutsidel 创建并理解场景 场景是绘制到屏幕上的所有对象的根容器,一个场景可以包含多层,每层容纳(静态或者动态地)一定数量的实体(Entity)。Scene 有子类:HUD, MenuScene, CameraScene, 这些子类绘制在固定位置和摄相机镜头无关。1.创建场景:Scene newScene = new Scene();2.显示切换场景:有时候,应当使用多个场景而不是使用多个活动(Activity) mEngine.setScene(scene); 切换到另一个场景,先前的场景就停止更新了。scene.setChildScene(different
22、Scene);为场景设置一个不同的子场景,有时子场景设置后需要决定是否进行更新,那么使用setChildScene(pChildScene, pModalDraw, pModalUpdate, pModalTouch)子场景很有用,比如需要弹出界面的时候。3.禁用场景的背景:yourScene.setBackgroundEnabled(false);在背景可见的情况下,设置子场景后只能看到子场景,为了出现弹出效果,把子场景的背景设为false。这样子场景好像在屏幕上一样(注:即子场景的背景透明)。l HUDHUD的解释在前面。HUD是Scene的子类,可以跟随摄像机的运动。HUD使用和Scen
23、e没有区别:HUD hud = new HUD();hud.attachChild(yourEntity);camera.setHUD(hud);不过记得为摄像机设置HUD.l 创建菜单场景(MenuScene)AE提供了一个很棒的MenuScene来创建好看又会动的菜单。1. 创建菜单场景。在例子中,我们创建一个带2个精灵菜单项的MenuScene.同时带有缩放的动画,当菜单项被点击时,会被放大。private MenuScene menuScene;private MenuScene createMenu() menuScene = new MenuScene(camera); final
24、 IMenuItem optionsMenuItem = new ScaleMenuItemDecorator(new SpriteMenuItem(0, region2, vbo), 2, 1); final IMenuItem playMenuItem = new ScaleMenuItemDecorator(new SpriteMenuItem(1, region1 vbo), 2, 1); menuScene.addMenuItem(optionsMenuItem); menuScene.addMenuItem(playMenuItem); menuScene.buildAnimati
25、ons(); menuScene.setBackgroundEnabled(false); menuScene.setOnMenuItemClickListener(this); return menuScene;使用ScaleMenuItemDecorator 创建动画,引擎还提供了其他MenuItem修饰器。你也可以很容易地创建自己的修饰器,还可以将修饰器和实体修改器结合起来。(具体见引擎的代码)SpriteMenuItem 的第一个参数是按钮的ID,然后 为菜单设置setOnMenuItemClickListener 监听器,实现IOnMenuItemClickListener:Over
26、ridepublic boolean onMenuItemClicked(MenuScene pMenuScene, IMenuItem pMenuItem, float pMenuItemLocalX, float pMenuItemLocalY) handleButtonActions(); switch(pMenuItem.getID() case 0: /action return true; case 1: /action return true; default: return false; l 实体间的碰撞:AE让我们检查两个实体的碰撞变得非常容易: a,创建实体。b,重写onM
27、anagedUpdate()Sprite entity = new Sprite(x, y, 100, 300, textureRegion, vbo) Override protected void onManagedUpdate(float pSecondsElapsed) if (player.collidesWith(this) / execute actions ;l 如何正确创建文字GLES2只有一个类便可以创建静态和动态的文字。1.创建文字时的重点 实例化文字对象前先准备内存。 比如想显示一个分数:Score:128 确定使用什么字体,和使用哪些字符,然后:Text t = ne
28、w Text(0, 0, font, Score:0123456789, vbo);这样,就不会每次都重新生成一个新的文字实例了!三。处理触摸事件:l 使用场景触摸监听:我会解释如何使用触摸监听 首先,应当实现IOnSceneTouchListener接口 然后检查事件 动作。Overridepublic boolean onSceneTouchEvent(Scene pScene, final TouchEvent pSceneTouchEvent) if (pSceneTouchEvent.isActionDown() /execute action. return false;最后,注册
29、到场景:scene.setOnSceneTouchListener(this);l 创建左/右按钮在大多数游戏中,你都要控制某个对象。所以控制器显得有必要。在这个例子中,我会展示如何创建左/右按钮(控制主角左/右移动)1.创建按钮本例使用 矩形实体(Rectangle Entity)简单明了。当然你可以使用任何其他实体如Sprite 或 AnimatedSprite。按钮会被关联到HUDprivate void createControllers() HUD yourHud = new HUD(); final Rectangle left = new Rectangle(20, 200, 6
30、0, 60, vbo) public boolean onAreaTouched(TouchEvent touchEvent, float X, float Y) if (touchEvent.isActionUp() / move player left return true; ; ; final Rectangle right = new Rectangle(100, 200, 60, 60, vbo) public boolean onAreaTouched(TouchEvent touchEvent, float X, float Y) if (touchEvent.isAction
31、Up() / move player right return true; ; ; / 可见,实际接受触摸事件消息的是场景! yourHud.registerTouchArea(left); yourHud.registerTouchArea(right); yourHud.attachChild(left); yourHud.attachChild(right); camera.setHUD(yourHud);首先,创建一个HUD,然后,两个矩形,重写矩形实体的 onAreaTouched以便能处理事件,在场景中注册响应区域,最后把实体加到场景中。别忘了调用Camera的setHUD。l 处
32、理安卓的原生按键消息(native key)在开发应用时候,处理按键消息也很重要。有几个要记住,这是我的观点:(注:这个属于Android Framework 层)1.重写方法:首先,应该重写onKeyDown方法,该方法会捕获电话的回退键。Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) if (keyCode = KeyEvent.KEYCODE_BACK) / perform your actons. return false; 2.处理不同的按键显然,会有很多不同的按键消息,重要的有: KeyEvent.KEYC
33、ODE_HOME KeyEvent.KEYCODE_BACK KeyEvent.KEYCODE_MENU值得一提的是,在有些设备上,没有特定的键,像我的平板就没有Menu键。3.仔细思考我强烈不建议重写系统的HOME/BACK键,因为需要返回 前一个APP,另一个重要因素是:在 Google Play Store 团队为应用排位时也会考虑这个因素。(注:不太了解)l 捕获连续的触屏事件本文讲述如何简单,快速,正确捕获连续触屏事件。假如有一个精灵,需要连续地执行某一动作(如,在X轴上给玩家力来作移动),这里,我使用矩形实体。1. 可能的解法有两个办法,分别介绍:final Rectangle b
34、utton = new Rectangle(0, 0, 100, 100, vbo) Override public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) if (pSceneTouchEvent.isActionMove() / Handle your action here return true; ;如上,重写onAreaTouched 方法并捕获isActionMove。这是个好办法,因为你手指按下时随着手指移动,即使是一,两个
35、像素也会获得连续的移动事件,但并不完美。所以有更好的解法:/ our flagprivate boolean isTouchedFlag = false;/ our buttonfinal Rectangle button = new Rectangle(0, 0, 100, 100, vbo) Override public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) if (pSceneTouchEvent.isActionDown()
36、isTouchedFlag = true; if (pSceneTouchEvent.isActionUp() isTouchedFlag = false; return true; Override protected void onManagedUpdate(float pSecondsElapsed) if (isTouchedFlag) / Execute your actions. super.onManagedUpdate(pSecondsElapsed); ;这个办法使用了Update handler总是有效,因为: 首先,声明一个布尔标志来存储按钮状态。 使用Rectangle
37、声明一个按钮。 重写onAreaTouched 方法捕获事件 . 如果是 isActionDown 按下,设置标志为True (触屏开始) 如果是 isActionUp 抬起设置标志为 false (释放) 这次我们重写 onManageUpdate 检查标志是否为True,如果是则在循环中执行我们的要做的事。l 捕获长时点击(Long Click)按着不放这个事件很容易实现,因为 AE已经内置这个功能了长时点击在界面中很有用,下面代码展示如何在场景中实现这个功能: 首先,必须实现IHoldDetectorListener接口,重写下面三个未实现的方法:Overridepublic void
38、onHoldStarted(HoldDetector pHoldDetector, int pPointerID, float pHoldX, float pHoldY) Overridepublic void onHold(HoldDetector pHoldDetector, long pHoldTimeMilliseconds, int pPointerID, float pHoldX, float pHoldY) Overridepublic void onHoldFinished(HoldDetector pHoldDetector, long pHoldTimeMillisecon
39、ds, int pPointerID, float pHoldX, float pHoldY) 声明一个ContinousHoldDetector 对象private ContinuousHoldDetector continuousHoldDetector; 初始化它,并注册到场景。 注意,这里使用默认的构造函数,如果要自定义一些参数,你也可以使用带参数的构造函数。continuousHoldDetector = new ContinuousHoldDetector(this);yourScene.registerUpdateHandler(continuousHoldDetector);
40、完成后,你就可以在IHoldDetectorListener接口的实现函数里执行自己的代码了 onHoldStarted() - 手指按住一段时间后调用。 onHoldFinished() - 手指离开屏幕后调用。四。基础l HelloWorld本文讲述如何使用AE创建Helloworld。相当简单,不需要有什么经验。使用的引擎为:GLES2确认android开发环境和AE的代码都准备好了。1. 在Eclipse中创建一个Android Project。2.将导入的AE 工程连接成库右键点击AndEngine-属性-Android-Library Field3.在创建的Helloworld工程
41、中,删除自动生成的Java 类.建一个新的类,基类为:SimpleBaseGameActivityIDE会强制你添加未实现的方法.package test.matim;import org.andengine.engine.options.EngineOptions;import org.andengine.entity.scene.Scene;import org.andengine.ui.activity.SimpleBaseGameActivity;public class TestActivity extends SimpleBaseGameActivity Override public EngineOptions onCreateEngineOptions() return null; Override protected void onCreateResources() Override protected Scene onCreateScene() return null;