- 类型:编程控件大小:17.0M语言:中文 评分:5.0
- 标签:
立即下载
接下来你将了解到运用DragonBones创建包含多个动作的骨骼动画,并在程序中通过键盘交互控制动作。
打开文件DragonBones_Tutorial_MultiBehavior.fla,双击库里的动画元件Dragon,你可以看到此动画中有四个动作:stand,walk,jump和fail。每个动作的起始帧上添加了对应的帧标签,这也是DragonBones识别不同动作的标识。
打开骨骼动画编辑面板,你会看到在Behavior List里面会有多个动作,选择某个动作就可以为对应动作设置动画帧数、缓动,设置此动作的某个骨骼的细节参数等。
请留意Behavior编辑里的Blending Times选项。
这个选项是表明的其他动作切换到当前动作需要的过渡时间。例如这里设置的跳跃动作的Blending Times为0.13,那么其他动作切换到跳跃需要0.13秒,DragonBones框架会自动为你添加其中的过渡帧,让各种动作之间切换变得自然。当然,你可以在动画预览窗口中看到各种动画的切换效果。
Dragon Bones插件 v2.3 官方最新版:http://www.cr173.com/soft/68403.html
调整完毕各个动作的细节后,点击“Export”按钮导出骨骼动画数据。
打开DBStarlingMultiBehavior.as文件,代码如下。此示例是在Starling框架中通过键盘控制骨骼动画运动。
PSE: collapse; FONT-FAMILY: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; MAX-WIDTH: 100%; FLOAT: none !important; HEIGHT: auto !important; FONT-SIZE: 1em !important; VERTICAL-ALIGN: baseline !important; OVERFLOW: hidden !important; BORDER-TOP: 0px; TOP: auto !important; RIGHT: auto !important; FONT-WEIGHT: normal !important; BORDER-RIGHT: 0px; PADDING-TOP: 0px !important; LEFT: auto !important; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px" border="0" cellspacing="0" cellpadding="0">package { import dragonBones.Armature; import dragonBones.animation.WorldClock; import dragonBones.factorys.StarlingFactory; import flash.ui.Keyboard; import starling.display.Sprite; import starling.events.EnterFrameEvent; import starling.events.KeyboardEvent; import starling.text.TextField; import flash.events.Event; public class DBStarlingMultiBehavior extends Sprite { [Embed(source = "../assets/Dragon2.png", mimeType = "application/octet-stream")] public static const ResourcesData:Class; private var factory:StarlingFactory; private var armature:Armature; private var armatureClip:Sprite; private var isLeft:Boolean; private var isRight:Boolean; private var isJumping:Boolean; private var moveDir:int=0; private var speedX:Number = 0; private var speedY:Number = 0; private var textField:TextField public function DBStarlingMultiBehavior() { factory = new StarlingFactory(); factory.addEventListener(Event.COMPLETE, textureCompleteHandler); factory.parseData(new ResourcesData()); } private function textureCompleteHandler(e:Event):void { armature = factory.buildArmature("Dragon"); armatureClip = armature.display as Sprite; armatureClip.x = 400; armatureClip.y = 550; addChild(armatureClip); WorldClock.clock.add(armature); updateBehavior() addEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrameHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyEventHandler); stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEventHandler); textField=new TextField(400,30,"A-move left,D-move right,W-jump","Verdana",16,0,true) textField.x=60; textField.y=2; addChild(textField); } private function onKeyEventHandler(e:KeyboardEvent):void { switch (e.keyCode) { case Keyboard.A : case Keyboard.LEFT : isLeft=e.type == KeyboardEvent.KEY_DOWN; break; case Keyboard.D : case Keyboard.RIGHT : isRight=e.type == KeyboardEvent.KEY_DOWN; break; case Keyboard.W : case Keyboard.UP : jump(); break; } var dir:int; if (isLeft && isRight) { dir=moveDir; return; } else if (isLeft) { dir=-1; } else if (isRight) { dir=1; } else { dir=0; } if(dir==moveDir) { return; } else { moveDir=dir; } updateBehavior() } private function onEnterFrameHandler(_e:EnterFrameEvent):void { updateMove(); WorldClock.clock.advanceTime(-1); } private function updateBehavior():void { if (isJumping) { return; } if (moveDir == 0) { speedX = 0; armature.animation.gotoAndPlay("stand"); } else { speedX=6*moveDir; armatureClip.scaleX = -moveDir; armature.animation.gotoAndPlay("walk"); } } private function updateMove():void { if (speedX != 0) { armatureClip.x += speedX; if (armatureClip.x < 0) { armatureClip.x = 0; } else if (armatureClip.x > 800) { armatureClip.x = 800; } } if (isJumping) { if (speedY <= 0 && speedY + 1 > 0 ) { armature.animation.gotoAndPlay("fall"); } speedY += 1; } if (speedY != 0) { armatureClip.y += speedY; if (armatureClip.y > 540) { armatureClip.y = 550; isJumping = false; speedY = 0; updateBehavior(); } } } private function jump():void { if (isJumping) { return; } speedY = -25; isJumping = true; armature.animation.gotoAndPlay("jump"); } } } |
通过上面的代码我们可以发现,我们只需要在程序中需要播放相关骨骼动画的时候调用函数armature.animation.gotoAndPlay()即可。
除了指定需要播放的动作名称,你还可以通过此函数来动态指定动作的总帧数、是否循环等。
对于每个动画,除了指定其播放之外,DragonBones框架提供了动画播放相关的各种事件。
动作切换事件:
armature.addEventListener(dragonbones.events.Event.MOVEMENT_CHANGE, aramtureEventHandler); |
动作开始事件:
armature.addEventListener(dragonbones.events.Event.START, aramtureEventHandler); |
动作结束事件
armature.addEventListener(dragonbones.events.Event.COMPLETE, aramtureEventHandler); |
动作循环完毕事件:
armature.addEventListener(dragonbones.events.Event.LOOP_COMPLETE, aramtureEventHandler); |
通过各种事件与动作的配合,你可以轻松创建具有复杂运动角色的游戏。
控制骨骼框架中的每根骨头
对于一个有趣的游戏,仅仅播放预先设置的骨骼动画或许不够,我们需要角色具有动态可控的各自动作。令人高兴的是DragonBones提供了访问并控制骨骼框架里每根骨头的方法,让你的角色在游戏中随意运动。
此示例通过鼠标在场景中的移动来控制骨骼。我们创建了一个跟随鼠标运动的小鸟,小龙人会与小鸟保持一定距离,同时小龙人的头和胳膊会跟随小鸟运动而做出不同姿势,非常有趣。
打开DBStarlingControlBone.as,代码如下。
package { import dragonBones.Armature; import dragonBones.Bone; import dragonBones.animation.WorldClock; import dragonBones.factorys.StarlingFactory; import flash.geom.Point; import flash.ui.Mouse; import starling.display.Image; import starling.display.Sprite; import starling.events.EnterFrameEvent; import starling.events.TouchEvent; import starling.textures.Texture; import flash.events.Event; public class DBStarlingControlBone extends Sprite { [Embed(source = "../assets/Dragon2.png", mimeType = "application/octet-stream")] public static const ResourcesData:Class; [Embed(source = "../assets/starling.png")] private static const starlingImg:Class; private var factory:StarlingFactory; private var armature:Armature; private var armatureClip:Sprite; private var mouseX:Number = 0; private var mouseY:Number = 0; private var moveDir:int=0; private var dist:Number; private var speedX:Number = 0; private var starlingBird:Image; private var _r:Number; private var _head:Bone; private var _armR:Bone; private var _armL:Bone; public function DBStarlingControlBone() { factory = new StarlingFactory(); factory.addEventListener(Event.COMPLETE, textureCompleteHandler); factory.parseData(new ResourcesData()); } private function textureCompleteHandler(e:Event):void { armature = factory.buildArmature("Dragon"); armatureClip = armature.display as Sprite; armatureClip.x = 400; armatureClip.y = 550; addChild(armatureClip); WorldClock.clock.add(armature); updateBehavior(0) addEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrameHandler); stage.addEventListener(TouchEvent.TOUCH, onMouseMoveHandler); starlingBird=new Image(Texture.fromBitmap(new starlingImg())) addChild(starlingBird); Mouse.hide(); //get the bones which you want to control _head = armature.getBone("head"); _armR = armature.getBone("armUpperR"); _armL = armature.getBone("armUpperL"); } private function onEnterFrameHandler(_e:EnterFrameEvent):void { checkDist(); updateMove(); updateBones(); WorldClock.clock.advanceTime(-1); } private function checkDist():void { dist = armatureClip.x-mouseX; if(dist<150) { updateBehavior(1) } else if(dist>190) { updateBehavior(-1) } else { updateBehavior(0) } } private function onMouseMoveHandler(_e:TouchEvent):void { var _p:Point = _e.getTouch(stage).getLocation(stage); mouseX = _p.x; mouseY = _p.y; starlingBird.x=mouseX-73; starlingBird.y=mouseY-73; } private function updateBehavior(dir:int):void { if(moveDir==dir)return; moveDir=dir; if (moveDir == 0) { speedX = 0; armature.animation.gotoAndPlay("stand"); } else { speedX=6*moveDir; armature.animation.gotoAndPlay("walk"); } } private function updateMove():void { if (speedX != 0) { armatureClip.x += speedX; if (armatureClip.x < 0) { armatureClip.x = 0; } else if (armatureClip.x > 800) { armatureClip.x = 800; } } } private function updateBones():void { //update the bones' pos or rotation _r = Math.PI + Math.atan2(mouseY - armatureClip.y+armatureClip.height/2, mouseX - armatureClip.x); if (_r > Math.PI) { _r -= Math.PI * 2; } _head.node.rotation = _r*0.3 _armR.node.rotation = _r *0.8; _armL.node.rotation = _r * 1.5; starlingBird.rotation=_r*0.2; } } } |
从上面代码我们可以看到,通过方法dragonBones.Armature.getBone(_name:String):Bone来获取某个骨骼。骨骼中的node对象包含了此骨骼的位置坐标,旋转弧度,拉伸比例,倾斜数据等等。我们根据游戏逻辑的需要对骨骼的这些参数赋数,即可实现动态控制此骨骼的效果。
在上面示例中,请留意updateBones()函数里,我们先获取到当前鼠标位置与骨骼框架中心点的夹角,然后根据这个角度,来改变小龙人的头部和胳膊的旋转弧度,从而实现了这个有趣的效果。