cocos2d-x 3.2 |如何实现一个贪吃蛇游戏

cocos2d-x 3.2 |如何实现一个贪吃蛇游戏
前情提要:今天我们来实现一个简单版的贪吃蛇游戏,利用这些经典的游戏上手cocos2d最好不过了。
忽略:本章忽略菜单、按钮、跳转、帮助等功能、主要实现贪吃蛇逻辑与效果

第一步:新建Game类,定义贪吃蛇主要功能与方法 Game.h如下:
#include 
#include "cocos2d.h"
USING_NS_CC;
using namespace ui;
//枚举定义蛇运动方向
enum class SNAKE_DIR
{
    DIR_UP,
    DIR_LEFT,
    DIR_RIGHT,
    DIR_DOWN
};
class SNode:public Node
{
public:
    LayerColor * sprite;//纹理
    int px,py;//坐标
    SNAKE_DIR dir;//方向
    CREATE_FUNC(SNode);
    bool init();//初始化
    void setColor(Color3B color);//颜色
    void moveTo(int x,int y);//位移到
};

class GameScene:public Layer
{
public:
    SNode * snakeHead;//蛇头
    SNode *food;//食物
    Vector allBody;//身体
    int mapx;
    int mapy;
    
    CREATE_FUNC(GameScene);
    bool init();
    static Scene * createScene();
    void gameLogc(float t);//逻辑
    virtual bool onTouchBegan(Touch *touch, Event *unused_event);//触摸
};
第二步:实现Game类的方法 Game.cpp如下:
#include "Game.h"

Scene * GameScene::createScene(){
    auto scene=Scene::create();
    auto layer=GameScene::create();
    scene->addChild(layer);
    return scene;
}
bool GameScene::init(){
    if(!Layer::init())
    {
        return false;
    }
    //绘制游戏背景
    auto bk=LayerColor::create(Color4B(149, 149, 149, 180));
    this->addChild(bk);

    
    //绘制游戏地图
    auto map=DrawNode::create();
    map->setTag(100);
    for (int i=0; i<=20; i++)
    {
        //绘制十1条横线
        map->drawSegment(Vec2(0,i*30),Vec2(600,i*30),0.5,Color4F::GRAY);
        map->drawSegment(Vec2(i*30,0),Vec2(i*30,600),0.5,Color4F::GRAY);
    }
    //map->setAnchorPoint(Vec2(0.5,0.5));
    map->setPosition(Vec2(280,20));

    this->addChild(map);
    //绘制蛇头
    this->snakeHead=SNode::create();
    this->snakeHead->setColor(Color3B::MAGENTA);
    map->addChild(snakeHead);
    int row=0;
    int col=0;
    row=rand()%10;
    col=rand()%10;
    this->snakeHead->moveTo(col*30, row*30);
    snakeHead->dir=SNAKE_DIR::DIR_DOWN;
    //绘制食物
    this->food=SNode::create();
    this->food->setColor(Color3B::YELLOW);
    map->addChild(food);
    mapx=map->getPositionX();
    mapy=map->getPositionY();
    row=rand()%20;
    col=rand()%20;
    this->food->moveTo(col*30, row*30);
    //让蛇头运动
    this->schedule(schedule_selector(GameScene::gameLogc), 0.2);
    //改变舌头方向
    auto listener=EventListenerTouchOneByOne::create();
    listener->onTouchBegan=CC_CALLBACK_2(GameScene::onTouchBegan, this);
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this);
    return true;
}

//根据按下位置,判断舌头移动方向
bool  GameScene::onTouchBegan(Touch *touch, Event *unused_event){
    int w=abs(touch->getLocation().x-mapx-snakeHead->px);
    int h=abs(touch->getLocation().y-mapy-snakeHead->py);
    if(w>h)//左右移动
    {
        if(touch->getLocation().x-mapx>snakeHead->px)//右
        {
            snakeHead->dir=SNAKE_DIR::DIR_RIGHT;
        }else
        {
            snakeHead->dir=SNAKE_DIR::DIR_LEFT;
        }
    }else
    {
        if(touch->getLocation().y-mapy>snakeHead->py)//上
        {
            snakeHead->dir=SNAKE_DIR::DIR_UP;
        }else
        {
            snakeHead->dir=SNAKE_DIR::DIR_DOWN;
        }
    }
    return true;
}
//根据舌头移动方向,位移距离
void GameScene::gameLogc(float t){
    //移动蛇头
    switch (snakeHead->dir) {
        case SNAKE_DIR::DIR_DOWN:
            snakeHead->moveTo(snakeHead->px, snakeHead->py-30);
            break;
        case SNAKE_DIR::DIR_UP:
            snakeHead->moveTo(snakeHead->px, snakeHead->py+30);
            break;
        case SNAKE_DIR::DIR_LEFT:
            snakeHead->moveTo(snakeHead->px-30, snakeHead->py);
            break;
        case SNAKE_DIR::DIR_RIGHT:
            snakeHead->moveTo(snakeHead->px+30, snakeHead->py);
            break;
    }
    //移动身体
    for(int i=allBody.size()-1;i>=0;i--)
    {
        SNode * nowbody=allBody.at(i);
        switch (nowbody->dir) {
            case SNAKE_DIR::DIR_DOWN:
                nowbody->moveTo(nowbody->px, nowbody->py-30);
                break;
            case SNAKE_DIR::DIR_UP:
                nowbody->moveTo(nowbody->px, nowbody->py+30);
                break;
            case SNAKE_DIR::DIR_LEFT:
                nowbody->moveTo(nowbody->px-30, nowbody->py);
                break;
            case SNAKE_DIR::DIR_RIGHT:
                nowbody->moveTo(nowbody->px+30, nowbody->py);
                break;
        }
        
        if (i==0) {
            allBody.at(0)->dir=snakeHead->dir;
        }else
        {
            nowbody->dir=allBody.at(i-1)->dir;//等于上一个方向
        }
    }
    
    //碰撞判断
    if (snakeHead->px==food->px&&snakeHead->py==food->py)
    {
        int row=rand()%20;
        int col=rand()%20;
        this->food->moveTo(col*30, row*30);
        SNode * newBody=SNode::create();
        newBody->setColor(Color3B::BLUE);
        //新的身体在蛇的尾部
        if (allBody.size()==0)
        {
            switch (snakeHead->dir)
            {
                case SNAKE_DIR::DIR_DOWN:
                    newBody->moveTo(snakeHead->px, snakeHead->py+30);
                    break;
                case SNAKE_DIR::DIR_UP:
                    newBody->moveTo(snakeHead->px, snakeHead->py-30);
                    break;
                case SNAKE_DIR::DIR_LEFT:
                    newBody->moveTo(snakeHead->px+30, snakeHead->py);
                    break;
                case SNAKE_DIR::DIR_RIGHT:
                    newBody->moveTo(snakeHead->px-30, snakeHead->py);
                    break;
            }
            allBody.pushBack(newBody);
            newBody->dir=snakeHead->dir;
        }
        else
        {
            SNode * lastBody=allBody.at(allBody.size()-1);
            switch (lastBody->dir) {
                case SNAKE_DIR::DIR_DOWN:
                    newBody->moveTo(lastBody->px, lastBody->py+30);
                    break;
                case SNAKE_DIR::DIR_UP:
                    newBody->moveTo(lastBody->px, lastBody->py-30);
                    break;
                case SNAKE_DIR::DIR_LEFT:
                    newBody->moveTo(lastBody->px+30, lastBody->py);
                    break;
                case SNAKE_DIR::DIR_RIGHT:
                    newBody->moveTo(lastBody->px-30, lastBody->py);
                    break;
            }
            allBody.pushBack(newBody);
            newBody->dir=lastBody->dir;
        }
        this->getChildByTag(100)->addChild(newBody);
    }
}
bool SNode::init(){
    if(!Node::init())
    {
        return false;
    }
    this->sprite=LayerColor::create(Color4B::RED);
    this->sprite->setContentSize(Size(30,30));
    this->addChild(sprite);
    return true;
}
void SNode::setColor(Color3B color){
    this->sprite->setColor(color);
}
void SNode::moveTo(int x,int y){
    this->px=x;
    this->py=y;
    this->sprite->setPosition(Vec2(x,y));
}

总结:文中利用DrawNode绘制方格背景,利用schedule移动蛇头。



你可能感兴趣的:(cocos2d-x)