Cocos2d-x 3.0final 终结者系列教程13-贪食蛇游戏案例(全)

2023-11-08 04:32

本文主要是介绍Cocos2d-x 3.0final 终结者系列教程13-贪食蛇游戏案例(全),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

快过节了,谢谢了屈原,我们爱你。

应该多几个向屈大人一样跳江的,这样我们就可以放假纪念啦。

---------------------------------快过节了,弄个案例,大家不妨假期做做,

运行效果展示:



全部代码和资源:

http://download.csdn.net/detail/sdhjob/7424329

1.准备资源

背景图片menuback.png:


节点图片

greenstar.png   

redstar.png      

yellowstar.png 

2.创建一个新项目(如何配置环境和创建新项目,参考前面教程):

cocos new -p com.xdl.game -l cpp -d ~/Desktop/test0515 snamegame

3.添加文件

首先将HelloWoldScene.h HelloWorld.cpp移走,然后添加GameScene.h GameScene.cpp HelpScene.h HelpScene.cpp MainMenu.h MainMenu.cpp

加上原来自动生成的AppDelegate.h 和AppDelegate.cpp共8个文件

4.编码

AppDelegate.h (这个文件基本没改动)

#ifndef  _APP_DELEGATE_H_

#define  _APP_DELEGATE_H_

#include "cocos2d.h"

class  AppDelegate : private cocos2d::Application

{

public:

    AppDelegate();

    virtual ~AppDelegate();

    virtual bool applicationDidFinishLaunching();

    virtual void applicationDidEnterBackground();

    virtual void applicationWillEnterForeground();

};

#endif // _APP_DELEGATE_H_

AppDelegate.cpp 

#include "AppDelegate.h"

#include "MainMenu.h"

#include "SimpleAudioEngine.h"    

USING_NS_CC;

using namespace CocosDenshion;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate() 

{

}

bool AppDelegate::applicationDidFinishLaunching() {

    // initialize director

    auto director = Director::getInstance();

    auto glview = director->getOpenGLView();

    if(!glview) {

        glview = GLView::create("My Game");

        director->setOpenGLView(glview);

    }

    // turn on display FPS

    director->setDisplayStats(false);

    // set FPS. the default value is 1.0/60 if you don't call this

    director->setAnimationInterval(1.0 / 60);

    // create a scene. it's an autorelease object

    auto scene = MainMenu::createScene();

    // run

    director->runWithScene(scene);

    //开始播放背景音乐

    SimpleAudioEngine::getInstance()->playBackgroundMusic("background.mp3");

    return true;

}


// This function will be called when the app is inactive. When comes a phone call,it's be invoked too

void AppDelegate::applicationDidEnterBackground() {

    Director::getInstance()->stopAnimation();

    // if you use SimpleAudioEngine, it must be pause

    SimpleAudioEngine::getInstance()->pauseBackgroundMusic();

}


// this function will be called when the app is active again

void AppDelegate::applicationWillEnterForeground() {

    Director::getInstance()->startAnimation();

    // if you use SimpleAudioEngine, it must resume here

    SimpleAudioEngine::getInstance()->resumeBackgroundMusic();

}

说明: 在入口类中加入了背景音乐的播放,并且入口场景设计为MainMenu,往下看

MainMenu.h

#ifndef __snakegame__MainMenu__

#define __snakegame__MainMenu__

#include "cocos2d.h"

USING_NS_CC;

class MainMenu:public Layer{

public:

    static Scene * createScene();

    CREATE_FUNC(MainMenu);

    virtual bool init();

    void menuCallBack(Ref * object);

};

#endif


MainMenu.cpp

#include "MainMenu.h"

#include "GameScene.h"

#include "HelpScene.h"

Scene * MainMenu::createScene()

{   auto scene=Scene::create();

    auto layer=MainMenu::create();

    scene->addChild(layer);

    return scene;

}

 bool MainMenu::init(){

     if(!Layer::init())

    {

    return false;

    }

     auto size=Director::getInstance()->getWinSize();

     //添加背景

     auto spriteBK=Sprite::create("menuback.png");

     spriteBK->setPosition(Point(size.width/2,size.height/2));

     this->addChild(spriteBK);

     //添加2个菜单条目

     auto menuItemStart=MenuItemFont::create("Start", CC_CALLBACK_1(MainMenu::menuCallBack,this));

     menuItemStart->setTag(1);

     auto menuItemHelp=MenuItemFont::create("Help", CC_CALLBACK_1(MainMenu::menuCallBack,this));

     menuItemHelp->setTag(2);

     auto menu=Menu::create(menuItemStart,menuItemHelp,NULL);

     menu->setPosition(Point::ZERO);

     menuItemStart->setPosition(Point(size.width-menuItemStart->getContentSize().width-100,menuItemStart->getContentSize().height+10));

     menuItemHelp->setPosition(Point(size.width-menuItemHelp->getContentSize().width-10,menuItemHelp->getContentSize().height+10));

     this->addChild(menu);

     return true;

}

void MainMenu::menuCallBack(Ref * object){

    auto target=(Node *)object;

    Scene * scene;

    switch (target->getTag()) {

        case 1://startgame

            scene=Game::createScene();

            break;

        case 2://Helpgame

            scene=Help::createScene();

            break;

        default:

            break;

    }

    Director::getInstance()->replaceScene(scene);

  }

说明:在菜单场景中实现了跳转到帮助场景和游戏场景,往下看:

HelpScene.h

#ifndef __snakegame__HelpScene__

#define __snakegame__HelpScene__

#include "cocos2d.h"

USING_NS_CC;

class Help:public Layer{

public:

    static Scene * createScene();

    CREATE_FUNC(Help);

    virtual bool init();

    void menuCallBack(Ref * object);

};

#endif

HelpScene.cpp

#include "HelpScene.h"

#include "MainMenu.h"

Scene * Help::createScene(){

    auto scene=Scene::create();

    auto layer=Help::create();

    scene->addChild(layer);

    return scene;

   }

bool  Help::init(){

    if(!Layer::init())

        {

        return  false;

        }

      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);

    //帮助信息

    auto labelScore=Label::create("帮助信息", "宋体", 25);

    labelScore->setPosition(Point(size.width-80,size.height-50));

    this->addChild(labelScore);

    //返回按钮

    auto menuItemBack=MenuItemFont::create("Back", CC_CALLBACK_1(Help::menuCallBack,this));

    auto menu=Menu::create(menuItemBack,NULL);

    menu->setPosition(Point::ZERO);

    menuItemBack->setPosition(Point(size.width-menuItemBack->getContentSize().width-100,menuItemBack->getContentSize().height+10));

    this->addChild(menu);

    return true;

}

void  Help::menuCallBack(Ref * object){

    auto scene=MainMenu::createScene();

    Director::getInstance()->replaceScene(scene);

}

说明:这里只是实现了一个帮助信息显示,可以返回到菜单,下面看游戏场景

GameScene.h

#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 ENUM_DIR m_dir;//移动方向

    int nodeType;       //节点类型1蛇头 2 身体 3 食物

    int m_row,m_col;    //当前节点的行列坐标

   

    static SnakeNode* create(int type);

    virtual bool init(int type);

    void setPositionRC(int row,int col);//设置节点的坐标

};

class Game:public Layer{

public:

    SnakeNode * spFood;//食物

    SnakeNode * spHead;//蛇头

     int m_score;

    Vector<SnakeNode *> allBody;//身体

    static Scene * createScene();

    CREATE_FUNC(Game);

    virtual bool init();

    void menuCallBack(Ref * object);

    void gameLogic(float t);

    void newBody();//添加一个新的身体节点

    void moveBody();//移动所有的身体节点

};

#endif

GameScene.cpp

//

//  GameScene.cpp

//  Created by shen on 14-5-27.

//


#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;//向右移动

        }

            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;

}

void SnakeNode::setPositionRC(int row,int col)//设置节点的坐标

{    this->m_row=row;

     this->m_col=col;

      setPosition(Point(col*32,row*32));

}

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,32*i), Point(320,32*i), 1, Color4F(1,1,1,1));

    draw->drawSegment(Point(32*i,0), Point(32*i,320), 1, Color4F(1,1,1,1));

    }

    //添加蛇头

    spHead=SnakeNode::create(1);

    

    

    this->addChild(spHead);

    //添加身体

    //添加食物

     spFood=SnakeNode::create(3);

 

    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::create("分数:0", "宋体", 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.5);

    //加入用户触摸事件侦听

    auto listener=EventListenerTouchOneByOne::create();

    listener->setSwallowTouches(true);

    listener->onTouchBegan=[&](Touch * t,Event * e){

        //改变贪食蛇移动的方向

        int col=t->getLocation().x/32;

        int row=t->getLocation().y/32;

        int spHeadCol=spHead->getPositionX()/32;

        int spHeadRow=spHead->getPositionY()/32;

        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.3, Point(32,0)));

            spHead->m_col++;

            break;

        case ENUM_DIR::DIR_LEFT:

            spHead->runAction(MoveBy::create(0.3, Point(-32,0)));

            spHead->m_col--;

            break;

        case ENUM_DIR::DIR_DOWN:

            spHead->runAction(MoveBy::create(0.3, Point(0,-32)));

            spHead->m_row--;

            break;

        case ENUM_DIR::DIR_UP:

            spHead->runAction(MoveBy::create(0.3, Point(0,32)));

            spHead->m_row++;

            break;

   

        default:

            break;

    }

    //碰撞检测

    if(spHead->m_row==spFood->m_row&&

       spHead->m_col==spFood->m_col)

    {  //音效的播放

        SimpleAudioEngine::getInstance()->playEffect("eat.wav");

        //分数增加

        this->m_score+=100;

        Label * label=(Label *)this->getChildByTag(110);

        char strscore[20];

        sprintf(strscore, "分数:%d",m_score);

        label->setString(strscore);

      //食物产生新的位置

        int row=rand()%10;

        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.3, Point(32,0)));

            bodynode->m_col++;

            break;

        case ENUM_DIR::DIR_LEFT:

            bodynode->runAction(MoveBy::create(0.3, Point(-32,0)));

            bodynode->m_col--;

            break;

        case ENUM_DIR::DIR_DOWN:

            bodynode->runAction(MoveBy::create(0.3, Point(0,-32)));

            bodynode->m_row--;

            break;

        case ENUM_DIR::DIR_UP:

            bodynode->runAction(MoveBy::create(0.3, Point(0,32)));

            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;

}

--------------------------------------------祝你成功-----------------------

这篇关于Cocos2d-x 3.0final 终结者系列教程13-贪食蛇游戏案例(全)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/367884

相关文章

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

python连接本地SQL server详细图文教程

《python连接本地SQLserver详细图文教程》在数据分析领域,经常需要从数据库中获取数据进行分析和处理,下面:本文主要介绍python连接本地SQLserver的相关资料,文中通过代码... 目录一.设置本地账号1.新建用户2.开启双重验证3,开启TCP/IP本地服务二js.python连接实例1.

Python 安装和配置flask, flask_cors的图文教程

《Python安装和配置flask,flask_cors的图文教程》:本文主要介绍Python安装和配置flask,flask_cors的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,... 目录一.python安装:二,配置环境变量,三:检查Python安装和环境变量,四:安装flask和flas

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa