Cocos2d-x 3.6 项目实战---贪吃蛇(4)

前端之家收集整理的这篇文章主要介绍了Cocos2d-x 3.6 项目实战---贪吃蛇(4)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

现在就是最主要也是较为复杂的界面和逻辑类了。

他实际包含两个类,一个SnakeNode蛇结点类和一个Game界面逻辑类。
绘制10*10的网格,初始化一个食物和一个蛇头,随机的坐标,然后定时移动蛇头,碰到食物则吃掉并产生一个身体结点,碰撞检测,到边界就结束返回主界面。
GameScene.h:

#pragma execution_character_set("utf-8")

#ifndef __snakegame__GameScene__
#define __snakegame__GameScene__
#include "cocos2d.h"
USING_NS_CC;
enum class ENUM_DIR{
    DIR_UP,DIR_DOWN,DIR_LEFT,DIR_RIGHT,DIR_STOP
};

class SnakeNode:public Sprite
{
public:
    ENUM_DIR m_dir;     //移动方向
    int nodeType;       //节点类型: 1蛇头 2 身体 3 食物
    int m_row,m_col;    //当前节点的行列坐标
public:
    static SnakeNode* create(int type);//!!!
    virtual bool init(int type);
    void setPositionRC(int row,int col);//设置节点的坐标
};

class Game:public Layer
{
public:
    //enum RESOLUTION{
    // NET_SIZE = 64,
    // NET_WIDTH = 640
    // _WIDTH = 960,
    // _HEIGHT = 640
    //};
    SnakeNode * spFood;//食物
    SnakeNode * spHead;//蛇头
    int m_score;
    Vector<SnakeNode *> allBody;//身体!!!
    static Scene * createScene();
    CREATE_FUNC(Game);
    virtual bool init();
public:
    void menuCallBack(Ref * object);
    void gameLogic(float t);
    void newBody();//添加一个新的身体节点
    void moveBody();//移动所有的身体节点
};
#endif /* defined(__snakegame__GameScene__) */

GameScen.cpp:

#include "GameScene.h"
#include "MainMenu.h"
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
Scene * Game::createScene()
{
    auto scene = Scene::create();
    auto layer = Game::create();
    scene->addChild(layer);
    return scene;

}

SnakeNode* SnakeNode::create(int type)
{
    SnakeNode *pRet = new SnakeNode();
    if (pRet && pRet->init(type))
    {
        pRet->autorelease();
        return pRet;
    }
    else
    {
        delete pRet;
        pRet = NULL;
        return NULL;
    }
}

bool SnakeNode::init(int type)
{
    if (!Sprite::init())
    {
        return false;
    }
    ///根据类型不同初始化不同的纹理
    switch (type) {
        case 1://蛇头
        {
            auto sprite = Sprite::create("redstar.png");
            sprite->setAnchorPoint(Point::ZERO);
            this->addChild(sprite);
            m_dir = ENUM_DIR::DIR_RIGHT;//向右移动
            m_row = 0;//初始化蛇头的位置
            m_col = 0;
        }
        break;
        case 2://身体
        {
            auto sprite = Sprite::create("greenstar.png");
            sprite->setAnchorPoint(Point::ZERO);
            this->addChild(sprite);
        }
        m_dir = ENUM_DIR::DIR_STOP;
        break;
        case 3://食物
        {
            auto sprite = Sprite::create("yellowstar.png");
            sprite->setAnchorPoint(Point::ZERO);
            this->addChild(sprite);
        }
        m_dir = ENUM_DIR::DIR_STOP;
        break;
        default:
        break;
    }
    return true;
}

enum RESOLUTION{
    NET_SIZE = 32,NET_WIDTH = 320
};

void SnakeNode::setPositionRC(int row,int col)//设置节点的坐标
{
    this->m_row = row;
    this->m_col = col;
    setPosition(Point(col * NET_SIZE,row * NET_SIZE));
}

bool  Game::init(){
    if (!Layer::init())
    {
        return  false;
    }
    //添加地图网格
    auto draw = DrawNode::create();
    draw->setAnchorPoint(Point::ZERO);
    draw->setPosition(Point::ZERO);
    this->addChild(draw);
    for (int i = 0; i < 11; i++)
    {
        draw->drawSegment(Point(0,NET_SIZE * i),Point(NET_WIDTH,1,Color4F(1,1));
        draw->drawSegment(Point(NET_SIZE * i,0),Point(NET_SIZE * i,NET_WIDTH),1));
    }
    //添加蛇头
    spHead = SnakeNode::create(1);  
    this->addChild(spHead);

    //添加身体
    //添加食物
    spFood = SnakeNode::create(3);

    //float i = CCRANDOM_0_1()*(end - start + 1) + start;
    int row = rand() % 10;
    int col = rand() % 10;
    spFood->setPositionRC(row,col);
    this->addChild(spFood);
    auto size = Director::getInstance()->getWinSize();
    //添加背景
    auto spriteBK = Sprite::create("menuback.png");
    spriteBK->setPosition(Point(size.width / 2,size.height / 2));
    spriteBK->setOpacity(75);
    this->addChild(spriteBK);
    //分数显示
    m_score = 0;
    auto labelscore = Label::createWithSystemFont("分数: 0","宋体",25);
    //auto labelscore = Label::createWithSystemFont("score: 0","AdobeHeitiStd-Regular",25);
    labelscore->setTag(110);
    labelscore->setPosition(Point(size.width - 80,size.height - 50));
    this->addChild(labelscore);
    //返回按钮
    auto menuItemBack = MenuItemFont::create("Back",CC_CALLBACK_1(Game::menuCallBack,this));
    auto menu = Menu::create(menuItemBack,NULL);
    menu->setPosition(Point::ZERO);
    menuItemBack->setPosition(Point(size.width - menuItemBack->getContentSize().width - 50,menuItemBack->getContentSize().height + 10));
    this->addChild(menu);
    //计划任务
    this->schedule(schedule_selector(Game::gameLogic),0.5f);
    //加入用户触摸事件侦听
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = [&](Touch * t,Event * e){
        //改变贪食蛇移动的方向
        int col = t->getLocation().x / NET_SIZE;
        int row = t->getLocation().y / NET_SIZE;
        int spHeadCol = spHead->getPositionX() / NET_SIZE;
        int spHeadRow = spHead->getPositionY() / NET_SIZE;
        if (abs(spHeadCol - col) > abs(spHeadRow - row))//左右
        {
            if (spHeadCol < col)//点击右方
            {
                spHead->m_dir = ENUM_DIR::DIR_RIGHT;
            }
            else
            {
                spHead->m_dir = ENUM_DIR::DIR_LEFT;
            }
        }
        else//上下
        {
            if (spHeadRow < row)//点击上方
            {
                spHead->m_dir = ENUM_DIR::DIR_UP;
            }
            else
            {
                spHead->m_dir = ENUM_DIR::DIR_DOWN;
            }
        }
        return true;
    };
    _eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,this);
    return true;
}

void  Game::menuCallBack(Ref * object){
    auto scene = MainMenu::createScene();
    Director::getInstance()->replaceScene(scene);
}

void Game::gameLogic(float t)
{
    moveBody();//移动所有身体节点
    //蛇头移动
    switch (spHead->m_dir) {
        case ENUM_DIR::DIR_RIGHT:
        spHead->runAction(MoveBy::create(0.3f,Point(NET_SIZE,0)));
        spHead->m_col++;
        break;
        case ENUM_DIR::DIR_LEFT:
        spHead->runAction(MoveBy::create(0.3f,Point(-NET_SIZE,0)));
        spHead->m_col--;
        break;
        case ENUM_DIR::DIR_DOWN:
        spHead->runAction(MoveBy::create(0.3f,Point(0,-NET_SIZE)));
        spHead->m_row--;
        break;
        case ENUM_DIR::DIR_UP:
        spHead->runAction(MoveBy::create(0.3f,NET_SIZE)));
        spHead->m_row++;
        break;
        default:
        break;
    }
    //add TODO
    if (spHead->m_row < 0 || spHead->m_col < 0 ||
        spHead->m_row > 9 || spHead->m_col > 9)
    {
        auto scene = MainMenu::createScene();
        Director::getInstance()->replaceScene(scene);
    }
    //碰撞检测
    if (spHead->m_row == spFood->m_row&&
        spHead->m_col == spFood->m_col)
    {  //音效的播放
        SimpleAudioEngine::getInstance()->playEffect("eat.wav");
        //分数增加
        this->m_score += 100;
        auto label = (Label *)this->getChildByTag(110);
        char strscore[20];
        sprintf(strscore,"分数: %d",m_score);
        label->setString(strscore);
        //食物产生新的位置
        int row = rand() % 10;//0-9
        int col = rand() % 10;
        spFood->setPositionRC(row,col);
        //添加节点
        newBody();
    }
}

void Game::newBody()//添加一个新的身体节点
{
    auto bodynode = SnakeNode::create(2);
    //设置这个节点的方向和坐标
    if (allBody.size() > 0)//有身体节点
    {   //新节点的方向为最后一个身体的节点
        auto lastbody = allBody.at(allBody.size() - 1);
        bodynode->m_dir = lastbody->m_dir;

        switch (bodynode->m_dir) {
            case ENUM_DIR::DIR_UP:
            bodynode->setPositionRC(lastbody->m_row - 1,lastbody->m_col);
            break;
            case ENUM_DIR::DIR_DOWN:
            bodynode->setPositionRC(lastbody->m_row + 1,lastbody->m_col);
            break;
            case ENUM_DIR::DIR_LEFT:
            bodynode->setPositionRC(lastbody->m_row,lastbody->m_col + 1);
            break;
            case ENUM_DIR::DIR_RIGHT:
            bodynode->setPositionRC(lastbody->m_row,lastbody->m_col - 1);
            break;
            default:
            break;
        }

    }
    else
    { //新节点的方向等于蛇头的方向
        bodynode->m_dir = spHead->m_dir;
        switch (bodynode->m_dir) {
            case ENUM_DIR::DIR_UP:
            bodynode->setPositionRC(spHead->m_row - 1,spHead->m_col);
            break;
            case ENUM_DIR::DIR_DOWN:
            bodynode->setPositionRC(spHead->m_row + 1,spHead->m_col);
            break;
            case ENUM_DIR::DIR_LEFT:
            bodynode->setPositionRC(spHead->m_row,spHead->m_col + 1);
            break;
            case ENUM_DIR::DIR_RIGHT:
            bodynode->setPositionRC(spHead->m_row,spHead->m_col - 1);
            break;
            default:
            break;
        }
    }
    //添加节点到当前图层
    this->addChild(bodynode);
    //添加节点到集合中
    allBody.pushBack(bodynode);
}

void Game::moveBody()//移动所有的身体节点
{
    if (allBody.size() == 0){ return; }
    for (auto bodynode : allBody)
    {
        switch (bodynode->m_dir) {
            case ENUM_DIR::DIR_RIGHT:
            bodynode->runAction(MoveBy::create(0.3f,0)));
            bodynode->m_col++;
            break;
            case ENUM_DIR::DIR_LEFT:
            bodynode->runAction(MoveBy::create(0.3f,0)));
            bodynode->m_col--;
            break;
            case ENUM_DIR::DIR_DOWN:
            bodynode->runAction(MoveBy::create(0.3f,-NET_SIZE)));
            bodynode->m_row--;
            break;
            case ENUM_DIR::DIR_UP:
            bodynode->runAction(MoveBy::create(0.3f,NET_SIZE)));
            bodynode->m_row++;
            break;
            default:
            break;
        }
    }
    //移动完成之后,改变每个body的方向
    for (int i = allBody.size() - 1; i > 0; i--)
    { //每个节点的 方向调整为它前一个节点的方向
        allBody.at(i)->m_dir = allBody.at(i - 1)->m_dir;
    }
    allBody.at(0)->m_dir = spHead->m_dir;
}

源码和资源下载地址:
@L_403_0@

猜你在找的Cocos2d-x相关文章