我们先来考虑一下这个PrefabManager是干什么的,我们的游戏中有重复出现的水管和老公,所以PrefabManager要能够动态管理他们,理所当然要有创建和销毁的方法,创建很简单,我们只需要每隔一段距离往pipeLayer添加子节点就行了,但销毁它们还是需要一些技巧的,从逻辑角度来说,当水管和老公移动到屏幕外时我们就要将他们销毁,这里我们用一个普通班不会教的方法——利用碰撞检测系统
我们先给PrefabManager添加一个碰撞组件,编辑如图
给水管兄弟添加碰撞组件,设置tag为333
给水管哥哥添加碰撞组件,设置tag为3331
给水管弟弟添加碰撞组件,设置tag也为3331
给老公添加碰撞组件,设置tag为666
PrefabManager.js
cc.Class({
extends: cc.Component,
properties: {
pipeGroupPre:cc.Prefab,
starPre:cc.Prefab,
pipeLayer:cc.Node,
//上下管子之间距离范围
spacingRange: cc.p(0,0),
// 下面管子Y轴偏移量范围
botYRange: cc.p(0,0),
// 左右管子之间距离
pipeSpace:0,
//第一个管子位置
oPipeX:0,
//星星位置范围
starYRange:cc.p(0,0),
},
init: function (game) {
this.game = game;
this.pipePool = new cc.NodePool();
this.starPool = new cc.NodePool();
for(var i=0;i<4;i++){
this.pipePool.put(cc.instantiate(this.pipeGroupPre));
this.starPool.put(cc.instantiate(this.starPre));
}
this.curPipeX = this.oPipeX;//当前管子位置
this.spawnPipe();
this.spawnPipe();
cc.director.getCollisionManager().enabled = true;
},
onCollisionEnter: function(other,self){
if(other.tag === 333){
this.desPipe(other.node);
}else if(other.tag === 666){
this.desStar(other.node);
}
},
spawnPipe: function(){
var pipeGroup = this.pipePool.get();
var pipeTop = pipeGroup.getChildByName("PipeTop");
var pipeBot = pipeGroup.getChildByName("PipeBot");
var botYPos = this.botYRange.x + Math.random() * (this.botYRange.y - this.botYRange.x);
var space = this.spacingRange.x + Math.random() * (this.spacingRange.y - this.spacingRange.x);
var topYPos = botYPos + space;
pipeTop.y = topYPos;
pipeBot.y = botYPos;
pipeGroup.x = this.curPipeX;
this.pipeLayer.addChild(pipeGroup);
this.spawnStar();
this.curPipeX += this.pipeSpace;
},
desPipe: function(node){
this.pipePool.put(node);
this.spawnPipe();
},
spawnStar: function(){
if(Math.random() < 0.8){
var star = this.starPool.get();
star.y = this.starYRange.x + Math.random()*(this.starYRange.y - this.starYRange.x);
star.x = this.curPipeX + this.pipeSpace/2;
this.pipeLayer.addChild(star);
}
},
desStar: function(node){
this.starPool.put(node);
},
});
按照惯例,我们从上往下看
在属性中我们定义了需要用到的两个Prefab和一个pipeLayer节点,还有一些随机设置Prefab的参数(这里用二维的点来表示范围,x是最小值,y是最大值)
第一个管子的位置要在屏幕外
在init方法里我们定义了两个cc.NodePool,分别存放pipeGroup和star
最后排的那位同学问了一个问题”为什么要用NodePool,直接用instantiate复制和destroy销毁不就行了么?”
老师很表扬这种勇于提问的表现,但也要批评这位同学不好好预习的行为
现在我们来翻一下官方文档
“记住了吗”
“记住了”
屏幕里最多出现两个水管,因为人生难免有意外,所以我们在pool里放四个,
当prefab滚到屏幕外的回收区时,我们就把它放回pool里,这样就可以实现一个良性循环,毕竟全球变暖了,话说今年好像比去年热了,话说我好像跑题了。。。
每添加一个pipeGroup我们就要调用一次spawnStar方法,但老公不是一个随便的人,所以我们要给他添加一个出现的概率,0.8吧,毕竟老公是我们这个游戏的唯一吸引力。。。
最后我们要在Game.js里初始化PrefabManager
var Player = require("Player");
var CameraManager = require("CameraManager");
var PrefabManager = require("PrefabManager");
cc.Class({
extends: cc.Component,
properties: {
player:Player,
cameraManager:CameraManager,
prefabManager:PrefabManager,
},
onLoad: function () {
//返回键返回菜单
cc.eventManager.addListener({
event: cc.EventListener.KEYBOARD,
onKeyPressed: function(keyCode, event) {
if(keyCode == cc.KEY.back){
cc.director.loadScene('Menu');
}
}
}, this.node);
this.startGame();
},
startGame: function(){
this.cameraManager.init(this);
this.prefabManager.init(this);
this.player.init(this);
},
stopGame: function(){
},
gainScore: function(){
},
gainEnergy:function(){
},
});
看一下效果