Learning Cocos2d-x for XNA(9)——碰撞检测

游戏中碰撞的检测相当重要,任何两个sprite间都避免不了有交集,碰撞检测也体现了游戏的真实性。

矩形检测

矩形检测是一种实现方式比较简单的检测方式,简单就意味着不那么真实。原理就是将sprite纹理抽象出一个Rect,然后通过判断Rect间是否相交,以此作为sprite的碰撞检测。这种碰撞检测是不精确的,当然,如果游戏要求不高,还是可以的。

Learning Cocos2d-x for XNA(9)——碰撞检测

可见,构建矩形框Rect(黑色)后,判断Rect相交即可实现碰撞检测,但无论矩形如何设置,难免会有“盲点”使得检测不那么精确(第3种情况)。

CCRect.CCRectIntersetsRect

Cocos2d-x提供了方法判断Rect是否相交的方法。

游戏规则

为了讲解碰撞检测,简单地设计一个游戏,游戏的规则是:玩家通过触碰屏幕操作Wolf的移动,Gold与Bomb随机从屏幕上端往下移动。Wolf与Gold碰撞得分,Wolf与Bomb碰撞扣分。很简单检测碰撞的游戏。

前提

还是老样子,添加游戏关键两层(Scene和Layer)GameScene、GameLayer。

GameScene
 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 GameScene:CCScene

10     {

11         public GameScene()

12         {

13             CCLayer gameLayer = new GameLayer();

14             this.addChild(gameLayer);

15         }

16     }

17 }

Sprite

Gold:继承CCSprite,构造方法中,添加各类的纹理图片,通过随机函数设置Gold的起始位置和运动,同时通过方法collideWithWolf检测是否与Wolf对象碰撞。

Gold
 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 Gold:CCSprite

10     {

11         public Gold(CCLayer layer)

12         {

13             Random rnd = new Random();

14             float posionX = 100 * (float)rnd.Next(1, 4);//Gold起始位置X坐标值

15             this.initWithFile("img/Wolf/Others/gold");

16             this.position = new CCPoint(posionX, 850);//Gold起始位置

17             layer.addChild(this);

18             this.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(posionX, -50)));//运动,垂直向下运动

19         }

20 

21         /// <summary>

22         /// 创建检测碰撞Rect

23         /// </summary>

24         /// <returns>返回用于检测碰撞的Rect</returns>

25         public CCRect rect()

26         {

27             CCSize s = Texture.getContentSize();//Gold纹理的大小

28             return new CCRect(this.position.x, this.position.y, this.contentSize.width/2, this.contentSize.height/2);//设置Rect

29         }

30 

31         /// <summary>

32         /// 检测是否与Wolf对象碰撞

33         /// </summary>

34         /// <param name="wolf"></param>

35         /// <returns>碰撞返回true,否则返回false</returns>

36         public bool collideWithWolf(Wolf wolf)

37         {

38             CCRect wolfRect = wolf.rect();

39             if(CCRect.CCRectIntersetsRect(wolfRect,rect()))//通过Rect是否相交判断是否碰撞

40             {

41                 return true;

42             }

43             return false;

44         }

45     }

46 }

Bomb:继承CCSprite,构造方法中,添加各类的纹理图片,通过随机函数设置Bomb的起始位置和运动,同时通过方法collideWithWolf检测是否与Wolf对象碰撞。

Bomb
 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 Bomb:CCSprite

10     {

11         public Bomb(CCLayer layer)

12         {

13             Random rnd = new Random();

14             float posionX = 100 * (float)rnd.Next(1, 4);//Gold起始位置X坐标值

15             this.initWithFile("img/Wolf/Others/bomb");

16             this.position = new CCPoint(posionX, 850);//Gold起始位置

17             layer.addChild(this);

18             this.runAction(CCMoveTo.actionWithDuration(5.0f, new CCPoint(posionX, -50)));//运动,垂直向下运动

19         }

20 

21         /// <summary>

22         /// 创建检测碰撞Rect

23         /// </summary>

24         /// <returns>返回用于检测碰撞的Rect</returns>

25         public CCRect rect()

26         {

27             CCSize s = Texture.getContentSize();//Bomb纹理的大小

28             return new CCRect(this.position.x, this.position.y, this.contentSize.width/2, this.contentSize.height/2);//设置Rect

29         }

30 

31         /// <summary>

32         /// 检测是否与Wolf对象碰撞

33         /// </summary>

34         /// <param name="wolf"></param>

35         /// <returns>碰撞返回true,否则返回false</returns>

36         public bool collideWithWolf(Wolf wolf)

37         {

38             CCRect wolfRect = wolf.rect();

39             if(CCRect.CCRectIntersetsRect(wolfRect,rect()))//通过Rect是否相交判断是否碰撞

40             {

41                 return true;

42             }

43             return false;

44         }

45     }

46 }

Wolf:继承CCSprite和ICCTargetedTouchDelegate接口,构造方法中,返回对象的用于检测碰撞的Rect。ICCTargetedTouchDelegate接口是为了实现触摸屏使得Wolf移动(上讲有讲解)。在runing方法中实现Sprite跑动动画。

Wolf
 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 Wolf:CCSprite, ICCTargetedTouchDelegate

10     {

11         /// <summary>

12         /// 创建检测碰撞Rect

13         /// </summary>

14         /// <returns>返回用于检测碰撞的Rect</returns>

15         public CCRect rect()

16         {

17             CCSize s = Texture.getContentSize();//Wolf纹理的大小

18             return new CCRect(this.position.x, this.position.y, this.contentSize.width / 2, this.contentSize.height / 2);//设置Rect

19         }

20 

21         public override void onEnter()

22         {

23             CCTouchDispatcher.sharedDispatcher().addTargetedDelegate(this, 0, true);

24             base.onEnter();

25         }

26 

27         public override void onExit()

28         {

29             CCTouchDispatcher.sharedDispatcher().removeDelegate(this);

30             base.onExit();

31         }

32 

33         public virtual bool ccTouchBegan(CCTouch touch, CCEvent eventer)

34         {

35             return true;

36         }

37 

38         public virtual void ccTouchMoved(CCTouch touch, CCEvent eventer)

39         { }

40 

41         /// <summary>

42         /// 触摸屏Ended事件

43         /// </summary>

44         /// <param name="touch"></param>

45         /// <param name="eventer"></param>

46         public virtual void ccTouchEnded(CCTouch touch, CCEvent eventer)

47         {

48             CCPoint touchPoint = touch.locationInView(touch.view());

49             CCPoint convertedLocation = CCDirector.sharedDirector().convertToGL(touchPoint);

50 

51             //执行运动

52             CCActionInterval move = CCMoveTo.actionWithDuration(2, convertedLocation);

53             CCActionInterval move_ease_inout = CCEaseInOut.actionWithAction(move);//ease缓冲

54             base.runAction(move_ease_inout);

55         }

56 

57         public void ccTouchCancelled(CCTouch pTouch, CCEvent pEvent)

58         {

59             throw new NotImplementedException();

60         }

61 

62         public void runing(CCLayer cclayer)

63         {

64             #region  Sprite跑动动画

65             CCSize s = CCDirector.sharedDirector().getWinSize();

66             // 创建批处理节点,读取plist文件

67             CCSpriteBatchNode batch = CCSpriteBatchNode.batchNodeWithFile("plist/images/wolf_move");//批处理节点贴图

68             cclayer.addChild(batch, 0, 1);

69             CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("plist/wolf_move");//读取plsit文件

70             //起始精灵

71             

72             this.initWithSpriteFrameName("wolf_move1.png");

73             this.position = (new CCPoint(s.width / 3, s.height / 2));

74             batch.addChild(this);

75             // 创建逐帧数组

76             List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>();

77             string str = "";

78             for (int i = 2; i < 8; i++)

79             {

80                 string temp = "";

81                 temp = i.ToString();

82                 str = string.Format("wolf_move{0}.png", temp);

83                 CCSpriteFrame frame = CCSpriteFrameCache.sharedSpriteFrameCache().spriteFrameByName(str);

84                 animFrames.Add(frame);

85             }

86             //动画Animate

87             CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.2f);//Animation动画信息

88             this.runAction(CCRepeatForever.actionWithAction(CCAnimate.actionWithAnimation(animation, false)));//执行动画

89             #endregion

90         }

91     }

92 }

Layer

在GameLayer中,构造方法中,实例化得分面板(记录分数),初始化Wolf,然后通过调用schedule方法不断地产生Gold和Bomb,在方法collide中不断地检测Wolf与Gold、Bomb的碰撞情况。

GameLayer
 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 GameLayer:CCLayer

10     {

11         Random rnd=new Random();//随机变量

12         const int likelihoodGold = 70;//产生Gold的比例

13         const int likelihoodBomb = 30;//产生Bomb的比例

14         CCLabelTTF lblScore;//文本,记录游戏得分

15         int score;//得分

16         Wolf wolf;//主角

17         List<Gold> golds = new List<Gold>();//用于存储Gold对象

18         List<Bomb> bombs = new List<Bomb>();//用于存储Bomb对象

19         public GameLayer()

20         {

21             base.isTouchEnabled = true;//开启触屏事件

22             CCDirector.sharedDirector().deviceOrientation = ccDeviceOrientation.kCCDeviceOrientationPortraitUpsideDown;//设置朝向,竖屏

23 

24             //得分

25             score = 0;

26             lblScore = CCLabelTTF.labelWithString(string.Format("得分:{0}",score), "Yahei", 30);

27             lblScore.position = new CCPoint(100, 100);

28             this.addChild(lblScore);

29 

30             wolf = new Wolf();

31             wolf.runing(this);//Sprite跑动动画

32 

33             this.schedule(CreateGoldOrBomb, 3.0f);//每隔3.0秒调用函数,类似线程

34             this.schedule(collide);//默认下1.0/60s执行

35             

36         }

37 

38         /// <summary>

39         /// 创建Gold对象

40         /// </summary>

41         /// <param name="dt">时间间隔</param>

42         public void CreateGoldOrBomb(float dt)

43         {

44             int random = rnd.Next(1, 100);//产生1-100间随机数

45             if (random < 30)//产生Bomb

46             {

47                 Bomb bomb = new Bomb(this);

48                 bombs.Add(bomb);

49             }

50             else//产生Gold

51             {

52                 Gold gold = new Gold(this);

53                 golds.Add(gold);

54             }

55         }

56 

57         /// <summary>

58         /// 碰撞检测

59         /// </summary>

60         /// <param name="dt"></param>

61         public void collide(float dt)

62         {

63             for (int i = 0; i < golds.Count; i++)//遍历golds

64             {

65                 if (golds[i].collideWithWolf(wolf))//调用Gold判断碰撞的方法,如果碰撞返回true,否则返回false

66                 {

67                     removeChild(golds[i], true);//将碰撞的Gold节点移除

68                     golds.RemoveAt(i);//移除泛型golds中节点

69                     lblScore.setString(string.Format("得分:{0}", (++score).ToString().Trim()));//得分

70                 }

71             }

72             for (int i = 0; i < bombs.Count; i++)//遍历bombs

73             {

74                 if (bombs[i].collideWithWolf(wolf))//调用Bomb判断碰撞的方法,如果碰撞返回true,否则返回false

75                 {

76                     removeChild(bombs[i], true);//将碰撞的Bomb节点移除

77                     bombs.RemoveAt(i);//移除泛型bombs中节点

78                     lblScore.setString(string.Format("得分:{0}", (--score).ToString().Trim()));//扣分

79                 }

80             }

81         }

82     }

83 }

进行游戏

游戏中,触摸屏幕操作Wolf的移动,去吃Gold得分,避开Bomb。

Learning Cocos2d-x for XNA(9)——碰撞检测

 

著作权声明:本文由http://www.cnblogs.com/suguoqiang 原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

你可能感兴趣的:(cocos2d-x)