演示视频地址:点击打开链接 (注 : 视频中两次使用炸弹,没有很好的感应,因为阈值设定有点问题,已改)
游戏的源码也上传到了 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 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);
}