Learning Cocos2d-x for XNA(9)——碰撞檢測


游戲中碰撞的檢測相當重要,任何兩個sprite間都避免不了有交集,碰撞檢測也體現了游戲的真實性。

矩形檢測

矩形檢測是一種實現方式比較簡單的檢測方式,簡單就意味着不那么真實。原理就是將sprite紋理抽象出一個Rect,然后通過判斷Rect間是否相交,以此作為sprite的碰撞檢測。這種碰撞檢測是不精確的,當然,如果游戲要求不高,還是可以的。

可見,構建矩形框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。

 

著作權聲明:本文由http://www.cnblogs.com/suguoqiang 原創,歡迎轉載分享。請尊重作者勞動,轉載時保留該聲明和作者博客鏈接,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM