cocos2dx+KinectV2 体感游戏之微信打飞机

来源:互联网 发布:女儿出嫁父亲知乎 编辑:程序博客网 时间:2024/06/03 10:44

Cocos2dx微信打飞机体感游戏

演示视频地址:点击打开链接 (注 : 视频中两次使用炸弹,没有很好的感应,因为阈值设定有点问题,已改)

1.打飞机添加结束层   

2.道具双排子弹    (为了保证游戏趣味性,放50颗子弹后恢复单排子弹)

3.各类飞机的添加  

4.数据本地化。历史最高成绩的获取 (保存为.xml文件)

5.随着分数越高,速度越快-----设置参数改变定时器时间(单位时间产生的敌人会越多)和移动一次屏幕距离的时间即可。

5.体感游戏实现  (一周时间,技术难点较多,主要创新点)


这里提供一个kinectV2控制鼠标的C++版本程序,同时包含Chengaotan的C#版本程序供参考,Kinect V2 能实现手势识别,石头,箭头和布,因此可以控制鼠标响应不同的点击事件,网上有个人写的鼠标控制,抖动太厉害,我这个还不错,根据chenggaotan C# 程序改写 C++版本 vs2013  戳我打开KinectV2控制鼠标程序。


先讲讲老师们的层次设计,将. 背景 飞机子弹 小敌机 中敌机 大敌机 Food(炸弹) 分门别类的进行分层

主要的三个场景: start   、   main  、   over

Start 场景:

   看图片,决定屏幕大小,这里在AppDelegate中设计为

pEGLView->setDesignResolutionSize(480, 800, kResolutionExactFit);
   然后预加载一些资源  声音, 图片缓存。在处理资源时候,通常将一类,放在一起。开始头文件如下,接下来只提供cpp文件,因为头文件大同小异。

#ifndef __LayerGameStart_H__#define __LayerGameStart_H__#include "cocos2d.h"USING_NS_CC;class LayerGameStart :public CCLayer{public:static CCScene * scene();CREATE_FUNC(LayerGameStart);bool init();void addStartGamePicture();//预加载游戏背景图片void addPreLoadMusic();   //预加载音乐void toMainGameCallback(); //被回调的};#endif
cpp文件也比较简单

#include "LayerGameStart.h"#include "AppMacros.h"#include "LayerGameMain.h"#include "SimpleAudioEngine.h"using namespace CocosDenshion;  //声音的外部库#define  loadMusic()  CocosDenshion::SimpleAudioEngine::sharedEngine()CCScene * LayerGameStart::scene(){CCScene * scene = CCScene::create();LayerGameStart * layer = LayerGameStart::create();scene->addChild(layer);return scene;}bool LayerGameStart::init(){CCLayer::init();addPreLoadMusic(); //预加载音乐addStartGamePicture();//预加载图片return true;}void LayerGameStart::addStartGamePicture(){// 设置安卓返回键 setKeypadEnabled(true);//加载全局图片信息CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("ui/shoot_background.plist");CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("ui/shoot.plist");//加载当前gamestart页面所需要的图片,动画CCSprite * background = CCSprite::createWithSpriteFrameName("background.png");background->setAnchorPoint(ccp(0, 0));background->setPosition(ccp(0, 0));addChild(background);CCSprite *copyright = CCSprite::createWithSpriteFrameName("shoot_copyright.png");copyright->setAnchorPoint(ccp(0.5, 0));copyright->setPosition(ccp(winSize.width / 2, winSize.height / 2));addChild(copyright);CCSprite *loading = CCSprite::createWithSpriteFrameName("game_loading1.png");loading->setPosition(ccp(winSize.width / 2, winSize.height / 2 - 40));addChild(loading);CCAnimation * animation = CCAnimation::create();animation->setDelayPerUnit(0.2f);char nameBuf[100];for (int i = 0; i < 4; i++){memset(nameBuf, 0, sizeof(nameBuf));sprintf(nameBuf, "game_loading%d.png", i + 1);animation->addSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(nameBuf));}CCAnimate *animate = CCAnimate::create(animation);CCRepeat *repeat = CCRepeat::create(animate, 4); //动画播放四次CCCallFunc * loadingDone = CCCallFunc::create(this, callfunc_selector(LayerGameStart::toMainGameCallback));//动画播放完毕回主场景CCSequence * sequence = CCSequence::create(repeat, loadingDone, NULL);loading->runAction(sequence);}void LayerGameStart::addPreLoadMusic(){//加载全局音乐信息loadMusic()->preloadBackgroundMusic("sound/game_music.wav");loadMusic()->preloadEffect("sound/achievement.wav");loadMusic()->preloadEffect("sound/big_spaceship_flying.wav");loadMusic()->preloadEffect("sound/bullet.wav");loadMusic()->preloadEffect("sound/button.wav");loadMusic()->preloadEffect("sound/enemy1_down.wav");loadMusic()->preloadEffect("sound/enemy2_down.wav");loadMusic()->preloadEffect("sound/enemy3_down.wav");loadMusic()->preloadEffect("sound/game_over.wav");loadMusic()->preloadEffect("sound/get_bomb.wav");loadMusic()->preloadEffect("sound/get_double_laser.wav");loadMusic()->preloadEffect("sound/out_porp.wav");loadMusic()->preloadEffect("sound/use_bomb.wav");}void LayerGameStart::toMainGameCallback(){CCScene * scene = LayerGameMain::scene();CCDirector::sharedDirector()->replaceScene(scene);}
此场景会跳到主场景中去,也就是主游戏场景。

#include "LayerGameMain.h"#include "AppMacros.h"#include "LayerGameOver.h"#include "SimpleAudioEngine.h"#include "KinectControl.h"using namespace CocosDenshion;int LayerGameMain::score = 0;   //分数初始化CCScene * LayerGameMain::scene(){CCScene * scene = CCScene::create();LayerGameMain * layer = LayerGameMain::create();scene->addChild(layer);return scene;}bool LayerGameMain::init(){CCLayer::init();// 设置安卓返回键 setKeypadEnabled(true);//播放背景音乐SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/game_music.wav", true);score = 0; bombInterval =false ;   //处理多于两个炸弹间隔爆炸 bombIntervalCount = 0;bigBoomCount = 0;scheduleUpdate();  // 开启帧循环定时器 进行碰撞检测setTouchEnabled(true);setTouchMode(kCCTouchesOneByOne);addBackGround(); //加载主场景背景addHero();       //加飞机addBulletLayer();addEnemyLayer();addCtrlLayer();addFoodLayer();return true;}//加载主场景背景void  LayerGameMain::addBackGround(){CCSprite * bg1 = CCSprite::createWithSpriteFrameName("background.png");bg1->setTag(BACK1);bg1->setAnchorPoint(ccp(0, 0));bg1->setPosition(ccp(0, 0));addChild(bg1);CCSprite * bg2 = CCSprite::createWithSpriteFrameName("background.png");bg2->setTag(BACK2);bg2->setAnchorPoint(ccp(0, 0));bg2->setPosition(ccp(0, bg2->getContentSize().height - 2));addChild(bg2);//启动定时器 帧循环是一帧是0.016schedule(schedule_selector(LayerGameMain::movingBackGround), 0.01f);}//背景动起来void LayerGameMain::movingBackGround(float dt){CCSprite * bg1 = (CCSprite*)getChildByTag(BACK1);CCSprite * bg2 = (CCSprite*)getChildByTag(BACK2);bg1->setPositionY(bg1->getPositionY() - 5);bg2->setPositionY(bg1->getPositionY() + bg2->getContentSize().height - 2);if (bg2->getPositionY() < 0){bg1->setPositionY(0);}}void LayerGameMain::addHero()  //添加飞机{Plane * hero = Plane::getInstance(); //单例获得飞机hero->setPosition(ccp(winSize.width / 2, hero->getContentSize().height / 2)); //设置初始时飞机的位置addChild(hero);}bool LayerGameMain::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){CCRect planeRect = Plane::getInstance()->boundingBox();planeRect.origin.x -= 30;  planeRect.origin.y -= 40;planeRect.size.width += 60;planeRect.size.height += 80;if (planeRect.containsPoint(pTouch->getLocation())){   //点中了则继续return true;}else{return false;}}void LayerGameMain::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent){Plane *hero = Plane::getInstance();CCPoint positon = hero->getPosition() + pTouch->getDelta(); //getDelta 一帧中获得的//CCLog("%g", hero->boundingBox().size.width/2);//CCLog("%g", winSize.width - hero->boundingBox().size.width/2);//CCLog("%g", hero->boundingBox().size.height/2);//CCLog("%g", winSize.height - hero->boundingBox().size.height/2);if (positon.x < hero->boundingBox().size.width / 2 ||positon.x > winSize.width - hero->boundingBox().size.width / 2 ||positon.y <hero->boundingBox().size.height / 2 ||positon.y > winSize.height - hero->boundingBox().size.height / 2){return; //出界了}else{Plane::getInstance()->setPosition(positon);}}void LayerGameMain::addBulletLayer(){_bulletLayer = LayerBullet::create();addChild(_bulletLayer);}void LayerGameMain::addEnemyLayer(){_enemyLayer = LayerEnemy::create();addChild(_enemyLayer);}void LayerGameMain::update(float dt){//bullet vs enemysmall CCObject * bt = NULL;  //子弹CCObject * et = NULL;  //敌机CCArray  *bulletsToDel = CCArray::create();CCARRAY_FOREACH(_bulletLayer->_bulletArray, bt) //遍历子弹{CCSprite * bullet = (CCSprite*)bt;CCArray  * smallEnemyToDel = CCArray::create();CCARRAY_FOREACH(_enemyLayer->smallArray, et) //取得小敌机{Enemy * smallEnemy = (Enemy *)et;if (bullet->boundingBox().intersectsRect(smallEnemy->getBoundingBox())){CCLog("%d", smallEnemy->getLife());if (smallEnemy->getLife() == 1){smallEnemy->loseLife();bulletsToDel->addObject(bullet);smallEnemyToDel->addObject(smallEnemy);score += SMALL_SCORE;_ctrlLayer->updataScore(score); //更新分数}}}CCARRAY_FOREACH(smallEnemyToDel, et) //遍历一遍再删除{Enemy * smallEnemy = (Enemy*)et;_enemyLayer->smallEnemyBlowUp(smallEnemy);}smallEnemyToDel->release();}CCARRAY_FOREACH(bulletsToDel, bt){CCSprite * bullet = (CCSprite*)bt;_bulletLayer->removeBullet(bullet);}bulletsToDel->removeAllObjects();//----------------bullet vs midplane CCARRAY_FOREACH(_bulletLayer->_bulletArray, bt) //遍历子弹{CCSprite * bullet = (CCSprite*)bt;CCArray  * midEnemyToDel = CCArray::create();CCARRAY_FOREACH(_enemyLayer->midArray, et) //取得中敌机{Enemy * midEnemy = (Enemy *)et;if (bullet->boundingBox().intersectsRect(midEnemy->getBoundingBox())){//CCLog("%d", midEnemy->getLife());if (midEnemy->getLife() > 1){midEnemy->loseLife();_enemyLayer->midHitAnimate(midEnemy); //显示击中效果bulletsToDel->addObject(bullet);}else if (midEnemy->getLife() == 1){midEnemy->loseLife();bulletsToDel->addObject(bullet);midEnemyToDel->addObject(midEnemy);score += MID_SCORE;_ctrlLayer->updataScore(score); //更新分数}}}CCARRAY_FOREACH(midEnemyToDel, et) //遍历一遍再删除{Enemy * midEnemy = (Enemy*)et;_enemyLayer->midEnemyBlowUp(midEnemy);}midEnemyToDel->release();}CCARRAY_FOREACH(bulletsToDel, bt){CCSprite * bullet = (CCSprite*)bt;_bulletLayer->removeBullet(bullet);}bulletsToDel->removeAllObjects();////----------------------------------bullet VS bigplane CCARRAY_FOREACH(_bulletLayer->_bulletArray, bt) //遍历子弹{CCSprite * bullet = (CCSprite*)bt;CCArray  * bigEnemyToDel = CCArray::create();CCARRAY_FOREACH(_enemyLayer->bigArray, et) //取得大敌机{Enemy * bigEnemy = (Enemy *)et;if (bullet->boundingBox().intersectsRect(bigEnemy->getBoundingBox())){//CCLog("%d", bigEnemy->getLife());if (bigEnemy->getLife() > 1){bigEnemy->loseLife();_enemyLayer->bigHitAnimate(bigEnemy); //显示击中效果bulletsToDel->addObject(bullet);}else if (bigEnemy->getLife() == 1){bigEnemy->loseLife();bulletsToDel->addObject(bullet);bigEnemyToDel->addObject(bigEnemy);score += BIG_SCORE;_ctrlLayer->updataScore(score); //更新分数}}}CCARRAY_FOREACH(bigEnemyToDel, et) //遍历一遍再删除{Enemy * bigEnemy = (Enemy*)et;_enemyLayer->bigEnemyBlowUp(bigEnemy);}bigEnemyToDel->release();}CCARRAY_FOREACH(bulletsToDel, bt){CCSprite * bullet = (CCSprite*)bt;_bulletLayer->removeBullet(bullet);}bulletsToDel->removeAllObjects();//------------------------------------hero vs enemySmallCCRect planeRect = Plane::getInstance()->boundingBox();  //获得飞机单例planeRect.origin.x += 30;planeRect.origin.y += 20;planeRect.size.width -= 60;planeRect.size.height -= 40;//-----------------------//CCARRAY_FOREACH(_enemyLayer->smallArray,et){Enemy  * smallEnemy = (Enemy  *)et;if (planeRect.intersectsRect(smallEnemy->getBoundingBox())){ ((CCLayer*)(Plane::getInstance()->getParent()))->setTouchEnabled(false);  //关闭触摸_bulletLayer->stopShoot();unscheduleAllSelectors(); // 关闭所有定时器Plane::getInstance()->blowUp();Plane::getInstance()->removePlane();   //如果加了场景切换  这里就不需要REMOVE_enemyLayer->smallEnemyBlowUp(smallEnemy); //把碰撞的小敌机也销毁SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/game_over.wav", true);CCScene *over = LayerGameOver::scene(); CCDirector::sharedDirector()->replaceScene(over);}}//------------------------------------hero vs enemyMidCCARRAY_FOREACH(_enemyLayer->midArray, et){Enemy  * midEnemy = (Enemy  *)et;if (planeRect.intersectsRect(midEnemy->getBoundingBox())){((CCLayer*)(Plane::getInstance()->getParent()))->setTouchEnabled(false);  //关闭触摸_bulletLayer->stopShoot();unscheduleAllSelectors(); // 关闭所有定时器Plane::getInstance()->blowUp();Plane::getInstance()->removePlane();   //如果加了场景切换  这里就不需要REMOVE_enemyLayer->midEnemyBlowUp(midEnemy); //把碰撞的中敌机也销毁SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/game_over.wav", true);CCScene *over = LayerGameOver::scene();CCDirector::sharedDirector()->replaceScene(over);}}//------------------------------------hero vs enemyBigCCARRAY_FOREACH(_enemyLayer->bigArray, et){Enemy  * bigEnemy = (Enemy  *)et;if (planeRect.intersectsRect(bigEnemy->getBoundingBox())){((CCLayer*)(Plane::getInstance()->getParent()))->setTouchEnabled(false);  //关闭触摸_bulletLayer->stopShoot();unscheduleAllSelectors(); // 关闭所有定时器Plane::getInstance()->blowUp();Plane::getInstance()->removePlane();   //如果加了场景切换  这里就不需要REMOVE_enemyLayer->midEnemyBlowUp(bigEnemy); //把碰撞的大敌机也销毁SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/game_over.wav", true);CCScene *over = LayerGameOver::scene();CCDirector::sharedDirector()->replaceScene(over);}}//------------------------------------food vs heroCCObject * ut;CCARRAY_FOREACH(_foodLayer->bigBoomArray, ut){CCSprite * bigBoom = (CCSprite*)ut;if (bigBoom->boundingBox().intersectsRect(Plane::getInstance()->boundingBox())  ){SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/get_bomb.wav", true); //得到炸弹的音效_foodLayer->removeBigBoom(bigBoom);bigBoomCount++;  //有几个炸弹updateBigBoomCount(bigBoomCount);}}//-------------------------gesture bigboom ---------------------if (bombInterval){bombIntervalCount++;}if (bombIntervalCount > 40) //比较合理的参数 {bombInterval =false ;bombIntervalCount = 0;}if (KinectControl::getInstance()->useBomb && bigBoomCount > 0 && !bombInterval ){bombInterval = true;  //处于间隔时间SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/use_bomb.wav", true);bigBoomCount--;CCString *strBoomCount = CCString::createWithFormat("X%d", bigBoomCount);((CCLabelBMFont*)(getChildByTag(TAG_BIGBOOMCOUNT)))->setCString(strBoomCount->getCString());score += _enemyLayer->smallArray->count() * SMALL_SCORE;score += _enemyLayer->midArray->count() * MID_SCORE;score += _enemyLayer->bigArray->count() * BIG_SCORE;_ctrlLayer->updataScore(score);_enemyLayer->removeAllEnemy(); //干掉所有敌机if (bigBoomCount == 0){removeChildByTag(TAG_BIGBOOM);removeChildByTag(TAG_BIGBOOMCOUNT);}KinectControl::getInstance()->useBomb = false;}//----------------------------------foodMultiBullet vs hero CCObject * mbt;CCARRAY_FOREACH(_foodLayer->multiBulletArray, mbt){CCSprite * multiBullets = (CCSprite*)mbt;if (multiBullets->boundingBox().intersectsRect(Plane::getInstance()->boundingBox())){SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/get_double_laser.wav", true); //得到双排子弹的音效_foodLayer->removeMultiBullets(multiBullets);_bulletLayer->multiBulletEffet();  //立即使用}}}void  LayerGameMain::updateBigBoomCount(int bigBoomCount){CCString strBoomCount;if (bigBoomCount < 0){return;}else if (bigBoomCount == 0){if (getChildByTag(TAG_BIGBOOM))  //炸弹 图显示{removeChildByTag(TAG_BIGBOOM, true);}if (getChildByTag(TAG_BIGBOOMCOUNT)) //炸弹  数目的显示{removeChildByTag(TAG_BIGBOOMCOUNT, true);}}else if (bigBoomCount == 1){CCSprite * norBoom = CCSprite::createWithSpriteFrameName("bomb.png");if (!getChildByTag(TAG_BIGBOOM)){CCSprite * selBoom = CCSprite::createWithSpriteFrameName("bomb.png");CCMenuItemSprite * boomItem = CCMenuItemSprite::create(norBoom, selBoom, this, menu_selector(LayerGameMain::boomMenuCallBack));boomItem->setPosition(ccp(norBoom->getContentSize().width / 2, norBoom->getContentSize().height / 2));CCMenu * boomMenu = CCMenu::create(boomItem, NULL);boomMenu->setPosition(CCPointZero);addChild(boomMenu, 100, TAG_BIGBOOM);}if (!getChildByTag(TAG_BIGBOOMCOUNT)){strBoomCount.initWithFormat("X%d", bigBoomCount);CCLabelBMFont * labelBoomCount = CCLabelBMFont::create(strBoomCount.getCString(), "font/font.fnt");labelBoomCount->setAnchorPoint(ccp(0, 0.5));labelBoomCount->setPosition(ccp(norBoom->getContentSize().width + 15, norBoom->getContentSize().height / 2));addChild(labelBoomCount, 200, TAG_BIGBOOMCOUNT);}}else if (bigBoomCount > 1){strBoomCount.initWithFormat("X%d", bigBoomCount);((CCLabelBMFont*)(getChildByTag(TAG_BIGBOOMCOUNT)))->setCString(strBoomCount.getCString());}}void LayerGameMain::boomMenuCallBack(CCObject * obj) //炸弹炸{SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/use_bomb.wav", true);bigBoomCount--;CCString *strBoomCount = CCString::createWithFormat("X%d", bigBoomCount);((CCLabelBMFont*)(getChildByTag(TAG_BIGBOOMCOUNT)))->setCString(strBoomCount->getCString());score += _enemyLayer->smallArray->count() * SMALL_SCORE;score += _enemyLayer->midArray->count() * MID_SCORE;score += _enemyLayer->bigArray->count() * BIG_SCORE;_ctrlLayer->updataScore(score);_enemyLayer->removeAllEnemy(); //干掉所有敌机if (bigBoomCount == 0){removeChildByTag(TAG_BIGBOOM);removeChildByTag(TAG_BIGBOOMCOUNT);}}void LayerGameMain::addCtrlLayer(){_ctrlLayer = LayerControl::create();addChild(_ctrlLayer);}void LayerGameMain::addFoodLayer(){_foodLayer = LayerFood::create();addChild(_foodLayer);}

上面是主要部分,数据本地化,保存历史最高成绩实现如下:

void LayerGameOver::showScore(){ int score = LayerGameMain::score;//----------------显示最终得分------------------------------//CCString *strScore = CCString::createWithFormat("%d", score);scoreFinalItem = CCLabelBMFont::create(strScore->getCString(), "font/font.fnt");scoreFinalItem->setColor(ccc3(10, 250, 10));scoreFinalItem->setAnchorPoint(ccp(0, 0));scoreFinalItem->setPosition(ccp(winSize.width / 2 - 30, winSize.height / 2));addChild(scoreFinalItem);//----------------------历史最佳成绩显示---------------------//int  BestScore= CCUserDefault::sharedUserDefault()->getIntegerForKey("HistoryHighScore", 0);if (BestScore < score){SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/achievement.wav", true);CCUserDefault::sharedUserDefault()->setIntegerForKey("HistoryHighScore", score);CCUserDefault::sharedUserDefault()->flush(); //下次读取前先从内存写入硬盘BestScore = score;}CCString *strHistoryHighScore = CCString::createWithFormat("%d", BestScore);scoreBestItem = CCLabelBMFont::create(strHistoryHighScore->getCString() , "font/font.fnt");scoreBestItem->setColor(ccc3(160, 160, 164));scoreBestItem->setAnchorPoint(ccp(0, 0));scoreBestItem->setPosition(ccp(winSize.width / 2 - 50, winSize.height -70));addChild(scoreBestItem);}
随着游戏得分越高,速度变快和小敌机中敌机大敌机参数设置,用了一个parameter的结构体变量,同时随机化保证飞机间隔不定时间出场,设定一个计数值smallEnemyFrameCount 达到计数值后清零;

void LayerEnemy::reSetframeCount(int degree){switch (degree){case SMALL:{curSmallFramCount = 0;smallEnemyFrameCount = rand() % 8 +  (6 - parameter.smallParameter);break;}case MID:{curMidFrameCount = 0;midEnemyFrameCount = rand() % 15 + (10 - parameter.midParameter);break;}case BIG:{curBigFrameCount = 0;bigEnemyFrameCount = rand() % 25+ (35 - parameter.bigParameter);break;}default:break;}}void LayerEnemy::updateParameter(){int score = LayerControl::getScore();if (score > 1000){int degree =(int ) ((score - 1000) / 500) + 1 ;parameter.smallParameter = degree;if (parameter.smallParameter > 6)  parameter.smallParameter = 6; parameter.midParameter = degree; if (parameter.midParameter > 8) parameter.midParameter = 8;parameter.bigParameter = degree;if (parameter.bigParameter > 12) parameter.bigParameter = 12;}}
这里的体感控制,也就是手势区控制鼠标完成单击,确定,以及拖动飞机

 1 kinect 单例设计  if(!m_Kinect)

                  m_Kinect = new KinectControl;

                  if (m_Kinect &&m_Kinect->init()){}

                              }

         return m_Kinect;  //模仿cocos2dx设计风格

   2 获取运行窗体相对于整个屏幕坐标 

HWND h =cocos2d::CCEGLView::sharedOpenGLView()->getHWnd(); //获得cocos2dx窗口的句柄

          RECTrt = { 0 };

          ::GetWindowRect(h,&rt);  //得到的既是相对于屏幕左上角的窗口矩形区域

   3 关键两行代码参考chengaotan GitHub 的C#程序,还好C#和MFC大致差不多,勉强看懂。也有用指尖识别的,抖动太剧烈,不过改改采集间隔和加阈值判断应该可以。3个与鼠标操作有关的API  ClipCursor;SetCursorPos;   GetCursorPos

 https://github.com/TangoChen/KinectV2MouseControl

下下来是不能运行了,改了一回才弄好,原来wpf和mfc也类似嘛,不然就GG了。

int  xNow = (int)(curPos.x + (x*mouseSensitivity*lWidth -( curPos.x - rt.left))*smoothing);

int  yNow = (int)(curPos.y + ((y + 0.25f) *mouseSensitivity *lHeight - (curPos.y-rt.top)) * smoothing);

schedule(schedule_selector(LayerControl::kinectUpdate), 0.02f);   //定时器进行鼠标控制


   4 实现KinectV2对鼠标控制后,一开始要让鼠标指向飞机,不同手势代表不同操作。共有三种不同的手势。这里用open代表飞机移动,拳头表示使用bomb(前提是你吃到了bomb),Lasso表示确定,用来返回游戏和退出游戏。


  

这里放一个没有和游戏交互的自己改进的Kinect控制鼠标的代码,和游戏交互,为了一开始就能使鼠标在飞机上,获取了游戏运行窗口在整个屏幕上的坐标,然后将鼠标固定到飞机上


HWND h = cocos2d::CCEGLView::sharedOpenGLView()->getHWnd(); //获得cocos2dx窗口的句柄rt = { 0 };::GetWindowRect(h, &rt);  //得到的既是相对于屏幕左上角的窗口矩形区域Plane * plane = Plane::getInstance();rtNew.left = rt.left + plane->boundingBox().size.width / 3 ;rtNew.right = rt.right - plane->boundingBox().size.width / 2;rtNew.top = rt.top + 30; //加上30为菜单栏的大小rtNew.bottom = rt.bottom - plane->boundingBox().size.height / 2 - 5;TopLeftCorner = { rtNew.left, rtNew.top };  //屏幕左上角lWidth = rtNew.right - rtNew.left;lHeight = rtNew.bottom - rtNew.top;SetCurPositonInPlane();ClipCursor(&rtNew);          //限制光标在矩形区域内
游戏结束场景,可以通过手势剪刀表示确定:



游戏结束代码如下:

#include "LayerGameOver.h"#include "AppMacros.h"#include "LayerGameMain.h"#include "SimpleAudioEngine.h"#include "KinectControl.h"using namespace CocosDenshion;CCScene * LayerGameOver::scene(){CCScene * scene = CCScene::create();LayerGameOver * layer = LayerGameOver::create();scene->addChild(layer);return scene;}bool LayerGameOver::init(){CCLayer::init();addGameOverPicture();showScore();OneMoreGame();schedule(schedule_selector(LayerControl::kinectUpdate), 0.016f);   //定时器进行鼠标控制return true;}void LayerGameOver::kinectUpdate(float dt){ KinectControl::getInstance()->Update ();}void LayerGameOver::MenuGameMainCallBack(CCObject *obj) //切换场景到游戏运行界面{//SetCursorPos(1024, 955);  //就算这样 , 飞机还是回不来了 O(∩_∩)O~CCScene * scene = LayerGameMain::scene();CCDirector::sharedDirector()->replaceScene(scene);}void LayerGameOver::addGameOverPicture(){CCSprite * background = CCSprite::createWithSpriteFrameName("gameover.png");background->setAnchorPoint(ccp(0, 0));background->setPosition(ccp(0, winSize.height-background->getContentSize().height));addChild(background);}void LayerGameOver::addOneMoreGame(){MoreGame = CCSprite::createWithSpriteFrameName("btn_finish.png");MoreGame->setPosition(ccp(winSize.width / 2 - 10, winSize.height / 3 - 20));addChild(MoreGame);}void LayerGameOver::showScore(){ int score = LayerGameMain::score;//----------------显示最终得分------------------------------//CCString *strScore = CCString::createWithFormat("%d", score);scoreFinalItem = CCLabelBMFont::create(strScore->getCString(), "font/font.fnt");scoreFinalItem->setColor(ccc3(10, 250, 10));scoreFinalItem->setAnchorPoint(ccp(0, 0));scoreFinalItem->setPosition(ccp(winSize.width / 2 - 30, winSize.height / 2));addChild(scoreFinalItem);//----------------------历史最佳成绩显示---------------------//int  BestScore= CCUserDefault::sharedUserDefault()->getIntegerForKey("HistoryHighScore", 0);if (BestScore < score){SimpleAudioEngine::sharedEngine()->playBackgroundMusic("sound/achievement.wav", true);CCUserDefault::sharedUserDefault()->setIntegerForKey("HistoryHighScore", score);CCUserDefault::sharedUserDefault()->flush(); //下次读取前先从内存写入硬盘BestScore = score;}CCString *strHistoryHighScore = CCString::createWithFormat("%d", BestScore);scoreBestItem = CCLabelBMFont::create(strHistoryHighScore->getCString() , "font/font.fnt");scoreBestItem->setColor(ccc3(160, 160, 164));scoreBestItem->setAnchorPoint(ccp(0, 0));scoreBestItem->setPosition(ccp(winSize.width / 2 - 50, winSize.height -70));addChild(scoreBestItem);}void LayerGameOver::QuitCallBack(CCObject * obj){KinectControl::getInstance()->KinectRemove();exit(1);}void LayerGameOver::OneMoreGame() //添加回到游戏按钮{  CCSprite * GameOnceMore = CCSprite::createWithSpriteFrameName("btn_finish.png");CCSprite * OutGame = CCSprite::create("define/out.png");CCMenuItemSprite * Again = CCMenuItemSprite::create(GameOnceMore, GameOnceMore, this, menu_selector(LayerGameOver::MenuGameMainCallBack));CCMenuItemSprite * End =  CCMenuItemSprite::create(OutGame, OutGame , this, menu_selector(LayerGameOver::QuitCallBack ));CCMenu * backMenu = CCMenu::create(Again,End, NULL);backMenu->alignItemsVerticallyWithPadding(40);backMenu->setPosition(ccp(winSize.width / 2 - 10, winSize.height / 3 - 20));addChild(backMenu);}