Learning Cocos2d-x for XNA(8)——Sprite到哪,我做主

游戏中,作为玩家对Sprite的操作,最基本的就是控制Sprite的移动,做Sprite的主人。着手让Sprite移动起来。

前期准备

添加素材png和plist至内容管道(Content)文件夹plist中,该动画是Sprite跑动的姿势。

wolf_move.plist代码

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跑动动画。

MoveLayer
 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)位置

修改后代码

MoveLayer
 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移动的位置是相对位置。

修改后代码

MoveLayer
 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类

代码如下

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修改后的代码

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 原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

posted @ 2013-02-24 20:40 Ghost Soar 阅读(...) 评论(...) 编辑 收藏