Cocos2d-x--发射多发子弹

一个简单的发射多发子弹的模型,效果图如下:

四发子弹:



五发子弹:



Bullet.h

#ifndef __BULLET_H__
#define __BULLET_H__

#include "Position.h"

class Bullet
{
public:
    Bullet(const Position& from, float radius);    
    Position getPosition() const;
    void setPosition(float x, float y);
    void setPosition(const Position& pos);
    float getRadius() const;
    float mIncrementX;
    float mIncrementY;

private:
    float mRadius;
    Position mPosition;
};
#endif


Bullet.cpp

#include "Bullet.h"

Bullet::Bullet( const Position& from, float radius )
    : mRadius(radius)
    ,mPosition(from)
    ,mIncrementX(0)
    ,mIncrementY(0){}

Position Bullet::getPosition() const
{
    return mPosition;
}

void Bullet::setPosition( float x, float y )
{
    mPosition.x = x;
    mPosition.y = y;
}

void Bullet::setPosition( const Position& pos )
{
    mPosition = pos;
}

float Bullet::getRadius() const
{
    return mRadius;
}

Position.h

#ifndef __POSITION_H__
#define __POSITION_H__

struct Position
{
    float x;
    float y;
    Position(float x, float y)
    {
        this->x = x;
        this->y = y;
    }

    Position set(float x, float y)
    {
        this->x = x;
        this->y = y;
        return *this;
    }
};
#endif

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Position.h"
#include "Bullet.h"
#include <vector>
USING_NS_CC;
using namespace std;

class HelloWorld : public cocos2d::CCLayer
{
public:
    struct Increment
    {
        float incrementX;
        float incrementY;

        Increment(float incrementX, float incrementY)
        {
            this->incrementX = incrementX;
            this->incrementY = incrementY;
        }
    };

    virtual bool init();  
    static cocos2d::CCScene* scene();
    void menuCloseCallback(CCObject* pSender);
    CREATE_FUNC(HelloWorld);

    Increment calc(const Position& from, const Position& to, float angle, float shakeAngle, int index , int count, float speed);
    double D2R(double angle);
    double R2D(double radian);

    virtual void registerWithTouchDispatcher();
    bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void draw();
    vector<Bullet*> mBullets;
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"
#define  PI 3.14159265
USING_NS_CC;

CCScene* HelloWorld::scene()
{
    CCScene *scene = CCScene::create();
    HelloWorld *layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback));
    
	pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
                                origin.y + pCloseItem->getContentSize().height/2));
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition(CCPointZero);
    this->addChild(pMenu, 1);
    this->setTouchEnabled(true);
    
    return true;
}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
	CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
}

/**
from 起始位置
to 触摸点位置
angle 每颗子弹之间的夹角
shakeAngle 子弹的抖动角度
index 子弹下载
count 子弹总数
*/
HelloWorld::Increment HelloWorld::calc( const Position& from, const Position& to, float angle, float shakeAngle, int index , int count , float speed)
{
    float mMidValue = ((float)count - 1) / 2;

    //以子弹起始点为原心,建立直角坐标系
    //一,二,三,四象限内,和X轴正负方向,Y轴正负方向,原心9种情况
    bool isInQuadrant1 = (to.x > from.x ) && (to.y > from.y);
    bool isInQuadrant2 = (to.x < from.x) && (to.y > from.y);
    bool isInQuadrant3 = (to.x < from.x) && (to.y < from.y);
    bool isInQuadrant4 = (to.x > from.x) && (to.y < from.y);
    bool isOnXR = (to.y == from.y) && (to.x > from.x);
    bool isOnXL = (to.y == from.y) && (to.x < from.x);
    bool isOnYT = (to.x == from.x) && (to.y > from.y);
    bool isOnYD = (to.x == from.x) && (to.y < from.y);
    bool isZero = (to.x == from.x) && (to.y == from.y);

    //起始点和触摸点形成的直线的斜率
    float mMidLineSlope = (from.y - to.y) / (from.x - to.x);
    //弧度值
    float mMidLineAngleR = atan(mMidLineSlope);
    //角度值
    float mMidLineAngleD = R2D(mMidLineAngleR);

    //如果在二,三象限,mMidLineAngleD会小于0
    if (isInQuadrant2 || isInQuadrant3)
    {
        //转换为正数,方便计算
        mMidLineAngleD = 180 + mMidLineAngleD;
    }
    else if (isOnYT)
    {
        mMidLineAngleD = 90;
    }
    else if (isOnXR)
    {
        mMidLineAngleD = 0;
    }
    else if (isOnXL)
    {
        mMidLineAngleD = 180;
    }
    else if (isInQuadrant4)
    {
        //在第四象限mMidLineAngleD小于0,转换为正数
        mMidLineAngleD = 360 + mMidLineAngleD;
    }
    else if (isOnYD)
    {
        mMidLineAngleD = 270;
    }
    else if(isZero)
    {
        return HelloWorld::Increment(0, 0);
    }

    //每颗子弹形成的直线的角度
    float mLineAngleD = mMidLineAngleD + (mMidValue - index) * angle + shakeAngle;
    //每颗子弹形成的直线的弧度
    float mLineAngleR = D2R(mLineAngleD);

    if (mLineAngleD > 360)
    {
        mLineAngleD = mLineAngleD - 360;
    }

    if (mLineAngleD < 0)
    {
        mLineAngleD = 360 + mLineAngleD;
    }

    //判断在直角坐标系中的位置
    isInQuadrant1 = (mLineAngleD > 0) && (mLineAngleD < 90); 
    isInQuadrant2 = (mLineAngleD > 90) && (mLineAngleD < 180);
    isInQuadrant3 = (mLineAngleD > 180) && (mLineAngleD < 270);
    isInQuadrant4 = (mLineAngleD > 270) && (mLineAngleD < 360);
    isOnXR = (mLineAngleD == 0);
    isOnXL = (mLineAngleD == 180);
    isOnYT = (mLineAngleD == 90);
    isOnYD = (mLineAngleD == 270);

    //x和y方向的增量
    float mIncrementX = 0;
    float mIncrementY = 0;
    float mIncrement = speed;

    if (isInQuadrant1)
    {
        mIncrementX = abs(mIncrement * cos(mLineAngleR));
        mIncrementY = abs(mIncrement * sin(mLineAngleR));
    }
    else if (isInQuadrant2)
    {
        mIncrementX = mIncrement * cos(mLineAngleR);
        mIncrementY = abs(mIncrement * sin(mLineAngleR));
        if(mIncrementX > 0) mIncrementX = -mIncrementX;
    }
    else if (isOnYT)
    {
        mIncrementY = speed;
    }
    else if (isOnXR)
    {
        mIncrementX = speed;
    }
    else if (isOnXL)
    {
        mIncrementX = -speed;
    }
    else if (isInQuadrant3)
    {
        mIncrementX = mIncrement * cos(mLineAngleR);
        mIncrementY = mIncrement * sin(mLineAngleR);
        if(mIncrementX > 0) mIncrementX = -mIncrementX;
        if(mIncrementY > 0) mIncrementY = -mIncrementY;
    }
    else if (isInQuadrant4)
    {
        mIncrementX = abs(mIncrement * cos(mLineAngleR));
        mIncrementY = mIncrement * sin(mLineAngleR);
        if(mIncrementY > 0) mIncrementY = -mIncrementY;
    }
    else if (isOnYD)
    {
        mIncrementY = -speed;
    }
    HelloWorld::Increment mResult = HelloWorld::Increment(mIncrementX, mIncrementY);
    return mResult;
}

/**角度转弧度*/
double HelloWorld::D2R( double angle )
{
    return angle / 180.0 * PI;
}

/**弧度转角度*/
double HelloWorld::R2D( double radian )
{
    return radian / PI * 180;
}

void HelloWorld::registerWithTouchDispatcher()
{
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}

bool HelloWorld::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
{
    //触摸点
    CCPoint mLocalTouch = pTouch->getLocation();
    CCSize mScreenSize = CCDirector::sharedDirector()->getWinSize();
    //子弹开始位置
    Position mFrom = Position(mScreenSize.width / 2, 20);
    //子弹飞向的位置
    Position mTo = Position(mLocalTouch.x, mLocalTouch.y);

    //一发5个子弹
    int count = 3;
    //圆形子弹的半径
    float mRadius = 10;
    //子弹速度
    float mSpeed = 5;
    //子弹之间的夹角
    float mAngle = 50;
    //子弹的抖动角度
    float mShakeAngle = 0;
    for (int index = 0; index < count; index++)
    {
        //返回每个子弹的增量
        Increment mIncremnet = calc(mFrom, mTo, mAngle, mShakeAngle, index, count, mSpeed);
        //实例化一个圆形子弹
        Bullet *pBullet = new Bullet(mFrom, mRadius);
        pBullet->mIncrementX = mIncremnet.incrementX;
        pBullet->mIncrementY = mIncremnet.incrementY;
        mBullets.push_back(pBullet);
    }
    return true;
}

/**绘制圆形子弹*/
void HelloWorld::draw()
{
    for (int index = 0; index < mBullets.size(); index++)
    {
        Bullet *pBullet = mBullets[index];
        pBullet->setPosition(pBullet->getPosition().x + pBullet->mIncrementX, pBullet->getPosition().y + pBullet->mIncrementY);
        ccDrawCircle(ccp(pBullet->getPosition().x, pBullet->getPosition().y), pBullet->getRadius(), 0, 70, false);
    }
    
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值