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

Cocos2dx微信打飞机体感游戏

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

游戏的源码也上传到了 csdn 50下载积分 , 但同时也上传到了Github,来个star吧,免费下载:

https://github.com/tanlichun211/SomaticGame-WeChat_PlanWars

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.016
	schedule(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 enemySmall
	CCRect 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 enemyMid
	CCARRAY_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 enemyBig
	CCARRAY_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 hero

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





    

猜你喜欢

转载自blog.csdn.net/qq_34609108/article/details/78082849