前言
會寫這篇文章主要是看到網路上有人詢問控制CCSprite的問題,想寫個類似Candy Crash置換圖片的控制。提到是否有效能比較好的作法!我個人是覺得不要一個一個pixel去拜訪效能就不會太差。這次寫一個簡易版的,測試結果還蠻順的啊,提供給大家參考參考。
執行結果
點選一個Candy,再拉到另一個Cindy,放手之後就會移動嚕。
初始畫面
點選(1,0)與(1,1)的方塊
置換後
開發環境
作業系統:Win7
開發工具:VC Express 2010
Cocos2dx版本:2.1.beta3
出發~HelloCpp,環境的設定
這次一樣拿HelloCpp專案修改,先設定一些環境,開啟HelloWorldScene.h,新增一下下面的設定,後面的程式寫起來才比較乾淨。
#ifndef __HELLOWORLD3_SCENE_H__
#define __HELLOWORLD3_SCENE_H__
#include "cocos2d.h"
using namespace cocos2d;
新增一下 using namespace cocos2d; 這樣後續宣告變數時,有關于cocos2d的型別就不用前面再加 cocos2d:: ,程式碼看起來就會比較舒服。
再來,定義一下我們要放置旗盤的大小,這次設定成5x5的盤。設定成有5種類型的candy。
#ifndef __HELLOWORLD3_SCENE_H__
#define __HELLOWORLD3_SCENE_H__
#include "cocos2d.h"
using namespace cocos2d;
#define MAX_ROW 5
#define MAX_COL 5
#define NUM_OF_CANDY MAX_ROW*MAX_COL
#define MAX_TYPE 5 //紅黃綠藍澄
MAX_ROW 表示有5列,MAX_COL表示有5行,所以總共可以放25個Candy(NUM_OF_CANDY),MAX_TYOE是假設Candy分別為紅黃綠藍澄這五種。
宣告,一堆Candy的變數
在HelloWorld類別中,新增放至Candy圖片的變數,大小就是總Candy數大小。
CCSprite* m_apImgBlock[NUM_OF_CANDY];
定義Candy位置
這次先把各位置Candy作標訂好,在Create時就可以方便取用。開啟HelloWorldScene.cpp,在檔案上頭我們定義位置如下
#include "HelloWorldScene3.h"
#include "AppMacros.h"
#include "base64.h"
USING_NS_CC;
float g_afPosX[MAX_COL]={
145, 199, 253, 308, 361
};
float g_afPosY[MAX_ROW]={
244, 190, 137, 84, 31
};
Create Candy
開啟HelloWorldScene.cpp,編輯init(),新增create sprite的內容
// on "init" you need to initialize your instance
bool HelloWorld3::init()
{
//以上省略
//--------------------
// Blocks create
for(int c=0;c<MAX_COL;c++)
{
for(int r=0;r<MAX_ROW;r++)
{
int iSeed = rand()%MAX_TYPE;
char acName[20];
memset(acName,0,sizeof(acName));
sprintf(acName,"BLOCK%02d.jpg",iSeed+1);
m_apImgBlock[(r*MAX_COL)+c] = CCSprite::create(acName);
m_apImgBlock[(r*MAX_COL)+c]->setAnchorPoint(ccp(0,0));
m_apImgBlock[(r*MAX_COL)+c]->setPosition(ccp(g_afPosX[c],g_afPosY[r]));
this->addChild(m_apImgBlock[(r*MAX_COL)+c]);
}
}
return true;
}
說明一下,我們隨機rand出25個candy,五個Candy圖檔分別為"BLOCK01.jpg"~"BLOCK05.jpg"。在設定setPosition時,我們將剛剛定義的位置放進去。
第一次的執行結果
寫好之後Run一下,可以得到結果如下。
觸碰環境設置
回到HelloWorldScene.h,要宣告一些觸碰處理的虛擬函數讓我們overwrite它們。
// 觸碰處理
void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
這時候我們還需要兩個變數,一個記錄點到candy的索引,另一個記錄目標轉換的candy的索引。分別為m_iStIdx與m_iEdIdx。
// 觸碰處理
void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
int m_iStIdx;
int m_iEdIdx;
CCSprite* m_apImgBlock[NUM_OF_CANDY];
實作控制
至HelloWorldScene.h,立即實作virtual function。
void HelloWorld3::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)( pTouches->anyObject() );
CCPoint location = touch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
//--------------------
// Blocks process
for(int i=0;i<NUM_OF_CANDY;i++)
{
if(m_apImgBlock[i]->numberOfRunningActions()>0) return;
}
m_iStIdx=-1;
m_iEdIdx=-1;
for(int c=0;c<MAX_COL;c++)
{
for(int r=0;r<MAX_ROW;r++)
{
CCRect rect = m_apImgBlock[(r*MAX_COL)+c]->boundingBox();
if(rect.containsPoint(location))
{
CCLog("click block begin %d",(r*MAX_COL)+c);
m_iStIdx=(r*MAX_COL)+c;
break;
}
}
}
}
..
void HelloWorld3::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)( pTouches->anyObject() );
CCPoint location = touch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
//--------------------
// Blocks process
if((m_iStIdx<0)||(m_iEdIdx>=0)) return;
CCRect rectSrc = m_apImgBlock[m_iStIdx]->boundingBox();
if(!rectSrc.containsPoint(location)){
for(int c=0;c<MAX_COL;c++){
for(int r=0;r<MAX_ROW;r++){
CCRect rect = m_apImgBlock[(r*MAX_COL)+c]->boundingBox();
if(rect.containsPoint(location)){
CCLog("click block end %d",(r*MAX_COL)+c);
m_iEdIdx=(r*MAX_COL)+c;
break;
}
}
}
}
}
..
void HelloWorld3::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)( pTouches->anyObject() );
CCPoint location = touch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
//--------------
// change position
if((m_iStIdx>=0)&&(m_iEdIdx>=0))
{
CCPoint p1 = m_apImgBlock[m_iStIdx]->getPosition();
CCPoint p2 = m_apImgBlock[m_iEdIdx]->getPosition();
m_apImgBlock[m_iStIdx]->runAction(CCMoveTo::create(0.5f,p2));
m_apImgBlock[m_iEdIdx]->runAction(CCMoveTo::create(0.5f,p1));
}
m_iStIdx=-1;
m_iEdIdx=-1;
}
最後Run一下,點選一個Candy,再拉到另一個Cindy,放手之後就會移動嚕。時間問題來不及寫清楚最後一段的說明,之後會補上更新。