Learning Cocos2d-x for XNA(8)——Sprite到哪,我做主
游戏中,作为玩家对Sprite的操作,最基本的就是控制Sprite的移动,做Sprite的主人。着手让Sprite移动起来。
前期准备
添加素材png和plist至内容管道(Content)文件夹plist中,该动画是Sprite跑动的姿势。
wolf_move.plist代码
1 <?xml version="1.0" encoding="UTF-8"?> 2 <plist version="1.0"> 3 <dict> 4 <key>frames</key> 5 <dict> 6 <key>wolf_move1.png</key> 7 <dict> 8 <key>frame</key> 9 <string>{{2,2},{69,98}}</string> 10 <key>offset</key> 11 <string>{-3,-6}</string> 12 <key>sourceSize</key> 13 <string>{75,110}</string> 14 </dict> 15 <key>wolf_move2.png</key> 16 <dict> 17 <key>frame</key> 18 <string>{{73,2},{73,104}}</string> 19 <key>offset</key> 20 <string>{-1,-1}</string> 21 <key>sourceSize</key> 22 <string>{75,110}</string> 23 </dict> 24 <key>wolf_move3.png</key> 25 <dict> 26 <key>frame</key> 27 <string>{{148,2},{75,106}}</string> 28 <key>offset</key> 29 <string>{0,2}</string> 30 <key>sourceSize</key> 31 <string>{75,110}</string> 32 </dict> 33 <key>wolf_move4.png</key> 34 <dict> 35 <key>frame</key> 36 <string>{{2,110},{69,96}}</string> 37 <key>offset</key> 38 <string>{2,-7}</string> 39 <key>sourceSize</key> 40 <string>{75,110}</string> 41 </dict> 42 <key>wolf_move5.png</key> 43 <dict> 44 <key>frame</key> 45 <string>{{73,110},{73,104}}</string> 46 <key>offset</key> 47 <string>{1,-1}</string> 48 <key>sourceSize</key> 49 <string>{75,110}</string> 50 </dict> 51 <key>wolf_move6.png</key> 52 <dict> 53 <key>frame</key> 54 <string>{{148,110},{73,104}}</string> 55 <key>offset</key> 56 <string>{-1,-1}</string> 57 <key>sourceSize</key> 58 <string>{75,110}</string> 59 </dict> 60 <key>wolf_move7.png</key> 61 <dict> 62 <key>frame</key> 63 <string>{{2,216},{69,98}}</string> 64 <key>offset</key> 65 <string>{-3,-6}</string> 66 <key>sourceSize</key> 67 <string>{75,110}</string> 68 </dict> 69 </dict> 70 <key>metadata</key> 71 <dict> 72 <key>format</key> 73 <integer>1</integer> 74 <key>realTextureFileName</key> 75 <string>wolf_move.png</string> 76 <key>size</key> 77 <string>{256,512}</string> 78 <key>smartupdate</key> 79 <string>$TexturePacker:SmartUpdate:fd81634a22eb23d48bf69caa8d75bd21$</string> 80 <key>textureFileName</key> 81 <string>wolf_move.png</string> 82 </dict> 83 </dict> 84 </plist>
还是老样子,先添加两个类MoveScene和MoveLayer
MoveScene修改后代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using cocos2d; namespace LearningCocos2d_xForXNA.Classes { class MoveScene:CCScene { public MoveScene() { CCLayer _moveLayer = new MoveLayer(); this.addChild(_moveLayer); } } }
MoveLayer中,我们先添加上讲主讲的帧频动画的效果,实现Sprite跑动动画。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using cocos2d; 6 7 namespace LearningCocos2d_xForXNA.Classes 8 { 9 class MoveLayer:CCLayer 10 { 11 public MoveLayer() 12 { 13 CCDirector.sharedDirector().deviceOrientation = ccDeviceOrientation.kCCDeviceOrientationPortraitUpsideDown;//设置朝向,竖屏 14 #region Sprite跑动动画 15 CCSize s = CCDirector.sharedDirector().getWinSize(); 16 // 创建批处理节点,读取plist文件 17 CCSpriteBatchNode batch = CCSpriteBatchNode.batchNodeWithFile("plist/images/wolf_move");//批处理节点贴图 18 addChild(batch, 0, 1); 19 CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("plist/wolf_move");//读取plsit文件 20 //起始精灵 21 CCSprite sprite1 = CCSprite.spriteWithSpriteFrameName("wolf_move1.png"); 22 sprite1.position = (new CCPoint(s.width / 3, s.height / 2)); 23 batch.addChild(sprite1); 24 // 创建逐帧数组 25 List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>(); 26 string str = ""; 27 for (int i = 2; i < 8; i++) 28 { 29 string temp = ""; 30 temp = i.ToString(); 31 str = string.Format("wolf_move{0}.png", temp); 32 CCSpriteFrame frame = CCSpriteFrameCache.sharedSpriteFrameCache().spriteFrameByName(str); 33 animFrames.Add(frame); 34 } 35 //动画Animate 36 CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.2f);//Animation动画信息 37 sprite1.runAction(CCRepeatForever.actionWithAction(CCAnimate.actionWithAnimation(animation, false)));//执行动画 38 #endregion 39 40 41 } 42 } 43 }
运行显示效果,我们可发现Sprite原地跑动起来了。
原地跑动不是真正跑动,只有真正的结合距离移动了才是跑动嘛。
直线移动选择CCMove即可,即是移动的动作类(Action)的子类。
该方法中提供了一个方法调用
public static CCMoveTo actionWithDuration(float duration, CCPoint position);
duration:持续的时间
position:移动的目标位置
在之前MoveLayer中的代码基础上,添加
sprite1.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(0, 0)));//移动到坐标(0,0)位置
修改后代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using cocos2d; 6 7 namespace LearningCocos2d_xForXNA.Classes 8 { 9 class MoveLayer:CCLayer 10 { 11 public MoveLayer() 12 { 13 CCDirector.sharedDirector().deviceOrientation = ccDeviceOrientation.kCCDeviceOrientationPortraitUpsideDown;//设置朝向,竖屏 14 #region Sprite跑动动画 15 CCSize s = CCDirector.sharedDirector().getWinSize(); 16 // 创建批处理节点,读取plist文件 17 CCSpriteBatchNode batch = CCSpriteBatchNode.batchNodeWithFile("plist/images/wolf_move");//批处理节点贴图 18 addChild(batch, 0, 1); 19 CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("plist/wolf_move");//读取plsit文件 20 //起始精灵 21 CCSprite sprite1 = CCSprite.spriteWithSpriteFrameName("wolf_move1.png"); 22 sprite1.position = (new CCPoint(s.width / 3, s.height / 2)); 23 batch.addChild(sprite1); 24 // 创建逐帧数组 25 List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>(); 26 string str = ""; 27 for (int i = 2; i < 8; i++) 28 { 29 string temp = ""; 30 temp = i.ToString(); 31 str = string.Format("wolf_move{0}.png", temp); 32 CCSpriteFrame frame = CCSpriteFrameCache.sharedSpriteFrameCache().spriteFrameByName(str); 33 animFrames.Add(frame); 34 } 35 //动画Animate 36 CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.2f);//Animation动画信息 37 sprite1.runAction(CCRepeatForever.actionWithAction(CCAnimate.actionWithAnimation(animation, false)));//执行动画 38 #endregion 39 40 sprite1.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(0, 0)));//移动到坐标(0,0)位置 41 } 42 } 43 }
运行显示效果,可以看到,Sprite不慌不忙地跑到坐标(0,0)位置。
在实际运动过程中,匀速运动在启动和结束时往往会有一定的加速和减速的效果,这样更加的真实。
cocoos2d-x引擎提供了相关的API,免除了我们编写相关的算法实现的烦恼,实现起来相当的方便。
实现该方法的是CCActionEase中CCEaseRateAction系列,大体分成三类:
In:开始时候的加速度
Out:结束时候的加速度
InOut:开始结束时候的加速度
(以下图片来源其他博文,具体地址忘记了,以后再加上)
1.指数缓冲
EaseExponentialIn
EaseExponentialOut
EaseExponentialInOut
2.赛因缓冲
EaseSineIn
EaseSineOut
EaseSineInOut
3.弹性缓冲
EaseElasticIn
EaseElasticOut
EaseElasticInOut
4.跳跃缓冲
EaseBounceIn
EaseBounceOut
EaseBounceInOut
5.回震缓冲
EaseBackIn
EaseBackOut
EaseBackInOut
以上各类中中包含各自创建的static方法。
actionWithAction(CCActionInterval pAction)
在代码基础上添加如下代码
记得先注释之前的动作
//直线匀速 //sprite1.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(0, 0)));//移动到坐标(0,0)位置 #region CCEaseInOut CCActionInterval move = CCMoveBy.actionWithDuration(3, new CCPoint(280, 0));//CCMoveBy是相当位移动作 CCActionInterval move_ease_inout = CCEaseInOut.actionWithAction(move);//ease缓冲 sprite1.runAction(move_ease_inout); #endregion
需要注意的是CCMoveBy和CCMoveTo的不同,CCMoveBy移动的位置是相对位置。
修改后代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using cocos2d; 6 7 namespace LearningCocos2d_xForXNA.Classes 8 { 9 class MoveLayer:CCLayer 10 { 11 public MoveLayer() 12 { 13 CCDirector.sharedDirector().deviceOrientation = ccDeviceOrientation.kCCDeviceOrientationPortraitUpsideDown;//设置朝向,竖屏 14 #region Sprite跑动动画 15 CCSize s = CCDirector.sharedDirector().getWinSize(); 16 // 创建批处理节点,读取plist文件 17 CCSpriteBatchNode batch = CCSpriteBatchNode.batchNodeWithFile("plist/images/wolf_move");//批处理节点贴图 18 addChild(batch, 0, 1); 19 CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("plist/wolf_move");//读取plsit文件 20 //起始精灵 21 CCSprite sprite1 = CCSprite.spriteWithSpriteFrameName("wolf_move1.png"); 22 sprite1.position = (new CCPoint(s.width / 3, s.height / 2)); 23 batch.addChild(sprite1); 24 // 创建逐帧数组 25 List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>(); 26 string str = ""; 27 for (int i = 2; i < 8; i++) 28 { 29 string temp = ""; 30 temp = i.ToString(); 31 str = string.Format("wolf_move{0}.png", temp); 32 CCSpriteFrame frame = CCSpriteFrameCache.sharedSpriteFrameCache().spriteFrameByName(str); 33 animFrames.Add(frame); 34 } 35 //动画Animate 36 CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.2f);//Animation动画信息 37 sprite1.runAction(CCRepeatForever.actionWithAction(CCAnimate.actionWithAnimation(animation, false)));//执行动画 38 #endregion 39 40 //直线匀速 41 //sprite1.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(0, 0)));//移动到坐标(0,0)位置 42 43 44 #region CCEaseInOut 45 CCActionInterval move = CCMoveBy.actionWithDuration(3, new CCPoint(280, 0));//CCMoveBy是相当位移动作 46 CCActionInterval move_ease_inout = CCEaseInOut.actionWithAction(move);//ease缓冲 47 sprite1.runAction(move_ease_inout); 48 #endregion 49 } 50 } 51 }
显示效果,可发现sprite运动时有了一定的缓冲的效果,使得更符合实际情况。
当然CCActionEase类还有很多现成的效果,可自行测试。
游戏中应该由我们游戏者控制sprite的运动才是真正的游戏嘛,的确,我们应该成为主人,主动控制sprite的移动位置。
CCTouch触摸
事件驱动同样适用于cocos2d-x引擎,cocos2d-x的触屏事件可分为单点和多点触屏。
一般用到情况有:Layer统一接受触屏消息,然后由程序根据需要分发给不同位置的sprite;自定义可接收触屏事件的sprite。
Layer层实现触屏事件
1.开启触屏事件
在Layer层初始化的时候设置
base.isTouchEnabled = true;//开启触屏事件
2.重写(覆盖)父类CCLayer的方法
以下为CCLayer类的虚方法
public virtual bool ccTouchBegan(CCTouch touch, CCEvent event_); public virtual void ccTouchCancelled(CCTouch touch, CCEvent event_); public virtual void ccTouchEnded(CCTouch touch, CCEvent event_); public virtual void ccTouchesBegan(List<CCTouch> touches, CCEvent event_); public virtual void ccTouchesCancelled(List<CCTouch> touches, CCEvent event_); public virtual void ccTouchesEnded(List<CCTouch> touches, CCEvent event_); public virtual void ccTouchesMoved(List<CCTouch> touches, CCEvent event_); public virtual void ccTouchMoved(CCTouch touch, CCEvent event_);
Begin:触屏事件开始
Ended:触屏事件结束
Moved:触屏拖动
根据具体情况,改写自己需要的触屏事件方法。
注意:cocos2d-x for xna(0.1.2)版本中
public override void ccTouchEnded(CCTouch touch, CCEvent event_)
似乎出现BUG,测试无响应。
重写ccTouchesEnded,目的是通过点击屏幕任意一点后,触屏事件获取触点坐标,然后sprite再runAction到该触点的坐标位置。
修改后代码
/// <summary> /// 触屏事件Ended处理函数 /// </summary> /// <param name="touches"></param> /// <param name="event_"></param> public override void ccTouchesEnded(List<CCTouch> touches, CCEvent event_) { object sender = touches.First();//获取第一个触点 CCTouch touch = (CCTouch)(sender); CCPoint touchLocation = touch.locationInView(touch.view());//获取触屏的坐标位置 CCPoint convertedLocation = CCDirector.sharedDirector().convertToGL(touchLocation);//转换坐标位置 //执行运动 CCActionInterval move = CCMoveTo.actionWithDuration(3, convertedLocation); CCActionInterval move_ease_inout = CCEaseInOut.actionWithAction(move);//ease缓冲 sprite1.runAction(move_ease_inout); }
注意一下,坐标系转换,xna(wp)中是以左上角为坐标系原点,cococs2d-x以左下角为坐标系原点,所以,在获取坐标点后,需要转换坐标系。
CCPoint convertedLocation = CCDirector.sharedDirector().convertToGL(touchLocation);//转换坐标位置
运行显示效果,在屏幕上任何位置触摸后,sprite会向着该触点移动。
Sprite自定义触屏事件
1.前期准备
还是得创建两个类SpriteDefinedTouchScene和SpriteDefinedTouchLayer。
SpriteDefinedTouchScene
using System; using System.Collections.Generic; using System.Linq; using System.Text; using cocos2d; namespace LearningCocos2d_xForXNA.Classes { class SpriteDefinedTouchScene:CCScene { public SpriteDefinedTouchScene() { CCLayer spriteDefinedTouchLayer = new SpriteDefinedTouchLayer(); this.addChild(spriteDefinedTouchLayer); } } }
2.创建一个类继承CCSprite和Touch相关接口
要使sprite实现自定义touch必须继承相关的touch接口。
TouchableSprite类
代码如下
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using cocos2d; 6 7 namespace LearningCocos2d_xForXNA.Classes 8 { 9 class TouchableSprite : CCSprite, ICCTargetedTouchDelegate 10 { 11 public new bool spriteWithSpriteFrameName(string pszSpriteFrameName) 12 { 13 base.initWithSpriteFrameName(pszSpriteFrameName); 14 return true; 15 } 16 17 public override void onEnter() 18 { 19 CCTouchDispatcher.sharedDispatcher().addTargetedDelegate(this, 0, true); 20 base.onEnter(); 21 } 22 23 public override void onExit() 24 { 25 CCTouchDispatcher.sharedDispatcher().removeDelegate(this); 26 base.onExit(); 27 } 28 29 public virtual bool ccTouchBegan(CCTouch touch, CCEvent eventer) 30 { 31 return true; 32 } 33 34 public virtual void ccTouchMoved(CCTouch touch, CCEvent eventer) 35 {} 36 37 public virtual void ccTouchEnded(CCTouch touch, CCEvent eventer) 38 { 39 CCPoint touchPoint = touch.locationInView(touch.view()); 40 CCPoint convertedLocation = CCDirector.sharedDirector().convertToGL(touchPoint); 41 42 //执行运动 43 CCActionInterval move = CCMoveTo.actionWithDuration(3, convertedLocation); 44 CCActionInterval move_ease_inout = CCEaseInOut.actionWithAction(move);//ease缓冲 45 base.runAction(move_ease_inout); 46 } 47 48 public void ccTouchCancelled(CCTouch pTouch, CCEvent pEvent) 49 { 50 throw new NotImplementedException(); 51 } 52 } 53 }
ICCTargetedTouchDelegate接口中含有四个方法,在子类中须全部覆盖。onEnter和onExit方法目的是使touch事件有效。我们在onTouchEnded事件中添加action。
3.添加Layer代码
我们在之前MoveLayer中复制大部分的代码到SpriteDefinedTouchLayer中,做几处修改即可.
SpriteDefinedTouchLayer修改后的代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using cocos2d; 6 7 namespace LearningCocos2d_xForXNA.Classes 8 { 9 class SpriteDefinedTouchLayer:CCLayer 10 { 11 TouchableSprite sprite1; 12 public SpriteDefinedTouchLayer() 13 { 14 base.isTouchEnabled = true;//开启触屏事件 15 CCDirector.sharedDirector().deviceOrientation = ccDeviceOrientation.kCCDeviceOrientationPortraitUpsideDown;//设置朝向,竖屏 16 #region Sprite跑动动画 17 CCSize s = CCDirector.sharedDirector().getWinSize(); 18 // 创建批处理节点,读取plist文件 19 CCSpriteBatchNode batch = CCSpriteBatchNode.batchNodeWithFile("plist/images/wolf_move");//批处理节点贴图 20 addChild(batch, 0, 1); 21 CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("plist/wolf_move");//读取plsit文件 22 //起始精灵 23 sprite1 = new TouchableSprite(); 24 sprite1.initWithSpriteFrameName("wolf_move1.png"); 25 sprite1.position = (new CCPoint(s.width / 3, s.height / 2)); 26 batch.addChild(sprite1); 27 // 创建逐帧数组 28 List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>(); 29 string str = ""; 30 for (int i = 2; i < 8; i++) 31 { 32 string temp = ""; 33 temp = i.ToString(); 34 str = string.Format("wolf_move{0}.png", temp); 35 CCSpriteFrame frame = CCSpriteFrameCache.sharedSpriteFrameCache().spriteFrameByName(str); 36 animFrames.Add(frame); 37 } 38 //动画Animate 39 CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.2f);//Animation动画信息 40 sprite1.runAction(CCRepeatForever.actionWithAction(CCAnimate.actionWithAnimation(animation, false)));//执行动画 41 #endregion 42 } 43 } 44 }
运行显示效果,同样得到和“Layer层实现触屏事件”的效果。
著作权声明:本文由http://www.cnblogs.com/suguoqiang 原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!