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

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

4B参数秒杀GPT-3.5:MiniCPM 3.0惊艳登场!

​ 面壁智能 在 AI 的世界里,总有那么几个时刻让人惊叹不已。面壁智能推出的 MiniCPM 3.0,这个仅有4B参数的"小钢炮",正在以惊人的实力挑战着 GPT-3.5 这个曾经的AI巨人。 MiniCPM 3.0 MiniCPM 3.0 MiniCPM 3.0 目前的主要功能有: 长上下文功能:原生支持 32k 上下文长度,性能完美。我们引入了

客户案例:安全海外中继助力知名家电企业化解海外通邮困境

1、客户背景 广东格兰仕集团有限公司(以下简称“格兰仕”),成立于1978年,是中国家电行业的领军企业之一。作为全球最大的微波炉生产基地,格兰仕拥有多项国际领先的家电制造技术,连续多年位列中国家电出口前列。格兰仕不仅注重业务的全球拓展,更重视业务流程的高效与顺畅,以确保在国际舞台上的竞争力。 2、需求痛点 随着格兰仕全球化战略的深入实施,其海外业务快速增长,电子邮件成为了关键的沟通工具。