cocos2dx CrystalCraze 宝石消除游戏 解析(二)

上一篇:cocos2dx CrystalCraze 宝石消除游戏 解析(一)

上一篇介绍了 mainScene界面,下面进入正题,GameScne界面!会比较长,毕竟1000行代码啊,耐心看下吧

2 GameScene.js

     这才是游戏界面的主要控制代码,一看1000行代码,啥也不说了,慢慢看吧… 

    界面还是从onDidLoadFromCCB 开始

//开始游戏
GameScene.prototype.onDidLoadFromCCB = function()
{// 初始化面板 各种数组setupBoard();//游戏是否结束 是否显示提示gIsGameOver = false;gIsDisplayingHint = false;//浏览器设置可以 鼠标控制if( sys.platform == 'browser')this.rootNode.setMouseEnabled( true );// 触摸事件 跟鼠标事件this.rootNode.onTouchesBegan = function( touches, event) {this.controller.onTouchesBegan(touches, event);return true;};this.rootNode.onMouseDown = function( event) {this.controller.onMouseDown(event);return true;};// Setup timer 进度条this.sprtTimer.setVisible(false);gTimer = cc.ProgressTimer.create(cc.Sprite.create("gamescene/timer.png"));gTimer.setPosition(this.sprtTimer.getPosition());gTimer.setPercentage(100);gTimer.setType(cc.PROGRESS_TIMER_TYPE_BAR);gTimer.setMidpoint(cc.p(0, 0.5));gTimer.setBarChangeRate(cc.p(1, 0));this.sprtHeader.addChild(gTimer);//这是最后的点击时间,连击的个数,是否是炸弹,是否快没有时间var dNow = Date.now();gStartTime = dNow + kIntroTime;gLastMoveTime = dNow;gNumConsecutiveGems = 0;gIsPowerPlay = false;gEndTimerStarted = false;gScore = 0;// 没帧刷新onUpdate方法this.rootNode.onUpdate = function(dt) {this.controller.onUpdate();};this.rootNode.schedule(this.rootNode.onUpdate);//判断平台,设置GameLayerif ("opengl" in sys.capabilities && "browser" != sys.platform){cc.log("OpenGL rendering");gParticleLayer = cc.ParticleBatchNode.create("particles/taken-gem.png", 250);gGameLayer = cc.SpriteBatchNode.create("crystals.pvr.ccz");}else{cc.log("WebGL or Canvas rendering");gParticleLayer = cc.Node.create();gGameLayer = cc.Node.create();}gGameLayer.setContentSize(this.gameLayer.getContentSize());//gParticleLayer = cc.ParticleBatchNode.create("particles/taken-gem.png", 250);//gParticleLayer = cc.Node.create();gHintLayer = cc.Node.create();gShimmerLayer = cc.Node.create();gEffectsLayer = cc.Node.create();//设置各界面层级关系this.gameLayer.addChild(gShimmerLayer, -1);this.gameLayer.addChild(gParticleLayer, 1);this.gameLayer.addChild(gGameLayer, 0);this.gameLayer.addChild(gHintLayer, 3);this.gameLayer.addChild(gEffectsLayer, 2);//gGameLayer = this.gameLayer;// 设置完成动画后回调this.rootNode.animationManager.setCompletedAnimationCallback(this, this.onAnimationComplete);//背景上面 那个条半透明 紫色条状图片 的旋转,移动 淡入淡出效果setupShimmer();//setupSparkle();// 分数控件gScoreLabel = this.lblScore;
};

function setupBoard()
{//游戏面板 存放宝石种类 初始化[80] var kBoardWidth = 8;//var kBoardHeight = 10;//var kNumTotalGems = kBoardWidth * kBoardHeight;gBoard = new Array(kNumTotalGems);for (var i = 0; i < kNumTotalGems; i++){gBoard[i] = -1;}//游戏精灵面板gBoardSprites = new Array(kNumTotalGems);//竖着的8列宝石数组gNumGemsInColumn = new Array(kBoardWidth);//当前时间每一列的位置gTimeSinceAddInColumn = new Array(kBoardWidth);var x;for (x = 0; x < kBoardWidth; x++){	//初始化为0gNumGemsInColumn[x] = 0;gTimeSinceAddInColumn[x] = 0;}// 初始化下落宝石二维数组gFallingGems = new Array(kBoardWidth);for (x = 0; x < kBoardWidth; x++){gFallingGems[x] = new Array(0);}//评估是否有可以消除的宝石 和默认可以消除的宝石位置 gBoardChangedSinceEvaluation = true;gPossibleMove = -1;
}


下面是整个游戏的重点 onUpdate方法

// Game main loop
GameScene.prototype.onUpdate = function(dt)
{//如果游戏没有结束if (!gIsGameOver){//删除各列已被消除连接着的宝石 并把它上面加入到gFallingGemsremoveMarkedGems();var x;var gem;// Add falling gemsfor (x = 0; x < kBoardWidth; x++){//当这一列中的个数+要下落的个数<10 && 在当前列的位置>=8 if (gNumGemsInColumn[x] + gFallingGems[x].length < kBoardHeight &&gTimeSinceAddInColumn[x] >= kTimeBetweenGemAdds){//每一列增加一个随机宝石位置在界面的顶部,但yPos设为kBoardHeight = 10 并加入到gFallingGems  var kGemSize = 40; var gemType = Math.floor(Math.random()*5);var gemSprite = cc.Sprite.createWithSpriteFrameName("crystals/"+gemType+".png");gemSprite.setPosition(x * kGemSize, kBoardHeight * kGemSize);gemSprite.setAnchorPoint(0,0);gem = {gemType: gemType, sprite: gemSprite, yPos: kBoardHeight, ySpeed: 0};gFallingGems[x].push(gem);gGameLayer.addChild(gemSprite);gTimeSinceAddInColumn[x] = 0;}gTimeSinceAddInColumn[x]++;}// Move falling gemsvar gemLanded = false;for (x = 0; x < kBoardWidth; x++){var column = gFallingGems[x];var numFallingGems = gFallingGems[x].length;//遍历这一列中需要下降的宝石for (var i = numFallingGems-1; i >= 0; i--){gem = column[i];//每次宝石 下降一定高度gem.ySpeed += 0.06;gem.ySpeed *= 0.99;gem.yPos -= gem.ySpeed;//如果宝石y坐标<=该列宝石个数时,证明已经到达了底部或碰到了宝石if (gem.yPos <= gNumGemsInColumn[x]){// 随机播放一个音效if (!gemLanded){gAudioEngine.playEffect("sounds/tap-"+Math.floor(Math.random()*4)+".wav");gemLanded = true;}//从gFallingGems中删除该宝石column.splice(i, 1);//插入该宝石到面板中 宝石类型到gBoard srite到gBoardSpritesvar y = gNumGemsInColumn[x];if (gBoard[x + y*kBoardWidth] != -1){cc.log("Warning! Overwriting board idx: "+x + y*kBoardWidth+" type: "+gBoard[x + y*kBoardWidth]);}gBoard[x + y*kBoardWidth] = gem.gemType;gBoardSprites[x + y*kBoardWidth] = gem.sprite;//更新宝石位置 和该列中宝石的个数gem.sprite.setPosition(x*kGemSize, y*kGemSize);gNumGemsInColumn[x] ++;//全部插满可以消除gBoardChangedSinceEvaluation = true;}else{// 更新宝石下落位置gem.sprite.setPosition(x*kGemSize, gem.yPos*kGemSize);}}}// Check if there are possible moves and no gems fallingvar isFallingGems = false;for (x = 0; x < kBoardWidth; x++){if (gNumGemsInColumn[x] != kBoardHeight){isFallingGems = true;break;}}//当全部下落完毕if (!isFallingGems){//遍历所有位置上的宝石,检查是否存在3个以上相连的宝石,并返回坐标var possibleMove = findMove();if (possibleMove == -1){// 如果没有可以消除的,随机选各位置,并把它右面和上面的变成相同图案createRandomMove();}}// Update timervar currentTime = Date.now();var elapsedTime = (currentTime - gStartTime)/kTotalGameTime;var timeLeft = (1 - elapsedTime)*100;if (timeLeft < 0) timeLeft = 0;if (timeLeft > 99.9) timeLeft = 99.9;gTimer.setPercentage(timeLeft);// 更新两次消除的间隔时间 如果大于1秒 重置if (currentTime - gLastMoveTime > kMaxTimeBetweenConsecutiveMoves){gNumConsecutiveGems = 0;}//更新炸弹粒子状态updatePowerPlay();//随机在宝石上增加闪耀的星星updateSparkle();// 时间小于6.6播放倒计时音效if (timeLeft < 6.6 && !gEndTimerStarted){gAudioEngine.playEffect("sounds/timer.wav");gEndTimerStarted = true;}//没有时间则游戏结束if (timeLeft === 0){//界面内剩余的全部宝石 x,y随机一个速度 createGameOver();//执行动画 (会有个回调,前面设置的onAnimationComplete)this.rootNode.animationManager.runAnimationsForSequenceNamed("Outro");gIsGameOver = true;//gAudioEngine.stopAllEffects();cc.log("stopAllEffects not working!");gAudioEngine.playEffect("sounds/endgame.wav");gLastScore = gScore;}else if (currentTime - gLastMoveTime > kDelayBeforeHint && !gIsDisplayingHint){displayHint();//大于3秒提示相连的宝石}}else{//结束宝石数组更新位置updateGameOver();}
};

     这样游戏一开始就可以一排排的落下来,直到填满整个游戏,序列大概如图所示:

: : : 79
: : : :
8 9 .. ..
0 1 .. 7

Published by

风君子

独自遨游何稽首 揭天掀地慰生平