cocos2d-x游戏开发 跑酷(五) 跳起和下蹲动作 手势识别
来源:互联网 发布:淘宝网旧版首页 编辑:程序博客网 时间:2024/05/02 04:36
转载请注明出处:http://blog.csdn.net/dawn_moon/article/details/22051929
人物已经可以跑动起来了,但是还仅仅只是一个单调的跑动,还会跑出屏幕。先实现一个无限滚动背景。
实现滚动背景有几个方式:
1.人物位置不动,背景滚动。我之前的天天飞翔是用的这种,不过那个背景移动是用的动画,两张图片重复动作滚动。还有之前的雷电,也是背景滚动。不过实现有点区别,是循环改变背景的Y坐标来实现的。
2.人物移动,当前层跟随人物,使用CCFollow。详细用法有兴趣可以自己搜索。
3.人物移动,摄像机跟随。这里用的就是第三种方式。
先解释一下CCCamera摄像机的概念:
OpenGL有个视点转换函数gluLookAt函数,原型:
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
第一组eyex, eyey,eyez 相机在世界坐标的位置
第二组centerx,centery,centerz 目标参考物体在世界坐标的位置
第三组upx,upy,upz 相机竖直方向在世界坐标中的方向向量
你把相机想象成为你自己的脑袋:
第一组数据就是脑袋的位置
第二组数据就是眼睛看的物体的位置
第三组就是头顶朝向的方向(因为你可以歪着头看同一个物体)。
CCCamera的概念跟这个类似。
为什么调整eyez的值可以实现缩放。Z值就是摄像机离物体距离,拿眼睛看一个物体,离物体远,看起来物体小,离物体近,物体看起来大。
这里我们不调整eyez的值,因为不做缩放,用默认就好。
需要调整摄像机X坐标和参考目标的X坐标,让摄像机跟随人物移动:
mLastEyeX = mRunner->getRunnerPX() - mRunner->getOffsetPx(); CCCamera* camera = this->getCamera(); float eyeZ = CCCamera::getZEye(); camera->setEyeXYZ(mLastEyeX, 0, eyeZ); camera->setCenterXYZ(mLastEyeX, 0, 0);
我用手势控制人物跳起和蹲下,但是我懒的弄那个手势识别的库就直接用了SimpleRecognizer,识别上下左右的滑动,向上滑动就跳起,向下滑动就蹲下。先来看动作,Runner.cpp里面:
void Runner::initAction(){ CCArray* animateFrames = CCArray::create(); char str[50] = {0}; for (int i = 0; i != 8; ++i) { sprintf(str, "runner%d.png", i); animateFrames->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str)); } CCAnimation* animationRunning = CCAnimation::createWithSpriteFrames(animateFrames, 0.1); // 设置无限循环 animationRunning->setLoops(-1); // 循环动画貌似可以不设置这个 animationRunning->setRestoreOriginalFrame(true); // running animation 命名 CCAnimationCache::sharedAnimationCache()->addAnimation(animationRunning, "running"); // jumpUpAction animateFrames->removeAllObjects(); for (int i = 0; i != 4; ++i) { sprintf(str, "runnerJumpUp%d.png",i); animateFrames->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str)); } CCAnimation* animationJumpUp = CCAnimation::createWithSpriteFrames(animateFrames, 0.2); // 动画完毕停在最后一帧 animationJumpUp->setRestoreOriginalFrame(false); // jumpUp animation 命名 CCAnimationCache::sharedAnimationCache()->addAnimation(animationJumpUp, "jumpUp"); // jumpDownAction animateFrames->removeAllObjects(); for (int i = 0; i != 2; ++i) { sprintf(str, "runnerJumpDown%d.png",i); animateFrames->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str)); } CCAnimation* animationJumpDown = CCAnimation::createWithSpriteFrames(animateFrames, 0.3); animationJumpDown->setRestoreOriginalFrame(false); // jumpDown animation 命名 CCAnimationCache::sharedAnimationCache()->addAnimation(animationJumpDown, "jumpDown"); // crouchAction animateFrames->removeAllObjects(); animateFrames->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("runnerCrouch0.png")); CCAnimation* animationCrouch = CCAnimation::createWithSpriteFrames(animateFrames,0.3); animationCrouch->setRestoreOriginalFrame(false); // crouch animation 命名 CCAnimationCache::sharedAnimationCache()->addAnimation(animationCrouch, "crouch"); }
生产序列帧的流程:
-- 生成单帧
-- 将序列帧存入数组
-- 用帧数组生成CCAnimation
-- 将animation存入缓存,取别名(用的时候通过名字取出即可)
这里值得注意的是需要设置帧间隔和是否恢复第一帧(setRestoreOriginalFrame)
setRestoreOriginalFrame这个函数看名字有点难理解,不过我试过后发现是恢复第一帧,就是说如果设为true,那么动画播放完毕后就会停留在第一帧,如果设为false则停在最后一帧。
动作初始化完毕后,要用的时候通过名字调用:
void Runner::runAction(const char *action){ // 通过名字获取animation CCAnimation* animation = CCAnimationCache::sharedAnimationCache()->animationByName(action); mRunner->runAction(CCAnimate::create(animation));}
我们要为人物添加跳起和蹲下的动作,由于人物和一个物理刚体关联,就需要对物体的初始化做相应修改。人物跑动和人物蹲下的中心坐标是不一样的,同时其物理性状大小也不一样,修改如下:
void Runner::initShape(const char* type){ // 如果物体已经有一个形状则删掉 if(mBody->GetFixtureList()) { mBody->DestroyFixture(mBody->GetFixtureList()); } if (strcmp(type,"running") == 0) { // 人物站立,中心改变,调整位置 mBody->SetTransform(b2Vec2(mBody->GetPosition().x, (GROUND_HEIGHT + mRunnerSize.height / 2) / RATIO), mBody->GetAngle()); // 定义runner的形状,一个box,参数是半宽高 mShape.SetAsBox(mRunnerSize.width / 2 / RATIO, mRunnerSize.height / 2 / RATIO); }else { // 由于人物下蹲的大小和站立大小不一致,所以要下调位置 mBody->SetTransform(b2Vec2(mBody->GetPosition().x, (GROUND_HEIGHT + mCrouchSize.height / 2) / RATIO) ,mBody->GetAngle()); // 定义runner下蹲的形状,一个box,参数是半宽高 mShape.SetAsBox(mCrouchSize.width / 2 / RATIO, mCrouchSize.height / 2 / RATIO); } b2FixtureDef fixDef; fixDef.friction = 0.0f; fixDef.shape = &mShape; mBody->CreateFixture(&fixDef);}
好了,只要识别向上的手势就跳起,向下滑动就蹲下,看跳起和蹲下的函数:
void Runner::jump(){ if (mState == RunnerStateRunning) { float impulse = mBody->GetMass() * 10; // 根据物体质量,施加一个向上的力,人物就会跳起 mBody->ApplyLinearImpulse(b2Vec2(0, impulse), mBody->GetWorldCenter()); mState = RunnerStateJumpUp; mRunner->stopAllActions(); runAction("jumpUp"); SimpleAudioEngine::sharedEngine()->playEffect(jumpmusic); }}void Runner::crouch(){ if (mState == RunnerStateRunning) { this->initShape("crouch"); mRunner->stopAllActions(); runAction("crouch"); mState = RunnerStateCrouch; scheduleOnce(schedule_selector(Runner::loadNormal), 1.5); SimpleAudioEngine::sharedEngine()->playEffect(crouchmusic); }}
人物蹲下后怎样恢复跑动的状态呢,直接1.5秒后调用loadNormal函数就好:
void Runner::loadNormal(){ initShape("running"); mRunner->stopAllActions(); runAction("running"); mState = RunnerStateRunning;}
人物跳起的动作分jumpUp和jumpDown,怎么样区分?
判断人物在Y轴上的速度分量,给物体一个向上的力,物体会在单步时间段内加速到指定速度,由于重力加速度的存在,Y轴速度会递减。这里的做法是,当物体速度小于0.1时开始到达顶点,那么切换状态到RunnerStateJumpDown同时切换jumpDown的动画。在RunnerStateJumpDown状态时,如果Y轴速度变为0,就是到达地面了。
毫无疑问,这些迭代要写在update函数里面:
void Runner::update(float dt){ b2Vec2 vel = mBody->GetLinearVelocity(); if (mState == RunnerStateJumpUp) { if (vel.y < 0.1) { mState = RunnerStateJumpDown; mRunner->stopAllActions(); runAction("jumpDown"); } } if (mState == RunnerStateJumpDown) { if (vel.y == 0) { mState = RunnerStateRunning; mRunner->stopAllActions(); runAction("running"); } } }
好了,这些都做完了,在PlayScene.cpp里面修改update函数
void PlayScene::update(float dt){ // 物理世界的迭代函数 mWorld->Step(dt, 10, 8); // 移动相机实现滚动地图 mLastEyeX = mRunner->getRunnerPX() - mRunner->getOffsetPx(); CCCamera* camera = this->getCamera(); float eyeZ = CCCamera::getZEye(); camera->setEyeXYZ(mLastEyeX, 0, eyeZ); camera->setCenterXYZ(mLastEyeX, 0, 0); // runner状态迭代 mRunner->update(dt);}
看下效果:
- cocos2d-x游戏开发 跑酷(五) 跳起和下蹲动作 手势识别
- cocos2d-x游戏开发 跑酷(五) 跳起和下蹲动作 手势识别
- Cocos2d-X游戏开发(五)
- iphone游戏开发之cocos2d(五)游戏中的动作CCAction
- Cocos2d-X游戏【泰然网《跑酷》】JS到C++移植7:Gesture Recognizer【手势识别】
- Cocos2d-x简易手势识别
- Cocos2d-x手机游戏开发中-组合动作
- 【cocos2d-x游戏开发】动作事件的监听
- Cocos2d-x游戏开发——简单的动作
- Cocos2d-x游戏开发——重复动作CCRepeatForever&CCJumpBy
- Cocos2d-x游戏开发——动作监听
- 【Cocos2d入门教程五】Cocos2d-x动作篇
- 【cocos2D-x学习】17.手势识别
- <cocos2d-x for wp7>在cocos2d-x里面手势识别
- cocos2d-x for wp7在cocos2d-x里面手势识别
- cocos2d-x游戏开发 跑酷(七) 添加金币和岩石
- cocos2d-x游戏开发 跑酷(七) 添加金币和岩石
- 【cocos2d-x游戏开发】场景和层
- Android的Message机制(简单小结)
- 原来还有cookie-free domain这么回事
- 伴随着父亲在这北灵境厮
- java中的构造方法
- Sicily8544
- cocos2d-x游戏开发 跑酷(五) 跳起和下蹲动作 手势识别
- 《APUE》chapter 6 System Data files and information 学习笔记(加上自己的代码)
- 将牧尘看做自己
- 在线教育十字路口:新东方遭危机 YY欲成颠覆者
- 没有谁不可取代
- poj——2502——Subway
- 扩展思维能力
- Access PostgreSQL with Python
- 花花的心不知道