這裏我們基於一個cocos2dx-x引擎的貪食豆小遊戲,簡單實現手柄與計分板等交互功能。
運行遊戲發現,吃到了豆豆也不會有分數獎勵,甚至手柄連豆豆的上下移動都沒有實現。
可以發現,源碼是指定左右和暫停來控制角色的移動,我們改用計算角度和力度來控制角色移動。
// 獲取搖桿角度
float Joystick::getAngle()
{
TouchPoint_Angle = atan2f((m_currentPoint - m_centerPoint).y, (m_currentPoint - m_centerPoint).x);
return TouchPoint_Angle;
}
// 獲取搖桿力度
float Joystick::getVelocity()
{
TouchPoint_Distanse = m_centerPoint.getDistance(m_currentPoint);
return 1.0 * TouchPoint_Distanse / m_radius;
}
然後通過計算所得的角度和力度分別更新角色橫縱座標,而且需要防止超出遊戲界面
// 通過角度和力度控制角色移動
if (m_joystick->getVelocity() > 0)
{
if (((bean->getPositionX() - bean->getContentSize().width / 2) >= 200 && cos(m_joystick->getAngle()) < 0)
|| (bean->getPositionX() + bean->getContentSize().width / 2 <= 680 && cos(m_joystick->getAngle()) > 0))
{
bean->setPositionX(bean->getPositionX() + 4 * m_joystick->getVelocity() * cos(m_joystick->getAngle()));
}
if (((bean->getPositionY() + bean->getContentSize().width) <= 667 && sin(m_joystick->getAngle()) > 0)
|| ((bean->getPositionY() - bean->getContentSize().width) >= 0 && sin(m_joystick->getAngle()) < 0))
{
bean->setPositionY(bean->getPositionY() + 4 * m_joystick->getVelocity() * sin(m_joystick->getAngle()));
}
}
這樣,我們就基本實現了手柄對角色的操控(手柄繪製源碼中實現),然後只需實現計分板的功能
public:
void updategrade(int);
//gradeboard init
void gradeboard();
private:
// tag for ball or grade
static const int BALL1_TAG = 110;
static const int BALL2_TAG = 111;
static const int BALL3_TAG = 112;
static const int GRADE_TAG = 113;
int grade = 0; //grade init
string FNT_PATH = "fonts/futura-48.fnt"; // fnt file path
顯然,我們應當有一個計分板初始化的實現,此外,應當實現分數的動態更新。爲了能夠得到指定的node,有必要使用tag來標記跟蹤每種類型的ball以及grade。在創建豆豆時進行setTag(ball_tag)操作,然後就可以通過getTag()判斷出vector中的當前ball的類型,並根據球的類型進行分數的更新。for (auto ball : ballVector)
{
//進行碰撞檢測,更新分數
auto balltype = ball->getTag();
if (bean->getBoundingBox().intersectsRect(ball->getBoundingBox()))
{
auto actionDown = CallFunc::create(CC_CALLBACK_0(HelloWorld::removeBall, this, ball));
ball->runAction(actionDown);
if (balltype==BALL1_TAG)
updategrade(1);
else if(balltype == BALL2_TAG)
updategrade(2);
else if(balltype == BALL3_TAG)
updategrade(3);
else ;
}
}
由於grade已經進行了初始化,這裏就只需將grade加上傳入的增量即可。此外,我們考慮使用LabelBMFont創建計分板,分別初始化設置字體、座標以及tag。此外,由於node不能強制轉換成label,但是能強制轉換成LabelBMFont,因此我考慮並使用了LabelBMFont.create而不是Label::createWithBMFont來創建計分板,從而能夠使用setString實時更新計分板。
// 更新分數
void HelloWorld::updategrade(int increment)
{
grade += increment;
//log("%d", grade);
}
// 計分板初始化
void HelloWorld::gradeboard()
{
auto grades = LabelBMFont::create(StringUtils::format("Grade\n%d", grade),FNT_PATH);
//auto grade = Label::createWithBMFont(FNT_PATH,StringUtils::format("Grade\n%d", grade));
grades->setPosition(Vec2(100, 350));
grades->setTag(GRADE_TAG);
this->addChild(grades, 10);
}
init(){
...
auto grades = (LabelBMFont*)this->getChildByTag(GRADE_TAG);
grades->setString(StringUtils::format("Grade\n%d",grade));
}
到此,我們就完整實現了計分板的功能。運行遊戲如下
計分板功能和遊戲手柄的功能都已經完整實現。