您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x--发射多发子弹

2013-11-30 15:35 429 查看
一个简单的发射多发子弹的模型,效果图如下:

四发子弹:



五发子弹:



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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息