cocos2d 皮球弹跳翻案实现
Dionysos 2014-4-14
今天,策划提了个翻案,要求实现皮球的弹跳效果,并且能够实现模拟真实世界,要求有皮球收缩效果。下午,粗略的尝试下,大概效果是实现。当然还有很多细节,要在具体实现。先把代码放出来,能实现加入Box2D,在放一个新版本。代码如下:
BallFall.h
#ifndef __BALL_FALL_H__
#define __BALL_FALL_H__
#include "cocos2d.h"
USING_NS_CC;
class BallFall : public CCSprite
{
private:
CCSprite* m_spBall;
float m_fGravity; ///< 重力
float m_fRebound; ///< 反弹力
float m_fVelocity; ///< 速度
float m_fHorizontalLine; ///< 水平线
int m_iScale; ///< 形变次数
int m_iScaleType; ///< 球是否挤压
void initData(const char* ballName, float fHorizontalLine);
public:
BallFall();
virtual ~BallFall();
bool initDate(void);
static BallFall* create(const char* ballName, float fHorizontalLine);
virtual bool init(const char* ballName, float fHorizontalLine = 0.0f);
public:
void FallUpdate(float delta);
void openSchedule(void);
void closeSchedule(void);
void setHorizontalLine(float horizontalLine);
};
#endif
BallFall.cpp
#include "BallFall.h"
BallFall::BallFall()
{
}
BallFall::~BallFall()
{
}
///@brief 精灵创建
///
///@param[in] ballName--精灵路径 fHorizontalLine--水平线位置(这里代表y轴位置)
///@return 精灵对象
///@retval
///@post
///@author DionysosLai, 906391500@qq.com
///@version 1.0
///@data 2014-04-14
BallFall* BallFall::create(const char* ballName, float fHorizontalLine)
{
BallFall *pSprite = new BallFall();
if (pSprite && pSprite->init(ballName, fHorizontalLine))
{
pSprite->autorelease();
return pSprite;
}
CC_SAFE_DELETE(pSprite);
return NULL;
}
bool BallFall::init(const char* ballName, float fHorizontalLine)
{
if (!CCSprite::init())
{
return false;
}
initData(ballName, fHorizontalLine);
return true;
}
///@brief 数据初始化
///
///@param[in] ballName--精灵路径 fHorizontalLine--水平线位置(这里代表y轴位置)
///@return 无
///@retval
///@post
///@author DionysosLai, 906391500@qq.com
///@version 1.0
///@data 2014-04-14
void BallFall::initData(const char* ballName, float fHorizontalLine)
{
m_fGravity = 1.0f; ///< 重力
m_fRebound = 0.0f; ///< 反弹力
m_fVelocity = 0.0f; ///< 速度
m_fHorizontalLine = fHorizontalLine; ///< 水平线
m_iScale = 3;
m_spBall = CCSprite::create(ballName);
m_spBall->setPosition(CCPointZero);
addChild(m_spBall);
}
///@brief 设置水平位置
///
///@param[in] horizontalLine--水平线位置(这里代表y轴位置)
///@return 无
///@retval
///@post
///@author DionysosLai, 906391500@qq.com
///@version 1.0
///@data 2014-04-14
void BallFall::setHorizontalLine(float horizontalLine)
{
m_fHorizontalLine = horizontalLine;
}
void BallFall::openSchedule(void)
{
schedule(schedule_selector(BallFall::FallUpdate), 0.05f);
}
void BallFall::closeSchedule(void)
{
unschedule(schedule_selector(BallFall::FallUpdate));
}
///@brief 皮球弹跳主要函数 主要完成位置更新,速度更新,反弹力跟新等
///
///@param[in]
///@return 无
///@retval
///@post
///@author DionysosLai, 906391500@qq.com
///@version 1.0
///@data 2014-04-14
void BallFall::FallUpdate(float delta)
{
CCPoint pointBall = this->getPosition();
CCSize sizeBall = m_spBall->getContentSize();
/// 首先监测球是否碰到地面了
if (0.2 > pointBall.y-m_fHorizontalLine-sizeBall.height/2.0f) ///< 这里不用0.0, 是保证误差存在
{
if (0 == m_iScaleType)
{
m_fRebound = m_fVelocity/4.f;
if (m_fRebound <= -5.5f )
{
m_fRebound = -5.5f; ///< 调整反弹力,否则会越跳越高
}
if (m_fRebound >= -0.2f)
{
closeSchedule();
}
m_fVelocity = -m_fGravity-m_fRebound; ///< 速度调整
pointBall.y += m_fVelocity;
this->setPosition(pointBall);
}
else
{
float scaleBallY = m_spBall->getScaleY();
if (1 == m_iScaleType)
{
m_spBall->setScaleY(scaleBallY - 0.1f);
m_iScale--;
if (0 >= m_iScale)
{
m_iScaleType = 2;
}
}
else
{
m_spBall->setScaleY(scaleBallY + 0.1f);
scaleBallY = m_spBall->getScaleY();
if (scaleBallY >= 1.0f)
{
m_iScaleType = 0;
}
}
}
}
else
{
pointBall.y += m_fVelocity;
/// 监测是否碰到地面了
if (0.2 > pointBall.y-m_fHorizontalLine-sizeBall.height/2.0f)
{
pointBall.y = m_fHorizontalLine+sizeBall.height/2.0f;
m_iScale = -(int)(m_fVelocity/6);
if (m_iScale >= 3)
{
m_iScale = 3;
}
m_iScaleType = 1;
}
else
{
m_fVelocity += -m_fGravity-m_fRebound; ///< 速度调整
}
if (0.0 != m_fRebound)
{
m_fRebound += 1.f;
if (0.1 < m_fRebound)
{
m_fRebound = 0.0f;
}
}
this->setPosition(pointBall);
}
}
用法如下:
/// 添加“球”精灵
BallFall* bf = BallFall::create("01.png", 0.0f);
bf->setPosition(ccp(visibleSize.width/2.0f, visibleSize.height));
bf->openSchedule();
this->addChild(bf, 2);
皮球效果还有几个方面要提高:
1. 皮球变形时,是两边一起变形,改进方案是一边变形即可;
2. 皮球变形时,位置未调整,气球比较小,看不出来,如果比较大,那肯定有“悬空”感觉------等着测试发bug吧,因此要调整;
3. 只能实现y轴弹跳,下次改进翻案:传入下落的高度,但地面可以根据手机倾斜角度发生变化(。。。好像游戏地面不能倾斜吧);
4. 皮球静止是,应该是随机向左右两边移动,这样跟真实(尝试加入小石头,碰到小石头,皮球形变,弹跳方向均发生变化。)
===就想到这里了。