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

三、人物角色

先创建人物对象,设置默认状态为站立。

1
2
3
4
5
6
7
8
9
10
11
12
13
var
Player = cc.Node.extend({
ctor: function(){
var self = this;
self._super();

self.bodySp = cc.Sprite.create();
self.bodySp.setAnchorPoint(0.5, 0);
self.addChild(self.bodySp);

self.setPlayerStatus("idel");
}
});

然后实现setPlayerStatus方法,根据角色的朝向和状态,执行对应的角色动画。但还要先判断一下,当前的状态与之前的状态是否相同,相同状态下,是不能执行动画,不然就会出现连续跑动的过程中,人物动画反复从第一帧开始的情况。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var
Player = cc.Scene.extend({
...
...
setPlayerStatus: function(status){
var
self = this,
dirction = self.dircetion;
self.playerStatus = status;
if(self.hisPlayerStatus != self.playerStatus || self.hisDircetion != dirction){
self.bodySp.stopActionByTag(self.playerSpPlayActionTag);
var playerAnimation = PlayerCache.getInstance().getPlayerAnimation(dirction, self.playerStatus);
var playerAction = self.bodySp.runAction(cc.RepeatForever.create(cc.Animate.create(playerAnimation)));
playerAction.setTag(self.playerSpPlayActionTag);
self.hisPlayerStatus = self.playerStatus;
self.hisDircetion = dirction;
}
}
});

之后再实现Player的moveTo方法,接收三个参数,角色起始位置、路径经过位置集合和回调,然后根据路径集合构建action所需要的数组。
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
32
33
34
35
var
Player = cc.Scene.extend({
...
...
moveTo: function(place, paths, callback){
place = mapObject.getBlockXY(place);
var
self = this,
times = self.getMoveTime(place),
moveact = [];
self.stopAllActions();
for(var i in paths){
var lastblock = paths[i - 1] || mapObject.getBlockXY(self.getPosition());
var pdircet = self.checkDirection(lastblock, paths[i]);
self.dircetion = pdircet;
var playerDircetChange = (function(player, thedir){
return cc.CallFunc.create(function(){
player.setDircetion(thedir);
player.setPlayerStatus("move");
})
})(self, pdircet);
moveact.push(playerDircetChange);
moveact.push(cc.moveTo(times, mapObject.getBlockCenter(paths[i])));
moveact.push(cc.CallFunc.create(function(){
self.setPlayerZOrder();
}));
}
moveact.push(cc.CallFunc.create(function(){
if(!!callback && typeof callback == "function"){
callback();
}
}));
self.runAction(cc.sequence(moveact));
}
});

针对要移动的路径的每一步,先根据当前位置点和上一个位置点,调整人物朝向,然后移动,移动后调整人物的Z轴,全部移动完后执行回调函数。这里调整朝向的时候,要创造一个闭包,来让朝向的参数确定下来。

人物的Z轴调整依据的是人物的Y轴大小,对整个地图而言,越靠下的人物,Z轴层级越高。

1
2
3
4
5
6
7
8
9
10
11
var
Player = cc.Scene.extend({
...
...
setPlayerZOrder: function(){
var
self = this,
j = (mapObject.mapYlen - (mapObject.getBlockXY(self.getPosition()))["y"]) * 32;
self.setLocalZOrder(j);
}
});

四、按钮类

UI部分还需要各种的按钮,可以先创建一个Button类,实现基础功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var
UIButton = cc.Node.extend({
ctor: function(){
var self = this;
self._super();
self.btnSp = cc.Sprite.create();
self.btnSp.setAnchorPoint(0, 0);
self.addChild(self.btnSp);
}
});
UIButton.create = function(nomal_img, touch_img, disabled_img, cb){
var btn = new UIButton();
btn.init(nomal_img, touch_img, disabled_img, cb)
return btn;
};
module.exports = UIButton;

类自身提供构造方法,返回按钮对象,通过init方法初始化。init方法的实现如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var
UIButton = cc.Node.extend({
...
...
init: function(nomal_img, touch_img, disabled_img, cb){
var self = this;
if(!!cb && typeof cb == "function"){
self.disabled_img = disabled_img;
}else{
cb = disabled_img;
}
self.nomal_img = nomal_img;
self.touch_img = touch_img;
self.cb = cb;
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);
self.showNomal();
}
});

再实现touch的相关方法
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
32
var
UIButton = cc.Node.extend({
...
...
onTouchBegan: function(touch, event){
var self = this;
var touchPos = touch.getLocationInView();
var localPos = self.convertTouchToNodeSpace(touch);
var box = self.getBoundingBox();
var target = event.getCurrentTarget();
box.x = 0;
box.y = 0;
if(!target.visible){
return false;
}
var isInside = cc.rectContainsPoint(box, localPos);
if(!isInside){
return false;
}
if(!self.btn_disabled){
self.showTouch();
}
return true;
},
onTouchEnded: function(touch, event){
var self = this;
if(!self.btn_disabled){
self.showNomal();
self.cb();
}
}
});

只能在按钮可见,并且点击在按钮上时,且此按钮的状态为可用,才执行按钮回调方法。同时,在按下和抬起的时候,还要切换按钮的图片效果。