使用cocos2d-js做一个ARPG游戏(3)

五、弹窗类

除了页面提示信息,还有各种功能需要弹窗,先完成弹窗的基础类Dialog,因为弹窗内还会出现按钮,同时还要引入之前的按钮类。

1
2
3
4
5
6
7
8
9
var
UIButton = require("../modules/button.js"),
Dialog = cc.Node.extend({
ctor: function(){
var self = this;
self._super();
self.addOutSideTouch();
}
});

然后需要实现addOutSideTouch方法,屏蔽掉弹窗以外的点击事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
...
Dialog = cc.Node.extend({
...
...
addOutSideTouch: function(){
var self = this;
cc.eventManager.addListener(cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan: self.onTouchBegan.bind(this),
onTouchEnded: self.onTouchEnded.bind(this)
}), this);
},
onTouchBegan: function(touch, event){
return true;
},
onTouchEnded: function(touch, event){
var
self = this,
touchPos = touch.getLocationInView(),
localPos = self.convertTouchToNodeSpace(touch),
box = self.getBoundingBox();
box.x = 0;
box.y = 0;
var isInside = cc.rectContainsPoint(box, localPos);
if(!isInside){
self.removeFromParent();
}
}
});

然后实现关闭按钮的相关功能,包括添加关闭按钮和关闭按钮的点击实现。添加这里图片使用的是统一的UI,各个dialog的关闭按钮位置交给各自去处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
...
Dialog = cc.Node.extend({
...
...
addCloseBtn: function(bg_sp, pos){
var self = this;
var btn = new UIButton();
btn.setAnchorPoint(0, 0);
btn.setPosition(pos);
btn.setLocalZOrder(30);
btn.init("btn_close_normal.png", "btn_close_touch.png", "btn_close_normal.png",self.onCloseBtn.bind(self));
bg_sp.addChild(btn);
},
onCloseBtn: function(){
var self = this;
self.removeFromParent();
}
});

然后需要实现dialog的显示,目前是在主界面声明弹窗容器dialog_layer,并实现showDialog方法。
1
2
3
4
5
6
7
8
9
10
11
...
...
showDialog: function(dialog){
var self = this;
var dialogSize = dialog.getContentSize();
dialog.setPosition(cc.p(
(cc.visibleRect.width - dialogSize.width) / 2,
(cc.visibleRect.height - dialogSize.height) / 2
));
self.dialog_layer.addChild(dialog);
}

六、衍生弹窗loading、alert

基于之前的dialog类,可以衍生出一些基础的loading和alert弹窗。添加弹窗背景并设置好弹窗的初始位置,为屏幕正中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var
Dialog = require("../dialog/dialog.js"),
PageAlert = Dialog.extend({
label: null,
ctor: function(){
var self = this;
self._super();
var bg_sp = cc.Scale9Sprite.createWithSpriteFrameName('pagealertbg.png', cc.rect(45, 36, 504, 46));
bg_sp.setContentSize(cc.size(582, 112));
bg_sp.setAnchorPoint(0, 0);
self.addChild(bg_sp);
self.setContentSize(bg_sp.getContentSize());
self.label = cc.LabelTTF.create("0");
self.label.setFontSize(26);
self.label.setColor(cc.color(226,177,98,255));
self.label.setPosition(cc.p(
bg_sp.getContentSize().width / 2,
bg_sp.getContentSize().height / 2
));
self.addChild(self.label);
}
});

再实现一个方法,来初始化loadingalert的容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PageAlert.createAlertLayer = function(){
var layer = cc.Layer.create();
layer.setLocalZOrder(20);
layer.setName("aler_layer");
return layer;
}
PageAlert.createLoadingLayer = function(){
var layer = cc.LayerColor.create(cc.color(0,0,0,128), cc.visibleRect.width, cc.visibleRect.height);
layer.setName("loading_layer");
layer.setVisible(false);
layer.setLocalZOrder(30);
cc.eventManager.addListener(cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan: function(){
return layer.isVisible();
},
}), layer);
return layer;
}

然后在主界面中可以使用初始化方法来生成容器
1
2
3
4
5
6
7
8
9
10
11
12
...
...
GameScene = cc.Scene.extend({
...
...
ctor: function(){
var aler_layer = PageAlert.createAlertLayer();
self.addChild(aler_layer);
var loading_layer = PageAlert.createLoadingLayer();
self.addChild(loading_layer);
}
});

最后实现alertloading的显示方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PageAlert.showAlert = function(text){
var alert_layer = cc.director.getRunningScene().getChildByName("aler_layer");
var dialog = new PageAlert();
dialog.label.setString(text);
dialog.setPosition(cc.p(
(cc.visibleRect.width - dialog.getContentSize().width) / 2,
(cc.visibleRect.height - dialog.getContentSize().height) / 2
));
alert_layer.addChild(dialog);
dialog.startTimer();
}
PageAlert.showLoading = function(){
var loading_layer = cc.director.getRunningScene().getChildByName("loading_layer");
loading_layer.setVisible(true);
}
PageAlert.hideLoading = function(){
var loading_layer = cc.director.getRunningScene().getChildByName("loading_layer");
loading_layer.setVisible(false);
}

由于alert使用的是定时关闭的逻辑,还需要实现一个计时器,来关闭alert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PageAlert = Dialog.extend({
...
...
startTimer: function(){
var self = this;
self.stopAllActions();
self.runAction(cc.sequence([
cc.delayTime(1.5),
cc.callFunc(function(){
if(self.getParent()){
self.removeFromParent();
}
}, self)
]));
}
});

然后就可以使用对应的方法来弹出loading或者alert了。
1
2
PageAlert.showAlert(error_msg);
PageAlert.showLoading();

在处理弹出框时,还有一个问题需要解决,如果页面使用了输入框input,因为input元素是覆盖在canvas之上的,那么需要在弹出框弹出时,隐藏掉所有的input。我是把这个方法放在了一个通用的类Util中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Util.prototype = {
...
...
hideAllInput: function(){
var ipts = document.querySelectorAll("input");
for(var i = 0, len = ipts.length; i < len; i++){
ipts[i].style.visibility = "hidden";
}
},
showAllInput: function(){
var ipts = document.querySelectorAll("input");
for(var i = 0, len = ipts.length; i < len; i++){
ipts[i].style.visibility = "visible";
}
}
};