zoukankan      html  css  js  c++  java
  • cocos2d_x_06_游戏_一个都不能死

    终于效果图:


    环境版本号:cocos2d-x-3.3beta0 使用内置的物理引擎


    游戏主场景
    //
    //  HeroScene.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    #ifndef __HeroScene_SCENE_H__
    #define __HeroScene_SCENE_H__
    
    #include "cocos2d.h"
    #include "GameCtrl.h"
    // 继承自 有颜色的Layer
    class HeroScene : public cocos2d::LayerColor
    {
    private:
        // 屏幕尺寸
        Size winSize;
        // 数组 不同的层 相应不同的控制器
        cocos2d::Vector<GameCtrl*> gameCtrlArr;
        
    public:
        // 宏定义的Create方法,内部会调用init方法
        CREATE_FUNC(HeroScene);
        // 供外界调用的 实例化场景的方法
        static cocos2d::Scene* createScene();
        // 初始化方法
        virtual bool init();
        // 时钟方法
        // 在场景的时钟方法中,更新控制  每个游戏控制器的时钟方法
        virtual void update(float dt);
    };
    
    #endif // __HeroScene_SCENE_H__
    


    //
    //  HeroScene.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    #include "HeroScene.h"
    #include "GameOverScene.h"
    
    USING_NS_CC;
    #pragma mark - 生命周期方法
    Scene* HeroScene::createScene()
    {
        // 使用cocos2d 内置的物理引擎
        auto scene = Scene::createWithPhysics();
        // 显示 调试用的 刚体 边线
    //    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
        // 调整重力加速度
        scene->getPhysicsWorld()->setGravity(Vec2(0, -1000));
        // 标准代码 通过静态的create方法创建Layer,加入�到场景,并返回场景
        auto layer = HeroScene::create();
        scene->addChild(layer);
        return scene;
    }
    // 实例化特有的对象
    bool HeroScene::init()
    {
        // 创建一个白色的Layer
        if ( !LayerColor::initWithColor(Color4B(255, 255, 255, 255)) ) return false;
        // 屏幕尺寸
        winSize = Director::getInstance()->getVisibleSize();
        log("winSize:%f,%f",winSize.width,winSize.height);
        
        // 创建2个 GameCtrl (2层)
        gameCtrlArr.insert(0, GameCtrl::create(this, 30));
        if(rand()%2 == 0){
            gameCtrlArr.insert(0, GameCtrl::create(this, 250));
        }
        
        // 开启消息调度
        scheduleUpdate();
        // ********************************************
        // 物理碰撞检測 「PhysicsContact」
        auto listener = EventListenerPhysicsContact::create();
        // 開始碰撞 游戏结束
        listener->onContactBegin = [this](PhysicsContact & contact){
            // 取消 消息调度
            this->unscheduleUpdate();
            // 切换至Game Over场景
            Director::getInstance()->replaceScene(GameOverScene::createScene());
            return true;
        };
        // 向事件分发器,注冊listener
        Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
        // ********************************************
        // 用户单点触摸 jump high 【TouchOneByOne】
        auto touchListener = EventListenerTouchOneByOne::create();
        // 開始触摸 原地 跳一下
        touchListener->onTouchBegan = [this](Touch * t,Event * e){
            // 每个游戏控制器 都运行一下 方法
            for (auto it = gameCtrlArr.begin(); it!=gameCtrlArr.end(); it++)
            {
                // 解引用 就能够获得数组成员对象了
                // 假设 是点在自己的那一层 才运行 跳高动作
                if ((*it)->hitTestPoint(t->getLocation()))
                {
                    (*it)->onUserTouch();
                    break;
                }
            }
            return false;
        };
        // 向事件分发器,注冊listener
        Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);
        return true;
    }
    
    #pragma mark - 时钟方法
    void HeroScene::update(float dt)
    {
        // 在场景的时钟方法中,更新控制  每个游戏控制器的时钟方法
        for (auto it = gameCtrlArr.begin(); it!=gameCtrlArr.end(); it++)
        {
            // 解引用 就能够获得数组成员对象了
            // 每个游戏控制器 开启时钟方法
            (*it)->startUpdate(dt);
        }
        
    }
    
    


    游戏结束时的场景
    //
    //  GameOverScene.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #include <cocos2d.h>
    #include "MainScene.h"
    using namespace cocos2d;
    // 继承自 有颜色的Layer
    class GameOverScene:public LayerColor {
        
    private:
        Size winSize;
        
    public:
        // 供外界调用
        static Scene* createScene()
        {
            auto s = Scene::create();
            auto l = GameOverScene::create();
            s->addChild(l);
            return s;
        };
        
        // 宏定义的Create方法,内部会调用init方法
        CREATE_FUNC(GameOverScene);
        
        // 初始化,自己用
        virtual bool init()
        {
            // 父类的init方法
            LayerColor::initWithColor(Color4B::WHITE);
            // 屏幕大小
            winSize = Director::getInstance()->getVisibleSize();
            // 创建一个Label
            auto label = Label::create();
            label->setString("Game Over");
            label->setSystemFontSize(40);
            label->setName("label");
            label->setColor(Color3B::BLACK);
            label->setPosition(winSize.width/2, winSize.height/2);
            // 加入�到Layer
            addChild(label);
    
            
            // 加入�一个事件,点击 Label,返回到主场景的事件
            // 2.触摸Label,开启 时钟updatePosition
            // 实例化一个触摸监听器 对象
            auto listener = EventListenerTouchOneByOne::create();
            // 当触摸開始时,绑定一个闭包函数;
            // 【】表示 要传入的外界对象,此处是this
            // ()表示參数
            listener->onTouchBegan = [this](Touch *t,Event *e){
                // 假设 点击 了label,才每隔一秒运行一次 更新位置方法
                Label *label =(Label *) e->getCurrentTarget()->getChildByName("label");
                if (label->getBoundingBox().containsPoint(t->getLocation())) {
                    // 回到主场景
                    // 创建场景,自己主动释放 it's an autorelease object
                    auto scene = MainScene::createScene();
                    // 替换场景
                    Director::getInstance()->replaceScene(scene);
                }
                return false;
            };
            // 5、获取事件分发器,加入�一个事件监听器,到this身上;即监听的是this对象【整个图层Layer】
            Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
            return true;
        };
        
        
    };


    一个游戏控制器实例 相应一层子游戏核心
    //
    //  GameCtrl.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #ifndef ___1_cocos2d_x__GameCtrl__
    #define ___1_cocos2d_x__GameCtrl__
    #include <cocos2d.h>
    // 全屏的边框
    #include "Boundary.h"
    
    #include "Hero.h"
    #include "Block.h"
    USING_NS_CC;
    // 继承自 Ref,就自己主动拥有了 释放机制
    class GameCtrl:public Ref
    {
    private:
        // 屏幕尺寸
        Size winSize;
        // 边界 边框,用成员变量记住,是由于 碰撞检測要用到
        Boundary * boundary;
        Hero * hero;
        
        // 重要~~~Layer就相当于HeroScene场景,由于全部的子精灵 全加入�到Layer中,所以须要传入Layer
        // 成员变量记住(其它方法中要用到)
        Layer * _layer;
        float _positionY;
        
        // 暂时变量,用于累计 记录 流逝的时间
        int tempTimeDelta;
        // 总共的时间间隔 (即 时间delta累计到 该间隔时,创建并加入�一个障碍物)
        int totalIntervalTime;
    
        
    private:
        // 每加入�一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
        void resetTempTimeDelta();
        // 每隔 随机的时间,创建并加入�一个障碍物
        void addBlock();
        
    public:
        // 重要~~~这个Layer就相当于HeroScene场景,由于全部的子精灵 全加入�到Layer中,所以须要传入Layer
        // 參数 就是在屏幕的y值
        // 供外界
        static GameCtrl* create(Layer *layer,float positionY);
        // 自己初始化
        virtual bool init(Layer * layer,float positionY);
        // 供场景调用,让场景来 开启和关闭 游戏控制器 中的 时钟方法
        void startUpdate(float dt);
        
    
        // 当被用户触摸了 时侯调用,给英雄一个向上的速度
        void onUserTouch();
        bool hitTestPoint(Vec2 point);
    
        
        
    };
    
    #endif /* defined(___1_cocos2d_x__GameCtrl__) */
    


    //
    //  GameCtrl.cpp
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #include "GameCtrl.h"
    // 重要~~~这个Layer就相当于HeroScene场景,由于全部的子精灵 全加入�到Layer中,所以须要传入Layer
    // 參数 就是在屏幕的y值
    // 供外界
    GameCtrl* GameCtrl::create(cocos2d::Layer *layer, float positionY)
    {
        auto gameCtrl = new GameCtrl();
        // 调用自己的init初始化,将參数 传递过去
        gameCtrl->init(layer, positionY);
        // 自己主动释放
        gameCtrl->autorelease();
        return gameCtrl;
    }
    // 自己初始化
    bool GameCtrl::init(cocos2d::Layer *layer, float positionY)
    {
        // 成员变量记住,其它方法中 要用到
        _layer = layer;
        _positionY = positionY;
        // 全屏
        winSize = Director::getInstance()->getVisibleSize();
        //**************************************
        // 1、加入�游戏的边框、边界
        boundary = Boundary::create();
        // 居中 (注意 不同的控制器,可能在不同的层 其y值不同 高度也不同)
        boundary->setPosition(winSize.width/2, winSize.height/2+positionY);
    
        // 全屏
        boundary->setContentSize(winSize);
        // 加入�到Layer
        layer->addChild(boundary);
        //**************************************
        // 2、加入�地板 (不须要关联物理世界)
        auto ground = Sprite::create();
        ground->setColor(Color3B(0, 0, 0));
        ground->setTextureRect(Rect(0, 0, winSize.width, 3));
        //  (注意 不同的控制器,可能在不同的层 其y值不同)  3 和1.5
        ground->setPosition(winSize.width/2,1.5+positionY);
        // 加入�到Layer
        layer->addChild(ground);
        //**************************************
        // 3、加入�Hero
        hero = Hero::create();
        //  (注意 不同的控制器,可能在不同的层 其y值不同)
        hero->setPosition(50, hero->getContentSize().height/2+positionY);
        // 加入�到Layer
        layer->addChild(hero);
        
        // 每加入�一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
        resetTempTimeDelta();
        return true;
    }
    
    #pragma mark - 供外界场景调用
    // 供场景调用,让场景来 开启和关闭 游戏控制器 中的 时钟方法
    void GameCtrl::startUpdate(float dt)
    {
        // 暂时变量,用于累计 记录 流逝的时间
        tempTimeDelta++;
        // 总共的时间间隔 (即 时间delta累计到 该间隔时,创建并加入�一个障碍物)
        if (tempTimeDelta >= totalIntervalTime)
        {
            // 每加入�一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
            resetTempTimeDelta();
            // 每隔 随机的时间,创建并加入�一个障碍物  
            addBlock();
        }
    }
    // 每加入�一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
    void GameCtrl::resetTempTimeDelta()
    {
        tempTimeDelta = 0;
        totalIntervalTime = (rand()%120) + 100;
    }
    
    // 创建 并 加入� 障碍物  (在随机的 时间 间隔 之后 )
    void GameCtrl::addBlock()
    {
        auto b = Block::create();
        _layer->addChild(b);
        // 注意 障碍物的y值是 和当前游戏控制器 自己的y值 同样的
        // 即 block的半高 + 当前控制器自己的y
        b->setPositionY(b->getContentSize().height/2 + _positionY);
    }
    
    
    #pragma mark - 触摸事件
    // 当被用户触摸了 时侯调用,给英雄一个向上的速度
    void GameCtrl::onUserTouch()
    {
        hero->getPhysicsBody()->setVelocity(Vec2(0, 400));
    }
    
    bool GameCtrl::hitTestPoint(cocos2d::Vec2 point)
    {
        return boundary->getBoundingBox().containsPoint(point);
    }
    


    边框、边界
    //
    //  Boundary.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //  边框、边界,其大小和winSize一样
    
    #ifndef __Boundary__
    #define __Boundary__
    
    
    
    #include <cocos2d.h>
    
    USING_NS_CC;
    
    class Boundary:public Node {
    public:
        // 宏定义 一个静态的create方法,内部会调用init方法
        CREATE_FUNC(Boundary);
        // 初始化方法
        virtual bool init();
    };
    
    #endif /* defined(__Boundary__) */
    


    //
    //  Boundary.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //  边框、边界,其大小和winSize一样
    
    #include "Boundary.h"
    
    
    bool Boundary::init(){
        // 父类的init方法,内部 直接返回一个true
        Node::init();
        
        // 960 * 640
        Size winSize = Director::getInstance()->getVisibleSize();
        // 设置Node大小 全屏
        setContentSize(winSize);
        
        // 设置物理刚体body,大小和winSize一样
        setPhysicsBody(PhysicsBody::createEdgeBox(winSize));
    
        return true;
    }


    Hero主角
    //
    //  Hero.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //  主角,继承自Sprite,奔跑的小人
    
    #ifndef ___1_cocos2d_x__Hero__
    #define ___1_cocos2d_x__Hero__
    
    #include <cocos2d.h>
    
    USING_NS_CC;
    
    class Hero:public Sprite {
        
    public:
        // 宏,静态的create方法,内部会调用init方法
        CREATE_FUNC(Hero);
        virtual bool init();
    
    };
    
    
    #endif /* defined(___1_cocos2d_x__Hero__) */
    


    //
    //  Hero.cpp
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //  主角,继承自Sprite,奔跑的小人
    
    #include "Hero.h"
    
    #include "FlashTool.h"
    
    
    bool Hero::init()
    {
        // 父类的init方法
        Sprite::init();
        // 运行 帧动画 一直奔跑 RepeatForever
        runAction(RepeatForever::create(FlashTool::animateFromJsonFile("Hero.json", 0.2f)));
    
        // Json中的尺寸
        Size s = Size(44, 52);
        // 精灵的大小
        setContentSize(s);
        
        // 设置物理世界的刚体body
        setPhysicsBody(PhysicsBody::createBox(s));
        // 刚体不同意 旋转
        getPhysicsBody()->setRotationEnable(false);
        // 重要~~~若想參与 碰撞,必须绑定一个碰撞标识
        getPhysicsBody()->setContactTestBitmask(1);
        
        return true;
    }


    障碍物
    //
    //  Block.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #ifndef ___1_cocos2d_x__Block__
    #define ___1_cocos2d_x__Block__
    
    #include <cocos2d.h>
    
    USING_NS_CC;
    
    class Block:public Sprite {
    public:
        // 宏,静态的create方法,内部会调用init方法
        CREATE_FUNC(Block);
        virtual bool init();
        // 时钟方法,内部会 让 障碍物不断地向左移动
        virtual void update(float dt);
    
    };
    
    #endif /* defined(___1_cocos2d_x__Block__) */
    


    //
    //  Block.cpp
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #include "Block.h"
    
    bool Block::init()
    {
        // 父类的init方法
        Sprite::init();
        // 屏幕大小
        Size winSize = Director::getInstance()->getVisibleSize();
        // 放在屏幕的外边
        setPositionX(winSize.width);
        // 黑色 障碍物
        setColor(Color3B(0, 0, 0));
    
        Size size = Size((rand()%20)+5, (rand()%30)+10);
        // 随机生成 不同大小的 障碍物
        setContentSize(size);
        // 黑色的方块区域
        setTextureRect(Rect(0, 0, size.width, size.height));
        // ***************************************
        // 设置 物理刚体
        setPhysicsBody(PhysicsBody::createBox(size));
        // 不是动态的刚体 即:是静态的刚体
        getPhysicsBody()->setDynamic(false);
        // 重要~~~若想參与 碰撞,必须绑定一个碰撞标识
        getPhysicsBody()->setContactTestBitmask(1);
        // ***************************************
        // 开启时钟方法
        scheduleUpdate();
        return true;
    }
    #pragma mark - 时钟方法
    // 时钟方法,内部会 让 障碍物不断地向左移动
    void Block::update(float dt){
        
        this->setPositionX(getPositionX()-8);
        // 移动到屏幕外边时,就停止消息调度,而且移除
        if (getPositionX()<0)
        {
            unscheduleUpdate();
            removeFromParent();
        }
        
    }


    通过解析flash cc导出的Json文件+大图片,

    生成一个Animate对象,用于运行序列帧动画


    //
    //  FlashTool.h
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #ifndef ___1_cocos2d_x__FlashTool__
    #define ___1_cocos2d_x__FlashTool__
    
    #include <cocos2d.h>
    
    USING_NS_CC;
    
    class FlashTool {
        
    public:
        // 通过解析flash cc 导出的Json文件+大图片,生成一个Animate对象,用于运行序列帧动画
        static Animate * animateFromJsonFile(std::string jsonFile,float delayPerUnit);
    };
    
    #endif /* defined(___1_cocos2d_x__FlashTool__) */
    


    //
    //  FlashTool.cpp
    //  01_cocos2d-x
    //
    //  Created by beyond on 14-10-6.
    //
    //
    
    #include "FlashTool.h"
    // Json解析 使用cocos2d 内置的rapidJson库
    #include <json/document.h>
    
    // 通过解析flash cc 导出的Json文件+大图片,生成一个Animate对象,用于运行序列帧动画
    Animate * FlashTool::animateFromJsonFile(std::string jsonFile,float delayPerUnit)
    {
        // 文档 对象
        rapidjson::Document doc;
        // FileUtils工具类 读入json文件
        std::string fileContent = FileUtils::getInstance()->getStringFromFile(jsonFile);
        // 
        fileContent.erase(0,fileContent.find_first_of('{'));
        // 标记默觉得 0 ,開始解析
        doc.Parse<0>(fileContent.c_str());
        // 得到大图片的 图片名
        std::string imgFileName = doc["meta"]["image"].GetString();
        
        auto &frames = doc["frames"];
        // 精灵帧缓存
        auto sfc = SpriteFrameCache::getInstance();
        // 容器用于 存放全部的 动画帧
        Vector<AnimationFrame*> animFrames;
        // 遍历,裁剪,创建,加入�到容器
        for (auto m=frames.MemberonBegin(); m!=frames.MemberonEnd(); m++) {
            auto frameName = m->name.GetString();
            auto & frameProperties = m->value["frame"];
            auto & spriteSourceSize = m->value["spriteSourceSize"];
            
            auto sf = sfc->getSpriteFrameByName(frameName);
            if (!sf) {
                sf = SpriteFrame::create(imgFileName, Rect(frameProperties["x"].GetInt(), frameProperties["y"].GetInt(), frameProperties["w"].GetInt(), frameProperties["h"].GetInt()), m->value["rotated"].GetBool(), Vec2(spriteSourceSize["x"].GetInt(), spriteSourceSize["y"].GetInt()), Size(spriteSourceSize["w"].GetInt(), spriteSourceSize["h"].GetInt()));
                sfc->addSpriteFrame(sf, frameName);
            }
            animFrames.pushBack(AnimationFrame::create(sf, delayPerUnit, ValueMapNull));
        }
        // 生成用于Action的Animate
        Animation * animation = Animation::create(animFrames,delayPerUnit);
        return Animate::create(animation);
    }


    flash cc 导出的Json文件+大图片


    {"frames": {
    
    "hero0000":
    {
    	"frame": {"x":0,"y":0,"w":44,"h":52},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":44,"h":52},
    	"sourceSize": {"w":44,"h":52}
    },
    "hero0001":
    {
    	"frame": {"x":44,"y":0,"w":42,"h":52},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":2,"y":0,"w":44,"h":52},
    	"sourceSize": {"w":44,"h":52}
    },
    "hero0002":
    {
    	"frame": {"x":86,"y":0,"w":42,"h":52},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":2,"y":0,"w":44,"h":52},
    	"sourceSize": {"w":44,"h":52}
    },
    "hero0003":
    {
    	"frame": {"x":0,"y":52,"w":42,"h":52},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":2,"y":0,"w":44,"h":52},
    	"sourceSize": {"w":44,"h":52}
    },
    "hero0004":
    {
    	"frame": {"x":42,"y":52,"w":42,"h":52},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":2,"y":0,"w":44,"h":52},
    	"sourceSize": {"w":44,"h":52}
    }},
    "meta": {
    	"app": "Adobe Flash Professional",
    	"version": "13.1.0.226",
    	"image": "Hero.png",
    	"format": "RGBA8888",
    	"size": {"w":128,"h":128},
    	"scale": "1"
    }
    }
    







  • 相关阅读:
    android:id="@android:id/tabhost" 、android:id="@+id/llRoot" 、android:id="@id/llRoot" 之间的区别
    android:ellipsize的使用
    PopupWindow为什么要设置setBackgroundDrawable(new BitmapDrawable());
    android中LayoutInflater的3种使用以及getSystemService的API
    context 的理解
    Android 中this、getContext()、getApplicationContext()、getApplication()、getBaseContext() 之间的区别
    android Matrix 使用
    public private protected frientdly 作用域
    pyinstaller参数介绍以及总结
    MongoDB高级查询详细
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4092142.html
Copyright © 2011-2022 走看看