cocos2d-x 拼图实现demo

最近公司要在一个项目里接入一个拼玩法,下面我简单做了一个demo

###1. 碎片的实现
这里派生一个Piece类来实现

####Piece.h

#ifndef Piece_hpp
#define Piece_hpp

#include <stdio.h>
#include "cocos2d.h"
#define  DELTA 50

typedef enum
{
    GROUP_NULL = 0,
    GROUP_1    = 1,
    GROUP_2    = 2,
    GROUP_3    = 3,
}Type;


using namespace cocos2d;
class Piece : public Sprite
{
public:

public:
    Piece();
    ~Piece();
    static Piece* create(const std::string &filename);
    virtual bool init(const std::string &filename);

public:
    /*点击到碎片*/
    void setActived(bool bActive);
    bool getActived();

    /*碎片是否和其他组合*/
    void setIsInGroup(bool bGroup);
    bool getIsInGroup();

    /*设置目标位置*/
    void setTargetPoistion(Vec2 targetPosition);
    Vec2 getTargetPosition();

    /*一定误差范围内移动到正确位置*/
    void moveToTargetPosition();
    /*碎片是否已经移动到正确的位置*/
    void setIsMovedSuccessed(bool success);
    bool getIsMovedSuccessed();

    /*本次触摸事件完成*/
    void setIsEnded(bool end);
    bool getIsEnded();
    /*加入的组合*/
    void setType(Type type);
    Type getType();
private:
    bool m_bActived;
    bool m_bSuccessed;
    bool m_bGroup;
    bool m_bEnded;
    Vec2 m_targetPosition;

    Type m_nType;
};
#endif /* Piece_hpp */

####Piece.cpp

//
//  Piece.cpp
//  Puzzle-mobile

#include "Piece.hpp"
Piece::Piece() : m_targetPosition(Vec2(0,0)),m_bGroup(false),m_bSuccessed(false),m_bEnded(false)
{

}
Piece::~Piece()
{
    m_targetPosition = Vec2(0,0);
}
Piece *Piece::create(const std::string &filename)
{
    Piece *piece = new Piece();
    if (piece && piece->init(filename))
    {
        piece->autorelease();
    }
    else
    {
        delete piece;
        return nullptr;
    }
    return piece;
}
bool Piece::init(const std::string &filename)
{
    if (!Sprite::init())
    {
        return false;
    }
    this->initWithFile(filename);
    return true;
}
void Piece::setIsEnded(bool end)
{
    this->m_bEnded = end;
}
bool Piece::getIsEnded()
{
    return this->m_bEnded;
}
void Piece::setTargetPoistion(cocos2d::Vec2 targetPosition)
{
    m_targetPosition = targetPosition;
}
Vec2 Piece::getTargetPosition()
{
    return this->m_targetPosition;
}
void Piece::setActived(bool bActive)
{
    this->m_bActived = bActive;
}
bool Piece::getActived()
{
    return this->m_bActived;
}
void Piece::setIsInGroup(bool bGroup)
{
    this->m_bGroup = bGroup;
}
bool Piece::getIsInGroup()
{
    return this->m_bGroup;
}
void Piece::setIsMovedSuccessed(bool success)
{
    m_bSuccessed = success;
}
bool Piece::getIsMovedSuccessed()
{
    return m_bSuccessed;
}
void Piece::moveToTargetPosition()
{
    this->runAction(MoveTo::create(0.2f, m_targetPosition));
    this->setIsMovedSuccessed(true);
}
void Piece::setType(Type type)
{
    this->m_nType = type;
}
Type Piece::getType()
{
    return this->m_nType;
}


####PuzzleScene.h

//
//  PuzzleScene.hpp
//  Puzzle-mobile


#ifndef PuzzleScene_hpp
#define PuzzleScene_hpp

#include <stdio.h>
#include "cocos2d.h"
#include "Piece.hpp"
USING_NS_CC;

using namespace std;
class PuzzleScene :  public Layer
{
public:
    PuzzleScene();
    ~PuzzleScene();

    static Scene *scene();

    bool init();


    virtual void setTouchListener();
    virtual bool onTouchBegan(Touch *touch,Event *unused_event);
    virtual void onTouchMoved(Touch *touch,Event *unused_event);
    virtual void onTouchEnded(Touch *touch,Event *unused_event);

    CREATE_FUNC(PuzzleScene);

public:
    void checkPiecePosition(Vec2 pt);

    bool checkPiecePositionRelativePiece(int i, int j);//没有组合时碎片的相对位置
    bool checkPiecePositionRelativeGroup(int i, int j);//检测碎片相对于组合的位置
    bool checkGroupPositionRelativePiece(int i, vector<Piece *> vec);//检测组合相对位置

    void checkFinalPosition();
private:
    map<Type,vector<Piece *>> m_mapPiece;
    vector<Piece *> m_vecPiece;
    vector<Vec2> m_positionVec;
    Sprite *m_background;
};
#endif /* PuzzleScene_hpp */

####PuzzleScene.cpp

//
//  PuzzleScene.cpp
//  Puzzle-mobile

#include "PuzzleScene.hpp"

PuzzleScene::PuzzleScene()
{

}
PuzzleScene::~PuzzleScene()
{

}
Scene *PuzzleScene::scene()
{
    Scene *scene = Scene::create();
    PuzzleScene *pLayer = PuzzleScene::create();
    scene->addChild(pLayer);
    return scene;
}


bool PuzzleScene::init()
{
    if (!Layer::init())
    {
        return false;
    }

    LayerColor *layer = LayerColor::create(Color4B(255,255,255,255));
    this->addChild(layer,0);
    this->m_background = Sprite::create("puzzle/background.png");
    this->m_background->setPosition(Vec2(this->getContentSize().width/2,this->getContentSize().height/2));
    this->addChild(m_background,1);

    Vec2 positionPieceTopLeft     = Vec2(m_background->getPositionX()- m_background->getContentSize().width/4,
                                         m_background->getPositionY()+ m_background->getContentSize().height/4);

    Vec2 positionPieceTopRight    = Vec2(m_background->getPositionX()+ m_background->getContentSize().width/4,
                                         m_background->getPositionY()+ m_background->getContentSize().height/4);

    Vec2 positionPieceBottomLeft  = Vec2(m_background->getPositionX()- m_background->getContentSize().width/4,
                                         m_background->getPositionY()- m_background->getContentSize().height/4);

    Vec2 positionPieceBottomRight = Vec2(m_background->getPositionX()+ m_background->getContentSize().width/4,
                                         m_background->getPositionY()- m_background->getContentSize().height/4);
    m_positionVec.push_back(positionPieceTopLeft);
    m_positionVec.push_back(positionPieceTopRight);
    m_positionVec.push_back(positionPieceBottomLeft);
    m_positionVec.push_back(positionPieceBottomRight);

    for (int i = 0; i < 4; i++)
    {
        Piece *piece = Piece::create("puzzle/piece_0" + to_string(i) + ".png");
        piece->setTargetPoistion(m_positionVec[i]);
        piece->setPosition(Vec2(piece->getContentSize().width,this->getContentSize().height - piece->getContentSize().height * i - 50));
        this->m_vecPiece.push_back(piece);
        this->addChild(piece,2);
    }
    setTouchListener();
    return true;
}

void PuzzleScene::setTouchListener()
{
    EventListenerTouchOneByOne *listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(PuzzleScene::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(PuzzleScene::onTouchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(PuzzleScene::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}

bool PuzzleScene::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
    for (int i = 0; i < m_vecPiece.size(); i++)
    {
        if (m_vecPiece.at(i)->getBoundingBox().containsPoint(touch->getLocation()) && !m_vecPiece.at(i)->getIsMovedSuccessed())
        {
            m_vecPiece.at(i)->setActived(true);
        }
    }


    return true;
}
void PuzzleScene::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
    Vec2 delta = touch->getDelta();
    for (int i = 0; i < m_vecPiece.size(); i++)
    {
        if (m_vecPiece.at(i)->getActived() && !m_vecPiece.at(i)->getIsMovedSuccessed())
        {
            if (!m_vecPiece.at(i)->getIsInGroup())
            {
                m_vecPiece.at(i)->setPosition(m_vecPiece.at(i)->getPosition() + delta);
                return;
            }
            else
            {
                map<Type, vector<Piece *>>::iterator itor = m_mapPiece.find(m_vecPiece.at(i)->getType());
                if (itor != m_mapPiece.end())
                {
                    vector<Piece *> vec = itor->second;
                    for (int j = 0; j < vec.size(); j++)
                    {
                        vec.at(j)->setPosition(vec.at(j)->getPosition() + delta);
                    }
                }
            }
        }
    }
}
void PuzzleScene::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{

    checkPiecePosition(touch->getLocation());

    checkFinalPosition();
    for (int i = 0; i < m_vecPiece.size(); i++)
    {
        m_vecPiece.at(i)->setIsEnded(false);
        m_vecPiece.at(i)->setActived(false);
    }
}

void PuzzleScene::checkPiecePosition(cocos2d::Vec2 pt)
{
    for (int i = 0; i < m_vecPiece.size(); i++)
    {
        if (m_vecPiece.at(i)->getActived() && !m_vecPiece.at(i)->getIsMovedSuccessed())
        {
            //位置发生变化的碎片没有和其他碎片组合时
            if (!m_vecPiece.at(i)->getIsInGroup())
            {
                bool bBreak = false;
                for (int j = 0; j < m_vecPiece.size(); j++)
                {
                    if (i != j)
                    {
                        if (!m_vecPiece.at(j)->getIsInGroup() && !m_vecPiece.at(j)->getIsMovedSuccessed())
                        {
                            bBreak = checkPiecePositionRelativePiece(i, j);
                        }
                        else if(m_vecPiece.at(j)->getIsInGroup() && !m_vecPiece.at(j)->getIsMovedSuccessed())
                        {
                            bBreak = checkPiecePositionRelativeGroup(i, j);
                        }
                        if (bBreak)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                //位置发生变化的碎片与其他碎片组合
                map<Type,vector<Piece *>>::iterator itor = m_mapPiece.find(m_vecPiece.at(i)->getType());
                if (itor != m_mapPiece.end())
                {
                    vector<Piece *> vec = itor->second;
                    if (checkGroupPositionRelativePiece(i, vec))
                    {
                        break;
                    }
                }
            }
        }
    }
}

bool PuzzleScene::checkPiecePositionRelativePiece(int i, int j)
{
    bool bBreak = false;
    if (!m_vecPiece.at(i)->getIsMovedSuccessed() && !m_vecPiece.at(j)->getIsMovedSuccessed())
    {
        Vec2 loc_i = m_vecPiece.at(i)->getPosition();
        Vec2 loc_j = m_vecPiece.at(j)->getPosition();
        int dis = loc_i.distance(loc_j);
        int lim = m_vecPiece.at(i)->getTargetPosition().distance(m_vecPiece.at(j)->getTargetPosition());
        if (dis < lim)
        {
            if (m_vecPiece.at(i)->getTargetPosition().x == m_vecPiece.at(j)->getTargetPosition().x)
            {
                if (m_vecPiece.at(i)->getTargetPosition().y > m_vecPiece.at(j)->getTargetPosition().y)
                {
                    m_vecPiece.at(j)->runAction(MoveTo::create(0.2f, Vec2(loc_i.x,loc_i.y - lim)));
                }
                else
                {
                    m_vecPiece.at(j)->runAction(MoveTo::create(0.2f, Vec2(loc_i.x,loc_i.y + lim)));
                }

                long count = m_mapPiece.size();
                m_vecPiece.at(i)->setIsInGroup(true);
                m_vecPiece.at(i)->setType((Type)(count + 1));
                m_vecPiece.at(j)->setIsInGroup(true);
                m_vecPiece.at(j)->setType((Type)(count + 1));

                vector<Piece *> vec;
                vec.push_back(m_vecPiece.at(i));
                vec.push_back(m_vecPiece.at(j));
                
                m_mapPiece.insert(map<Type, vector<Piece *>>::value_type(m_vecPiece.at(i)->getType(),vec));


                bBreak = true;

            }
            else if (m_vecPiece.at(i)->getTargetPosition().y == m_vecPiece.at(j)->getTargetPosition().y)
            {
                if (m_vecPiece.at(i)->getTargetPosition().x > m_vecPiece.at(j)->getTargetPosition().x)
                {
                    m_vecPiece.at(j)->runAction(MoveTo::create(0.2f, Vec2(loc_i.x - lim,loc_i.y)));
                }
                else
                {
                    m_vecPiece.at(j)->runAction(MoveTo::create(0.2f, Vec2(loc_i.x + lim,loc_i.y)));
                }
                long count = m_mapPiece.size();
                m_vecPiece.at(i)->setIsInGroup(true);
                m_vecPiece.at(i)->setType((Type)(count + 1));
                m_vecPiece.at(j)->setIsInGroup(true);
                m_vecPiece.at(j)->setType((Type)(count + 1));

                vector<Piece *> vec;
                vec.push_back(m_vecPiece.at(i));
                vec.push_back(m_vecPiece.at(j));

                m_mapPiece.insert(map<Type, vector<Piece *>>::value_type(m_vecPiece.at(i)->getType(),vec));

                bBreak = true;
            }
        }
    }
    return bBreak;
}

bool PuzzleScene::checkPiecePositionRelativeGroup(int i, int j)
{
    bool bBreak = false;
    int dis = m_vecPiece.at(i)->getPosition().distance(m_vecPiece.at(j)->getPosition());
    int lim = m_vecPiece.at(i)->getTargetPosition().distance(m_vecPiece.at(j)->getTargetPosition());
    if (dis < lim)
    {
        Vec2 delta = Vec2(0,0);
        Vec2 loc_i = m_vecPiece.at(i)->getPosition();
        Vec2 loc_j = m_vecPiece.at(j)->getPosition();
        if (m_vecPiece.at(i)->getTargetPosition().x == m_vecPiece.at(j)->getTargetPosition().x)
        {
            if (m_vecPiece.at(i)->getTargetPosition().y > m_vecPiece.at(j)->getTargetPosition().y)
            {
                delta = Vec2(loc_i.x,loc_i.y - lim) - loc_j;
            }
            else
            {
                delta = Vec2(loc_i.x,loc_i.y + lim) - loc_j;
            }

            map<Type, vector<Piece *>>::iterator itor = m_mapPiece.find(m_vecPiece.at(j)->getType());
            vector<Piece *> vec;
            if (itor != m_mapPiece.end())
            {
                vec = itor->second;
                for (int k = 0; k < vec.size(); k++)
                {
                    Vec2 loc = vec.at(k)->getPosition();
                    vec.at(k)->runAction(MoveTo::create(0.2f, Vec2(loc.x + delta.x,loc.y + delta.y)));
                }
                m_vecPiece.at(i)->setIsInGroup(true);
                m_vecPiece.at(i)->setType(m_vecPiece.at(j)->getType());
                vec.push_back(m_vecPiece.at(i));

                m_mapPiece.erase(m_vecPiece.at(j)->getType());
                m_mapPiece.insert(map<Type, vector<Piece *>>::value_type(m_vecPiece.at(i)->getType(),vec));
            }

            bBreak = true;
        }
        else if (m_vecPiece.at(i)->getTargetPosition().y == m_vecPiece.at(j)->getTargetPosition().y)
        {

            if (m_vecPiece.at(i)->getTargetPosition().x > m_vecPiece.at(j)->getTargetPosition().x)
            {
                delta = Vec2(loc_i.x - lim,loc_i.y) - loc_j;
            }
            else
            {
                delta = Vec2(loc_i.x + lim,loc_i.y) - loc_j;
            }

            map<Type, vector<Piece *>>::iterator itor = m_mapPiece.find(m_vecPiece.at(j)->getType());
            vector<Piece *> vec;
            if (itor != m_mapPiece.end())
            {
                vec = itor->second;
                for (int k = 0; k < vec.size(); k++)
                {
                    Vec2 loc = vec.at(k)->getPosition();
                    vec.at(k)->runAction(MoveTo::create(0.2f, loc + delta));
                }
                m_vecPiece.at(i)->setIsInGroup(true);
                m_vecPiece.at(i)->setType(m_vecPiece.at(j)->getType());
                vec.push_back(m_vecPiece.at(i));

                m_mapPiece.erase(m_vecPiece.at(j)->getType());
                m_mapPiece.insert(map<Type, vector<Piece *>>::value_type(m_vecPiece.at(i)->getType(),vec));
            }

            bBreak = true;
        }
    }
    return bBreak;
}
bool PuzzleScene::checkGroupPositionRelativePiece(int i, vector<Piece *> vec)
{
    bool bBreak = false;
    Type nType = m_vecPiece.at(i)->getType();
    for (int k = 0; k < m_vecPiece.size();k++)
    {
        Piece *piece = m_vecPiece.at(k);
        if (nType != piece->getType() && !piece->getIsMovedSuccessed())
        {
            if (!piece->getIsInGroup())
            {
                for (int m = 0; m < vec.size(); m++)
                {

                    Piece *pie = vec.at(m);
                    int dis = piece->getPosition().distance(pie->getPosition());
                    int lim = piece->getTargetPosition().distance(pie->getTargetPosition());
                    if (dis < lim)
                    {
                        bBreak = true;
                        if (pie->getTargetPosition().x == piece->getTargetPosition().x)
                        {
                            if (pie->getTargetPosition().y < piece->getTargetPosition().y)
                            {
                                piece->runAction(MoveTo::create(0.2f, Vec2(pie->getPosition().x,pie->getPosition().y + lim)));
                                piece->setType(pie->getType());
                                piece->setIsInGroup(true);
                                vec.push_back(piece);
                                m_mapPiece.erase(pie->getType());
                                m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(pie->getType(),vec));
                                return bBreak;
                            }
                            else
                            {
                                piece->runAction(MoveTo::create(0.2f, Vec2(pie->getPosition().x,pie->getPosition().y - lim)));
                                piece->setType(pie->getType());
                                piece->setIsInGroup(true);
                                vec.push_back(piece);
                                m_mapPiece.erase(pie->getType());
                                m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(pie->getType(),vec));
                                return bBreak;
                            }
                        }
                        if (pie->getTargetPosition().y == piece->getTargetPosition().y)
                        {
                            if (pie->getTargetPosition().x < piece->getTargetPosition().x)
                            {
                                piece->runAction(MoveTo::create(0.2f, Vec2(pie->getPosition().x + lim,pie->getPosition().y)));
                                piece->setType(pie->getType());
                                piece->setIsInGroup(true);
                                vec.push_back(piece);
                                m_mapPiece.erase(pie->getType());
                                m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(pie->getType(),vec));
                                return bBreak;
                            }
                            else
                            {
                                piece->runAction(MoveTo::create(0.2f, Vec2(pie->getPosition().x - lim,pie->getPosition().y)));
                                piece->setType(pie->getType());
                                piece->setIsInGroup(true);
                                vec.push_back(piece);
                                m_mapPiece.erase(pie->getType());
                                m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(pie->getType(),vec));
                                return bBreak;
                            }
                        }
                    }
                }
            }
            else
            {
                map<Type, vector<Piece *>>::iterator itor = m_mapPiece.find(piece->getType());
                vector<Piece *> vec2;
                if (itor != m_mapPiece.end())
                {
                    vec2 = itor->second;
                }
                for (int k = 0; k < vec.size(); k++)
                {
                    for (int m = 0; m < vec2.size(); m++)
                    {
                        Piece *vecPie = vec.at(k);
                        Piece *vec2Pie = vec2.at(m);
                        int dis = vecPie->getPosition().distance(vec2Pie->getPosition());
                        int lim = vecPie->getTargetPosition().distance(vec2Pie->getTargetPosition());

                        if (dis < lim)
                        {
                            Vec2 delta;
                            bBreak = true;

                            if (vecPie->getTargetPosition().x == vec2Pie->getTargetPosition().x)
                            {
                                if (vecPie->getTargetPosition().y < vec2Pie->getTargetPosition().y)
                                {
                                    delta = Vec2(vecPie->getPosition().x,vecPie->getPosition().y + lim) - vec2Pie->getPosition();
                                    for (int n = 0; n < vec2.size(); n++)
                                    {
                                        vec2.at(n)->runAction(MoveTo::create(0.2f,vec2.at(n)->getPosition() + delta));
                                        vec2.at(n)->setType(vecPie->getType());
                                        vec.push_back(vec2.at(n));
                                    }
                                    m_mapPiece.erase(vecPie->getType());
                                    m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(vecPie->getType(),vec));
                                    return bBreak;
                                }
                                else
                                {
                                    delta = Vec2(vecPie->getPosition().x,vecPie->getPosition().y - lim) - vec2Pie->getPosition();
                                    for (int n = 0; n < vec2.size(); n++)
                                    {
                                        vec2.at(n)->runAction(MoveTo::create(0.2f,vec2.at(n)->getPosition() + delta));
                                        vec2.at(n)->setType(vecPie->getType());
                                        vec.push_back(vec2.at(n));
                                    }
                                    m_mapPiece.erase(vecPie->getType());
                                    m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(vecPie->getType(),vec));
                                    return bBreak;
                                }
                            }
                            if (vecPie->getTargetPosition().y == vec2Pie->getTargetPosition().y)
                            {
                                if (vecPie->getTargetPosition().x < vec2Pie->getTargetPosition().x)
                                {
                                    delta = Vec2(vecPie->getPosition().x + lim,vecPie->getPosition().y) - vec2Pie->getPosition();
                                    for (int n = 0; n < vec2.size(); n++)
                                    {
                                        vec2.at(n)->runAction(MoveTo::create(0.2f,vec2.at(n)->getPosition() + delta));
                                        vec2.at(n)->setType(vecPie->getType());
                                        vec.push_back(vec2.at(n));
                                    }
                                    m_mapPiece.erase(vecPie->getType());
                                    m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(vecPie->getType(),vec));
                                    return bBreak;
                                }
                                else
                                {
                                    delta = Vec2(vecPie->getPosition().x - lim,vecPie->getPosition().y) - vec2Pie->getPosition();
                                    for (int n = 0; n < vec2.size(); n++)
                                    {
                                        vec2.at(n)->runAction(MoveTo::create(0.2f,vec2.at(n)->getPosition() + delta));
                                        vec2.at(n)->setType(vecPie->getType());
                                        vec.push_back(vec2.at(n));
                                    }
                                    m_mapPiece.erase(vecPie->getType());
                                    m_mapPiece.insert(map<Type,vector<Piece *>>::value_type(vecPie->getType(),vec));
                                    return bBreak;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return bBreak;
}
void PuzzleScene::checkFinalPosition()
{
    for (int i = 0; i < m_vecPiece.size(); i++)
    {
        if (m_vecPiece.at(i)->getPosition().distance(m_vecPiece.at(i)->getTargetPosition()) < DELTA)
        {
            m_vecPiece.at(i)->moveToTargetPosition();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值