在cocos2d-x引擎中 使用了类CCAccelerometer来存储加速度计的信息 类CCAccelerometer的作用和用户操作的分发器类似 区别在于用户操作的分发器可以拥有很多委托对象 而加速度计只存在一个委托对象 这是因为一个移动设备只有一个硬件 所以接口进行了简化 CCAccelerometerDelegate就是加速度计的委托对象
和触摸事件事件一样 重力感应的处理先被引擎抽象为一个触摸代理的协议 然后由CCLayer提供了一个接口 在实际开发中 只需要重载加速度计事件即可
virtual void didAccelerate(CCAcceleration* pAccelerationValue);
CCAcceleration是一个结构体 包含加速度计获得的三个方向的加速度
typedef struct
{
double x;
double y;
double z;
double timestamp;
}CCAcceleration;
为了便于游戏中开发使用 每一个结构体中的每一个方向的加速度大小都是以一个重力加速度为单位9.8m/s的平方 举例来说 当手机放置得桌子上的时候 获得的加速度应该为(0,1,0)
正常使用的时候 总的加速度应该在1上下波动 如果检测到一个大幅度的偏离1 可以判断为突然动作:手摇手机 会在一个或者多个方向上出现出很大的加速度 投掷或者坠落则很容易检测到一个很小的加速度
void AccelerometerTest::onEnter()
{
CCLayer::onEnter();
setAccelerometerEnabled(true);//想要当前CCNode对象可以接收加速度计的操作信息 必须在初始化函数中调用此函数
CCLabelTTF* label = CCLabelTTF::create(title().c_str(), "Arial", 32);
addChild(label, 1);
label->setPosition( ccp(VisibleRect::center().x, VisibleRect::top().y-50) );
m_pBall = CCSprite::create("Images/ball.png");
m_pBall->setPosition(ccp(VisibleRect::center().x, VisibleRect::center().y));
addChild(m_pBall);
m_pBall->retain();
}
重写didAccelerate这个函数 获得CCAcceleration结构体信息 获得X,Y,Z方向上的加速度 分别乘以重力加速度获得相应的加速度
void AccelerometerTest::didAccelerate(CCAcceleration* pAccelerationValue)
{
// double fNow = pAccelerationValue->timestamp;
//
// if (m_fLastTime > 0.0)
// {
// CCPoint ptNow = convertToUI
// }
//
// m_fLastTime = fNow;
CCDirector* pDir = CCDirector::sharedDirector();
/*FIXME: Testing on the Nexus S sometimes m_pBall is NULL */
if ( m_pBall == NULL ) {
return;
}
CCSize ballSize = m_pBall->getContentSize();
CCPoint ptNow = m_pBall->getPosition();
CCPoint ptTemp = pDir->convertToUI(ptNow);
ptTemp.x += pAccelerationValue->x * 9.81f;
ptTemp.y -= pAccelerationValue->y * 9.81f;
CCPoint ptNext = pDir->convertToGL(ptTemp);
FIX_POS(ptNext.x, (VisibleRect::left().x+ballSize.width / 2.0), (VisibleRect::right().x - ballSize.width / 2.0));
FIX_POS(ptNext.y, (VisibleRect::bottom().y+ballSize.height / 2.0), (VisibleRect::top().y - ballSize.height / 2.0));
m_pBall->setPosition(ptNext);
}
//------------------------------------------------------------------
//
// AccelerometerTestScene
//
//------------------------------------------------------------------
void AccelerometerTestScene::runThisTest()
{
CCLayer* pLayer = new AccelerometerTest();
addChild(pLayer);
pLayer->release();
CCDirector::sharedDirector()->replaceScene(this);
}
class CC_DLL CCAccelerometer
{
public:
CCAccelerometer();
~CCAccelerometer();
void setDelegate(CCAccelerometerDelegate* pDelegate);
void setAccelerometerInterval(float interval);
void update( double x,double y,double z,double timestamp );
private:
CCAcceleration m_obAccelerationValue;
CCAccelerometerDelegate* m_pAccelDelegate;
};
NS_CC_END
CCAccelerometer::CCAccelerometer() :
m_pAccelDelegate(NULL)
{
memset(&m_obAccelerationValue, 0, sizeof(m_obAccelerationValue));
}
CCAccelerometer::~CCAccelerometer()
{
}
void CCAccelerometer::setDelegate(CCAccelerometerDelegate* pDelegate)
{
m_pAccelDelegate = pDelegate;
// Enable/disable the accelerometer.
// Well, there isn't one on Win32 so we don't do anything other than register
// and deregister ourselves from the Windows Key handler.
if (pDelegate)
{
// Register our handler
CCEGLView::sharedOpenGLView()->setAccelerometerKeyHook( &myAccelerometerKeyHook );
}
else
{
// De-register our handler
CCEGLView::sharedOpenGLView()->setAccelerometerKeyHook( NULL );
resetAccelerometer();
}
}
void CCAccelerometer::setAccelerometerInterval(float interval)
{
}
void CCAccelerometer::update( double x,double y,double z,double timestamp )
{
if (m_pAccelDelegate)
{
m_obAccelerationValue.x = x;
m_obAccelerationValue.y = y;
m_obAccelerationValue.z = z;
m_obAccelerationValue.timestamp = timestamp;
// Delegate
m_pAccelDelegate->didAccelerate(&m_obAccelerationValue);
}
}
NS_CC_END