「cocos2d-x」垂直射击游戏之宇智波鼬 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());
}

 

 

 

转载于:https://www.cnblogs.com/awakenjoys/archive/2013/05/21/cocos2d_shooting_1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值