zoukankan      html  css  js  c++  java
  • 「cocos2dx」垂直射击游戏之宇智波鼬 VS 九尾狐(1)

    本来打算分多个模块实现的,后来想想看cocos2d一个多月,还是先学会走路,等走稳了再学跑步。

    游戏的主要内容是:

    1. 显示Logo画面,并模拟了一个资源加载的进度条;
    2. “资源加载”完成后会进行场景切换,切换到主场景;
    3. 主场景的下方有宇智波鼬, 上方是几只九尾狐,宇智波鼬通过发射手里剑攻击敌人。

    代码结构如下:

    LoadingScene是Logo显示及“资源加载”场景

    GameScene是游戏的主场景,主要实现了背景的无限滚动

    InputLayer是用户输入层,玩家通过虚拟摇杆控制游戏,但这次的游戏逻辑也实现在了这里,这次没加入碰撞检测,可以看到手里剑和敌人擦肩进过,下次加入新功能后会重构代码结构。

    游戏效果如下:

    http://www.56.com/u49/v_OTE4NTUxNDI.html

    代码下载地址:

    http://vdisk.weibo.com/s/Cjiy3/1369105760

    LoadingScene的代码可以参考我以前写的关于进度条的文章,GameScene可参考背景的无限滚动。主要贴一下InputLayer的代码:

    InputLayer.h

    #include "cocos2d.h"
    
    typedef enum
    {
        HudLayerTag = 2,
        GameLayerTag =1,
        
    }GameLayersTags;
    
    using namespace cocos2d;
    
    class InputLayer : public cocos2d::CCLayer
    {
    public:
        InputLayer();                //构造函数声明
        ~InputLayer();                //析构函数声明
        CREATE_FUNC(InputLayer);    //类似于cocos2d中的node方法,返回一个autorelease对象
        virtual bool init();        //本类对象初始化
        void InitJoystick();        //初始化摇杆
        void InitHero();            //初始化主角精灵
        //void InitBullet();        //初始化子弹
        void InitFox();                //初始化敌人-9尾狐
        void update(float dt);        //定时器
        void Shootupdate(float dt);        //发射子弹定时器
        //主角精灵发射子弹
        void shootBulletFromHero(CCSprite *bullet, cocos2d::CCPoint point);
        void menuCloseCallback(CCObject* pSender);    //退出游戏按钮
    
    
        //触摸事件处理
        virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
        virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
        virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
    
        float heronsformula(float x1, float y1, float x2, float y2, float x3, float y3);  
        bool triangleContainPoint(float x1, float y1, float x2, float y2, float x3, float y3, float px, float py);  
    
        void setPlayerPosition(cocos2d::CCPoint position);        //设置玩家位置
    
        CC_SYNTHESIZE(cocos2d::CCSprite*, _player, Player);
        
        //CC_SYNTHESIZE();
    private:
        void Moving(float dt);
        cocos2d::CCSprite *joystick;
        cocos2d::CCSprite *joystick1;
        cocos2d::CCSize size;
        //cocos2d::CCSpriteBatchNode *_spritebatchnode;
        cocos2d::CCPoint velocity;
        cocos2d::CCSprite *bullet;
        cocos2d::CCPoint O;        //中心点O  
        float R;                //大圆半径  
        
        //精灵移动的速度分量值  
        float speedX;  
        float speedY;  
    
        //是否移动的标志  
        bool IsMoving;  
        
        CCMotionStreak* _strike;        //主角精灵的CCMotionStreak变量
        CCMotionStreak* _bulletstrike;    //手里剑的CCMotionStreak变量
    };


    InputLayer.cpp:

    #include "InputLayer.h"
    
    InputLayer::InputLayer()
    {
        //初始化需要的变量
        IsMoving = false;
        speedX = speedY = 0;
        size = CCDirector::sharedDirector()->getWinSize();
    }
    
    InputLayer::~InputLayer()
    {
    
    }
    
    bool InputLayer::init()
    {
        bool bRet = false;
        do
        {
            //先初始化父类,如果失败则break循环
            CC_BREAK_IF(! CCLayer::init());
    
            //创建一个关闭按钮菜单置于屏幕右下角
            CCMenuItemLabel *txtmenItem = CCMenuItemLabel::create(CCLabelTTF::create("EXIT", "Arial", 20), this, menu_selector(InputLayer::menuCloseCallback));
            CC_BREAK_IF(! txtmenItem);
            txtmenItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - txtmenItem->getContentSize().width/2, 20));
            CCMenu* pMenu = CCMenu::create(txtmenItem, NULL);
            pMenu->setPosition(CCPointZero);
            CC_BREAK_IF(! pMenu);
    
            // Add the menu to HelloWorld layer as a child layer.
            this->addChild(pMenu, 10);
    
            this->InitHero();                //初始化精灵
            this->setTouchEnabled(TRUE);    //打开触摸事件处理
            this->InitJoystick();            //初始化摇杆
            //this->InitBullet();                //初始化子弹
            this->InitFox();                //初始化敌人-9尾狐
    
            //每帧要执行的函数  
            this->schedule(schedule_selector(InputLayer::Moving));
            this->schedule(schedule_selector(InputLayer::Shootupdate));
    
            bRet = true;
    
        }while(0);
    
        return bRet;
    
    }
    
    void InputLayer::menuCloseCallback(CCObject* pSender)
    {
        CCDirector::sharedDirector()->end();
    }
    
    void InputLayer::InitJoystick()
    {
        //创建摇杆下面部分 
        joystick1 = CCSprite::create("joystick1.png");  
        //设置透明度,锚点,位置
        joystick1->setOpacity(150);
        joystick1->setAnchorPoint(ccp(0, 0));
        joystick1->setPosition(ccp(0, 0));
        joystick1->setColor(ccGREEN);
        //大圆半径
        R=joystick1->getContentSize().width/2;  
        //中心点  
        O = ccp(R, R);  
        //添加进布景  
        this->addChild(joystick1, 3);
    
        //创建摇杆上面圆圈部分 
        joystick = CCSprite::create("joystick2.png");
        //设置位置为摇杆中心点并添加进布景
        joystick->setPosition(ccp(O.x, O.y));
        joystick->setColor(ccRED);
        joystick->setScale(0.5f);
        this->addChild(joystick, 4);
    
    }
    void InputLayer::InitHero()
    {
        CCSize size = CCDirector::sharedDirector()->getWinSize();
        this->setPlayer(CCSprite::create("hartnett.jpg"));
        _player->setScale(0.3f);
        float picsize = _player->getContentSize().width * 0.3f;
        _strike = CCMotionStreak::create(0.5f, picsize, picsize, ccWHITE, "hartnett.jpg");
        this->addChild(_strike);
        CCSize spSize = _player->getContentSize();
        _player->setPosition(ccp(size.width/2, spSize.height * 0.5f * 0.3f));
        this->addChild(_player);
    }
    void InputLayer::Moving(float dt)  
    {  
        if (IsMoving && (speedX != 0 || speedY != 0))
        {  
            //精灵移动
            CCPoint position = ccp(_player->getPosition().x + speedX * 3, _player->getPosition().y + speedY * 3);
            CCSize size = CCDirector::sharedDirector()->getWinSize();
            CCSize spSize = _player->getContentSize();
            CCRect rect = CCRectMake(spSize.width * 0.5f * 0.3f, spSize.height * 0.5f * 0.3f, size.width - spSize.width * 0.5f * 0.3f * 2, size.height - spSize.height * 0.5f * 0.3f * 2);  
    
            //判断触摸点是否在屏幕内  
            if(rect.containsPoint(position))
            {  
                _player->setPosition(position);
                _strike->setPosition(position);
                
            }  
    
        }  
    }  
    
    float InputLayer::heronsformula(float x1, float y1, float x2, float y2, float x3, float y3)  
    {  
        //求边长a  
        float a = sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));  
        //求边长b  
        float b = sqrt(pow(x2 - x3, 2) + pow(y2 - y3, 2));  
        //求边长c  
        float c = sqrt(pow(x3 - x1, 2) + pow(y3 - y1, 2));  
        //求半周长s  
        float s = (a + b + c) / 2;  
      
        //根据海伦公式返回三角形面积  
        return sqrt(s * (s - a) * (s - b) * (s - c));  
    }  
      
    //判断三个新三角形面积和是否等于原先三角形面积的函数的实现  
    bool InputLayer::triangleContainPoint(float x1, float y1, float x2, float y2, float x3, float y3, float px, float py)  
    {  
        //求S1的面积  
        float s1=heronsformula(x1, y1, x2, y2, px, py);  
        //求S2的面积  
        float s2=heronsformula(x2, y2, x3, y3, px, py);  
        //求S3的面积  
        float s3=heronsformula(x3, y3, x1, y1, px, py);  
        //求S的面积  
        float s=heronsformula(x1, y1, x2, y2, x3, y3);  
      
        //返回S是否等于S1,S2,S3的和  
        return abs(s - (s1 + s2 + s3)) < 0.001f;  
    }  
    
    
    void InputLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
    {
        CCTouch *touch = (CCTouch*)pTouches->anyObject();  
        CCPoint location = touch->getLocation();  
      
        CCRect rect = joystick->boundingBox();  
        if (rect.containsPoint(location))  
        {  
            IsMoving = true;  
        }  
    }
    
    void InputLayer::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
    {
        CCTouch *touch = (CCTouch*)pTouches->anyObject();  
        CCPoint location = touch->getLocation();  
      
        //判断触摸滑动点是否在摇杆范围内  
        bool inRange = pow(O.x - location.x, 2) + pow(O.y - location.y, 2) < pow(R, 2);  
        if (IsMoving && inRange)
        {  
            CCPoint position=_player->getPosition();  
            joystick->setPosition(location);  
      
            float r = R * 2 / 6;  
            float d = R * 2 / 3;  
    
            //上,区域2或5  
            if(triangleContainPoint(O.x, O.y, O.x - r, O.y + r, O.x  +r, O.y + r, location.x, location.y)  
                || CCRectMake(O.x - r, O.y + r, d, d).containsPoint(location))
            {  
                speedX = 0;  
                speedY = 1;  
            }  
    
            //下,区域6或11  
            else if (triangleContainPoint(O.x, O.y, O.x - r, O.y - r, O.x + r, O.y - r, location.x, location.y)  
                || CCRectMake(O.x - r, O.y - r - d, d, d).containsPoint(location))
            {  
                speedX = 0;  
                speedY = -1;  
            }  
    
            //左,区域4或7  
            else if (triangleContainPoint(O.x, O.y, O.x - r, O.y + r, O.x - r, O.y - r, location.x, location.y)  
            || CCRectMake(O.x - r - d, O.y - r, d, d).containsPoint(location))
            {  
                speedX = -1;  
                speedY = 0;  
            }  
    
            //右,区域9或8  
            else if (triangleContainPoint(O.x, O.y, O.x + r, O.y + r, O.x + r, O.y - r, location.x, location.y)  
            || CCRectMake(O.x + r, O.y - r, d, d).containsPoint(location))
            {  
                speedX = 1;  
                speedY = 0;  
            }  
    
            //右上,区域3  
            else if (location.x - (O.x + r) > 0 && location.y - (O.y + r) > 0)
            {  
                speedX = 0.7f;  
                speedY = 0.7f;  
            }  
    
            //左上,区域1  
            else if (location.x - (O.x - r) < 0 && location.y - (O.y + r) > 0)
            {  
                speedX =- 0.7f;  
                speedY = 0.7f;  
            }  
    
            //左下,区域10  
            else if (location.x - (O.x - r) < 0 && location.y - (O.y - r) < 0)
            {  
                speedX = -0.7f;  
                speedY = -0.7f;  
            }  
    
            //右下,区域12  
            else if (location.x - (O.x + r) > 0 && location.y - (O.y - r) < 0)
            {  
                speedX = 0.7f;  
                speedY = -0.7f;  
            }
        }
    }
    
    void InputLayer::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
    {
        IsMoving = false;  
        joystick->setPosition(O);  
        speedX = speedY = 0;  
    }
    /*
    void InputLayer::InitBullet()
    {
        
        _spritebatchnode = CCSpriteBatchNode::create("bullet.png");
        _spritebatchnode->setPosition(ccp(size.width, size.height/2));
        this->addChild(_spritebatchnode, 12);
    
        for (int i = 0; i < 200; i++)
        {
            CCSprite *bullet = CCSprite::create("bullet.png");
            bullet->setPosition(ccp(-50, -50));        //置于屏幕外面
            bullet->setScale(0.3f);
            _spritebatchnode->addChild(bullet);
        }
    }
    */
    void InputLayer::InitFox()
    {
        CCSprite *tmpfox = CCSprite::create("fox.png");
        CCSize foxsize = tmpfox->getContentSize();
        //tmpfox->setPosition(ccp(size.width/2, size.height/2));
        //tmpfox->setScale(0.3f);
        //this->addChild(tmpfox);
        //CCLOG("Fox num %d", (int)(size.width / foxsize.width / 0.3f));
        int foxnum = (int)(size.width / foxsize.width / 0.3f);
        for (int i = 0; i < foxnum; i++)
        {
            CCSprite *fox = CCSprite::create("fox.png");
            fox->setScale(0.3f);
            fox->setPosition(ccp(foxsize.width * 0.3f * 0.5f + i * foxsize.width * 0.3f, size.height - foxsize.height * 0.5f * 0.3f));
            this->addChild(fox);
        }
    }
    
    void InputLayer::shootBulletFromHero(CCSprite *bullet, cocos2d::CCPoint point)
    {
        float spread = (CCRANDOM_0_1() + 12.5f) * 0.5f;
        velocity = ccp(0, spread);
        bullet->setPosition(ccp(point.x, point.y + this->getPlayer()->getContentSize().height * 0.5f * 0.3f));
        bullet->setVisible(true);
    
        CCRotateBy* rotate = CCRotateBy::actionWithDuration(1, 360 * 5);
        bullet->runAction(rotate);
    
        this->scheduleUpdate();
    }
    
    void InputLayer::update(float dt)
    {
        bullet->setPosition(ccpAdd(bullet->getPosition(), velocity));
        _bulletstrike->setPosition(ccpAdd(bullet->getPosition(), velocity));
    
        if (bullet->getPosition().y > size.height)
        {
            bullet->setVisible(false);
            this->unscheduleAllSelectors();
    
            this->schedule(schedule_selector(InputLayer::Moving));
            this->schedule(schedule_selector(InputLayer::Shootupdate));
        }
    
    
    }
    
    void InputLayer::Shootupdate(float dt)
    {
        this->unschedule(schedule_selector(InputLayer::Shootupdate));
        bullet = CCSprite::create("bullet.png");
        bullet->setPosition(ccp(-50, -50));        //置于屏幕外面
        bullet->setScale(0.3f);
        this->addChild(bullet);
        float picsize = bullet->getContentSize().width * 0.5f;
        _bulletstrike = CCMotionStreak::create(0.5f, picsize, picsize, ccRED, "bullet.png");
        this->addChild(_bulletstrike);
        this->shootBulletFromHero(bullet, this->getPlayer()->getPosition());
    }
  • 相关阅读:
    Solidity 官方文档中文版 3_安装Solidity
    javaweb监听器
    ssh基础配置大全
    servlet
    压缩介绍
    jsp小结
    servlet生命周期
    后台权限验证
    进程&线程
    StrutsPreparedAndExcuteFilter与Interceptor
  • 原文地址:https://www.cnblogs.com/awakenjoys/p/cocos2d_shooting_1.html
Copyright © 2011-2022 走看看