Cocos2d-x 《雷電大戰》-精靈隨手指移動,你點哪我走哪!

    本文要實現飛機遊戲中,人的手指按着飛機,就能拖着飛機走動,這裏實現了當你手指按在手機的圖片上,手指一直按着屏幕,飛機就會跟着你走。同時,還加入了邊界判斷條件,讓飛機在你的視野內移動,實現的效果完全和我們手機上的飛機遊戲一樣。

效果:

wKiom1T8QyfjnzlgABqxNLHvPJQ526.gif

Cocos2d-x版本:3.4

工程環境:VS30213

一、代碼編寫

1、頭文件GameMain.h

/**
*@作者 林炳文(郵箱:[email protected])
*@博客 http://linbingwen.blog.51cto.com/
*@時間 2015.3.8
*@功能 遊戲的主界面
*/
#ifndef __GameMain_H__
#define __GameMain_H__
#include "BackLayerDown.h"
#include "BackLayerUp.h"
#include "cocos2d.h"
USING_NS_CC;
class GameMain : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    
    virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even);
   
    CREATE_FUNC(GameMain);
private:
    bool isHeroPlaneControl;//飛機是否被控制着
    float mDeltaX;//英雄飛機隨手指移動時的X偏移量
    float mDeltaY;//英雄飛機隨手指移動時的Y偏移量
    Sprite *mHeroPlane;//英雄飛機
};

#endif // __GameMain_H__
#include "GameMain.h"
USING_NS_CC;
Scene* GameMain::createScene()
{
    auto scene = Scene::create();
    auto layer = GameMain::create();
    scene->addChild(layer);
    return scene;
}

bool GameMain::init()
{
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    //這是地面圖層
    this->addChild(BackLayerUp::create());
    //這是白雲圖層
    this->addChild(BackLayerDown::create());

    //加個飛機
    mHeroPlane = Sprite::create("air1.png");
    mHeroPlane->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 5));
    this->addChild(mHeroPlane, 1, 100);
    isHeroPlaneControl = false;

    //打開觸摸,增加觸摸監聽事件
    this->setTouchEnabled(true);
    auto listen = EventListenerTouchOneByOne::create();
    listen->onTouchBegan = CC_CALLBACK_2( GameMain::onTouchBegan,this);
    listen->onTouchMoved = CC_CALLBACK_2(GameMain::onTouchMoved, this);
    listen->onTouchEnded = CC_CALLBACK_2(GameMain::onTouchEened, this);
    listen->onTouchCancelled = CC_CALLBACK_2(GameMain::onTouchCancelled, this);
    listen->setSwallowTouches(false);
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);

    return true;
}
bool  GameMain::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    
    Point mHeroPos = mHeroPlane->getPosition();
    Point mBeganPos = touch->getLocationInView();
    mBeganPos = Director::getInstance()->convertToGL(mBeganPos);

    //判斷當前手指按下區域是否是英雄飛機的區域,並且計算飛機要移動時的偏移量
    if (mBeganPos.x > mHeroPos.x - mHeroPlane->getContentSize().width / 2 && mBeganPos.x<mHeroPos.x + mHeroPlane->getContentSize().width / 2 &&
        mBeganPos.y>mHeroPos.y - mHeroPlane->getContentSize().height / 2 && mBeganPos.y < mHeroPos.y + mHeroPlane->getContentSize().height / 2){
        isHeroPlaneControl = true;
        //計算偏移量
        mDeltaX = mBeganPos.x - mHeroPos.x;
        mDeltaY = mBeganPos.y - mHeroPos.y;

    }

    return true;
}
void  GameMain::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    if (isHeroPlaneControl){
        Point mMovedPos = touch->getLocationInView();
        mMovedPos = Director::getInstance()->convertToGL(mMovedPos);

        Size visibleSize = Director::getInstance()->getVisibleSize();
        Point origin = Director::getInstance()->getVisibleOrigin();
        float x = mMovedPos.x - mDeltaX;//記得減去偏移量
        float y = mMovedPos.y - mDeltaY;
    
        if (x <= mHeroPlane->getContentSize().width / 2 + origin.x)//x到達屏幕左邊界
            x = mHeroPlane->getContentSize().width / 2 + origin.x;
        else if (x >= visibleSize.width - mHeroPlane->getContentSize().width / 2)//x到達屏幕右邊界
            x = visibleSize.width - mHeroPlane->getContentSize().width / 2;

        if (y <= mHeroPlane->getContentSize().height / 2 + origin.y)//y到達屏幕下邊界
            y = mHeroPlane->getContentSize().height / 2 + origin.y;
        else if (y >= visibleSize.height - mHeroPlane->getContentSize().height / 2)//x到達屏幕上邊界
            y = visibleSize.height - mHeroPlane->getContentSize().height/ 2;

        //飛機跟隨手指移動
        mHeroPlane->setPosition(Vec2(x,y));
    }
}
void  GameMain::onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    isHeroPlaneControl = false;
}
void  GameMain::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even){
    isHeroPlaneControl = false;
}

這裏再說一寫主要函數:

頭文件增加觸摸事件:

virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event);
    virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even);

實現文件開啓觸摸事件監聽:

//打開觸摸,增加觸摸監聽事件
    this->setTouchEnabled(true);
    auto listen = EventListenerTouchOneByOne::create();
    listen->onTouchBegan = CC_CALLBACK_2( GameMain::onTouchBegan,this);
    listen->onTouchMoved = CC_CALLBACK_2(GameMain::onTouchMoved, this);
    listen->onTouchEnded = CC_CALLBACK_2(GameMain::onTouchEened, this);
    listen->onTouchCancelled = CC_CALLBACK_2(GameMain::onTouchCancelled, this);
    listen->setSwallowTouches(false);
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);

然後就是觸摸事件 的處理了:

bool  GameMain::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    
    Point mHeroPos = mHeroPlane->getPosition();
    Point mBeganPos = touch->getLocationInView();
    mBeganPos = Director::getInstance()->convertToGL(mBeganPos);

    //判斷當前手指按下區域是否是英雄飛機的區域,並且計算飛機要移動時的偏移量
    if (mBeganPos.x > mHeroPos.x - mHeroPlane->getContentSize().width / 2 && mBeganPos.x<mHeroPos.x + mHeroPlane->getContentSize().width / 2 &&
        mBeganPos.y>mHeroPos.y - mHeroPlane->getContentSize().height / 2 && mBeganPos.y < mHeroPos.y + mHeroPlane->getContentSize().height / 2){
        isHeroPlaneControl = true;
        //計算偏移量
        mDeltaX = mBeganPos.x - mHeroPos.x;
        mDeltaY = mBeganPos.y - mHeroPos.y;

    }

    return true;
}
void  GameMain::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    if (isHeroPlaneControl){
        Point mMovedPos = touch->getLocationInView();
        mMovedPos = Director::getInstance()->convertToGL(mMovedPos);

        Size visibleSize = Director::getInstance()->getVisibleSize();
        Point origin = Director::getInstance()->getVisibleOrigin();
        float x = mMovedPos.x - mDeltaX;//記得減去偏移量
        float y = mMovedPos.y - mDeltaY;
    
        if (x <= mHeroPlane->getContentSize().width / 2 + origin.x)//x到達屏幕左邊界
            x = mHeroPlane->getContentSize().width / 2 + origin.x;
        else if (x >= visibleSize.width - mHeroPlane->getContentSize().width / 2)//x到達屏幕右邊界
            x = visibleSize.width - mHeroPlane->getContentSize().width / 2;

        if (y <= mHeroPlane->getContentSize().height / 2 + origin.y)//y到達屏幕下邊界
            y = mHeroPlane->getContentSize().height / 2 + origin.y;
        else if (y >= visibleSize.height - mHeroPlane->getContentSize().height / 2)//x到達屏幕上邊界
            y = visibleSize.height - mHeroPlane->getContentSize().height/ 2;

        //飛機跟隨手指移動
        mHeroPlane->setPosition(Vec2(x,y));
    }
}
void  GameMain::onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event){
    isHeroPlaneControl = false;
}
void  GameMain::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even){
    isHeroPlaneControl = false;
}

   方法很簡單,代碼量也很少,有需要的把上面的自己拿過去,把圖片改改,把類名改改就可以了。

   其實這裏應該把英雄和移動事件單獨寫一個類,然後在GameMain裏頭來調用,因爲英雄這個類我還構思好,所以先這樣寫,後頭會把英雄飛機單獨提取出來成爲一個類,就不會在GameMain裏頭寫這麼多了;

效果:

wKiom1T8QyfjnzlgABqxNLHvPJQ526.gif

wKioL1T8REXTT8-WAA275rBxn4o876.gif

wKiom1T8Qy3jgfhpABuBZi5igXk095.gif



效果很好,飛機能跟隨移動並且不會跑出屏幕範圍

二、思路說明

1、首先在onTouchBegan判斷觸摸點是否在英雄飛機的圖片矩形內,若在這個範圍內,剛將布爾型的mHeroPlaneControl設置爲true,並且計算觸摸點的橫縱座標與英雄飛機的錨點座標的差值。

2、因爲要讓英雄飛機移動,要修改錨點位置,必須知道錨點位置與觸摸位置的偏移量,之後纔可以通過這個偏移量設置主角的位置。

3、判斷英雄飛機是否跑出屏幕範圍了,如果是,就將它設置在邊界處,詳看上面的兩個if判斷。

4、在onTouchMoved中,若mHeroPlaneControl爲true,說明可以移動英雄飛機。

  

                若你覺得此文對你有用,那就幫我贊一下~~謝謝啦


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章