用cocos2d-html5做的消除类游戏《英雄爱消除》(2)——Block设计实现
Block可以说是这个游戏的核心类,它除了包含自身的一些属性和方法外还添加了对触摸事件的响应。
我们先来看下源码吧
/** * Power by html5中文网(html5china.com) * author: jackyWHJ */ var Block = cc.Sprite.extend({ id:0, name:"", active:true, pointX:0, pointY:0, beginPoint:null, flash:false, ctor:function (arg) { this._super(); if(!arg)return; this.initWithSpriteFrameName(arg); this.name = arg; // cc.registerTargetedDelegate(0,true,this); cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, 0, true); }, //销毁隐藏 destroy:function () { var explosion =Explosion.getOrCreateExplosion(); explosion.setPosition(this.getPosition()); // SparkEffect.getOrCreateSparkEffect(this.getPosition()); if(LLK.SOUND){ cc.AudioEngine.getInstance().setMusicVolume(0.7); cc.AudioEngine.getInstance().playEffect(s_explodeEffect_mp3); } this.setVisible(false); this.active = false; LLK.COUNT --; if(LLK.COUNT <= 0/* || 1*/){ g_sharedGameLayer.onGameOver(); } }, //判断触摸点是否在图片的区域上 containsTouchLocation:function (touch) { //获取触摸点位置 var getPoint = touch.getLocation(); //物体当前区域所在的位置 var contentSize = this.getContentSize(); var myRect = cc.rect(0, 0, contentSize.width, contentSize.height); myRect.origin.x += this.getPosition().x; myRect.origin.y += this.getPosition().y; //判断点击是否在区域上 return cc.rectContainsPoint(myRect,getPoint); }, //刚触摸瞬间 onTouchBegan:function (touch, event) { if (!this.containsTouchLocation(touch)) return false; this.beginPoint = touch.getLocation(); // this.setZIndex(100); this.flash = true; this.setScale(1.2); return true; }, //触摸移动 onTouchMoved:function (touch, event) { if (!this.containsTouchLocation(touch)) return false; var touchPoint = touch.getLocation(); var xDist = touchPoint.x - this.beginPoint.x,yDist = touchPoint.y - this.beginPoint.y; //移动距离超过10个像素位才有效 if((Math.abs(xDist) >= 10 || Math.abs(yDist) >= 10)&&this.flash){ this.flash = false; var block = this; if(Math.abs(xDist) > Math.abs(yDist)){ if(xDist > 0){this.moveRight(block);} else{this.moveLeft(block);} } else{ if(yDist > 0){this.moveUp(block);} else{this.moveDown(block);} } return false; } }, onTouchEnded:function(touch,event){ this.setScale(1); this.flash = true; }, moveLeft:function(block){ if(block.pointX == 0)return; var leftBlock = Block.getBlock(block.pointX - 1,block.pointY); if(leftBlock){ leftBlock.pointX = block.pointX; leftBlock.setPosition(block.pointX*60,block.pointY*60+30); leftBlock.checkTheSame(); } block.pointX --; block.setPosition(block.pointX*60,block.pointY*60+30); block.checkTheSame(); }, moveRight:function(block){ if(block.pointX == LLK.LEVEL.x - 1)return; var rightBlock = Block.getBlock(block.pointX + 1,block.pointY); if(rightBlock){ rightBlock.pointX = block.pointX; rightBlock.setPosition(block.pointX*60,block.pointY*60+30); rightBlock.checkTheSame(); } block.pointX ++; block.setPosition(block.pointX*60,block.pointY*60+30); block.checkTheSame(); }, moveUp:function(block){ if(block.pointY == LLK.LEVEL.y - 1)return; var upBlock = Block.getBlock(block.pointX,block.pointY+1); if(upBlock){ upBlock.pointY = block.pointY; upBlock.setAnchorPoint(cc.p(0, 0)); upBlock.setPosition(block.pointX*60,block.pointY*60+30); upBlock.checkTheSame(); } block.pointY ++; block.setPosition(block.pointX*60,block.pointY*60+30); block.checkTheSame(); }, moveDown:function(block){ if(block.pointY == 0)return; var downBlock = Block.getBlock(block.pointX,block.pointY - 1); if(downBlock){ downBlock.pointY = block.pointY; downBlock.setPosition(block.pointX*60,block.pointY*60+30); downBlock.checkTheSame(); } block.pointY --; // block.setAnchorPoint(cc.p(0, 0)); block.setPosition(block.pointX*60,block.pointY*60+30); block.checkTheSame(); }, checkTheSame:function(){ this.checkLeft() || this.checkUp()||this.checkRight()||this.checkDown(); }, checkLeft:function(){ if(this.pointX == 0)return false; var leftBlock = Block.getBlock(this.pointX - 1,this.pointY); if(leftBlock && leftBlock.name == this.name){ this.destroy(); leftBlock.destroy(); return true; } return false; }, checkRight:function(){ if(this.pointX == LLK.LEVEL.x - 1)return false; var rightBlock = Block.getBlock(this.pointX + 1,this.pointY); if(rightBlock && rightBlock.name == this.name){ this.destroy(); rightBlock.destroy(); return true; } return false; }, checkUp:function(){ if(this.pointY == LLK.LEVEL.y - 1)return false; var upBlock = Block.getBlock(this.pointX,this.pointY+1); if(upBlock && upBlock.name == this.name){ this.destroy(); upBlock.destroy(); return true; } return false; }, checkDown:function(){ if(this.pointY == 0)return false; var downBlock = Block.getBlock(this.pointX,this.pointY - 1); if(downBlock && downBlock.name == this.name){ this.destroy(); downBlock.destroy(); return true; } return false; } }); Block.getBlock = function(pointX,pointY) { for (var j = 0,len = LLK.map.length; j < len; j++) { if (LLK.map[j].active && pointX == LLK.map[j].pointX && pointY == LLK.map[j].pointY) { return LLK.map[j]; } } return null; };
首先我们先来看Block的几个重要属性:name是block的名字属性,用来判断相邻的block是不是同种类型,active是block是否存在界面上的标识,pointX,pointY是block的位置坐标。
接下来我们看构造方法ctor
ctor:function (arg) { this._super(); if(!arg)return; this.initWithSpriteFrameName(arg); this.name = arg; // cc.registerTargetedDelegate(0,true,this); cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, 0, true); },
构造方法中,使用initWithSpriteFrameName方法根据传进来的参数初始化sprite,同时,给sprite的name属性赋值,之后添加该sprite的触摸监听事件。
接下来看getBlock这个方法,它根据传入的坐标位置获取相对应的block,而获取的这个block前提是它的active属性为true,也就是获取到的是还存在界面上的block,不存在的话就返回null。
Block.getBlock = function(pointX,pointY) { for (var j = 0,len = LLK.map.length; j < len; j++) { if (LLK.map[j].active && pointX == LLK.map[j].pointX && pointY == LLK.map[j].pointY) { return LLK.map[j]; } } return null; };
onTouchBegan、onTouchMoved、onTouchEnded是对触摸事件的相应,在onTouchBegan和onTouchMoved中,我们需要先行判断当前的触点是否存在与sprite上,所有我们有了containsTouchLocation这个方法 ,在刚触摸的瞬间我们把sprite放大并且把当前的flash标识设置为true,这个flash标识是用来判断我们的触摸拖动是否已经结束(其实也应该可以不用这么做,但是我在调试中发现了个bug,所以就设置了这个标识),而在onTouchMoved中,我们根据拖动的位移判断当前是往那个方向移动,然后移动Block。移动结束后,我们在onTouchEnded把Block的大小还原。
//判断触摸点是否在图片的区域上 containsTouchLocation:function (touch) { //获取触摸点位置 var getPoint = touch.getLocation(); //物体当前区域所在的位置 var contentSize = this.getContentSize(); var myRect = cc.rect(0, 0, contentSize.width, contentSize.height); myRect.origin.x += this.getPosition().x; myRect.origin.y += this.getPosition().y; //判断点击是否在区域上 return cc.rectContainsPoint(myRect,getPoint); }, //刚触摸瞬间 onTouchBegan:function (touch, event) { if (!this.containsTouchLocation(touch)) return false; this.beginPoint = touch.getLocation(); // this.setZIndex(100); this.flash = true; this.setScale(1.2); return true; }, //触摸移动 onTouchMoved:function (touch, event) { if (!this.containsTouchLocation(touch)) return false; var touchPoint = touch.getLocation(); var xDist = touchPoint.x - this.beginPoint.x,yDist = touchPoint.y - this.beginPoint.y; //移动距离超过10个像素位才有效 if((Math.abs(xDist) >= 10 || Math.abs(yDist) >= 10)&&this.flash){ this.flash = false; var block = this; if(Math.abs(xDist) > Math.abs(yDist)){ if(xDist > 0){this.moveRight(block);} else{this.moveLeft(block);} } else{ if(yDist > 0){this.moveUp(block);} else{this.moveDown(block);} } return false; } }, onTouchEnded:function(touch,event){ this.setScale(1); this.flash = true; },
而在我们移动方块后,我们需要判断发生位移的方块是否在上下左右4个方向上存在相同的方块,这个通过checkTheSame来实现,具体看源码
checkTheSame:function(){ this.checkLeft() || this.checkUp()||this.checkRight()||this.checkDown(); },
之后是相同的方块销毁隐藏
//销毁隐藏 destroy:function () { var explosion =Explosion.getOrCreateExplosion(); explosion.setPosition(this.getPosition()); // SparkEffect.getOrCreateSparkEffect(this.getPosition()); if(LLK.SOUND){ cc.AudioEngine.getInstance().setMusicVolume(0.7); cc.AudioEngine.getInstance().playEffect(s_explodeEffect_mp3); } this.setVisible(false); this.active = false; LLK.COUNT --; if(LLK.COUNT <= 0/* || 1*/){ g_sharedGameLayer.onGameOver(); } },
在该方法中,我们隐藏Block并且在Block的位置添加爆炸效果然后播放音效,之后,我们的Block总计数减1,然后在计数为0的时候游戏结束,调用主程序的onGameOver方法结束游戏。