这是我第一次接触Cocos Cretor,博主之前学的是Unity3D开发,由于U3D的工作不怎么好找所以博主打算转2D。这也是我学Cocos Creator的第二天就面试上的公司,也是我的第一个项目。写的不好的地方希望大家多多包涵。
这个游戏是“最强灌篮大作战”,由于之前没写过类似的游戏,所以在我接触到这个项目时感觉亚历山大。不过在我每天加班加点的学习过程中,程序已经渐渐成型。虽然在很多的地方稍有不足。
第一步,先创建一个Cocos Cretor的项目,如图:
第二步,按照程序的设计样板,编辑相应的界面。
这里简单说一下,此类游戏的重点,是设置它的物理,碰撞等系统。在这个游戏里,博主为了防止篮球被弹出屏幕,楼主把游戏界面做成了盒子。
盒子的组成属性如上图,添加方法:点击添加组件=>物理=>Collider =>box。
即可完成所有盒子的添加。
第三步,物理组建的添加怎么可能少了篮球呢。篮球的物理大部分和盒子的物理类似,只是部分数据不同。请看图。
哦对了,物理和碰撞系统默认情况下是关闭的。所以如果要使用首先得开启物理系统和碰撞系统。
Game.js: onLoad()
这里还要补充一点的是设置蓝板框,因为大部分的物理检测都是在蓝板上
如图,在篮板上我添加了四个物理碰撞,首先是蓝板(防止球穿过篮板),其次是在进球的筐,让球能够从两个物理点进球(也是为了防止篮球穿过球筐),第四个点是用来检测球是否进筐。当球与该点接触,即进球。计分器加一。接触判断需要添加组。
第四步,物理设置好了接下来就是控制篮球的方向,及点击跳动了。我这里就直接粘贴代码了。我把触摸写在了Canvas上也就是Game脚本上。然后调用控制Player节点。
Game.js
cc.Class({
extends: cc.Component,
properties: {
//player 节点,用于获取主角弹跳的高度,控制主角行动
player: {
default: null,
type: cc.Node
},
//更新分数的Label
ScoreLabel: {
default: null,
type: cc.Label
},
},
onLoad () {
//开启冲力,感觉没啥用
cc.director.getPhysicsManager().enabled = true;
cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
// cc.PhysicsManager.DrawBits.e_pairBit |
// cc.PhysicsManager.DrawBits.e_centerOfMassBit |
cc.PhysicsManager.DrawBits.e_jointBit |
cc.PhysicsManager.DrawBits.e_shapeBit;
cc.director.getPhysicsManager().debugDrawFlags = 0;
/*==========================开启碰撞检测系统==========================*/
var manager = cc.director.getCollisionManager();
manager.enabled = true;
/*==========================开启物理碰撞==========================*/
this.physicsManager = cc.director.getPhysicsManager();
this.physicsManager.enabled = true;
/*==========================触摸监听==========================*/
this.node.on(cc.Node.EventType.TOUCH_START,function(touch){
//角色绑定控件
var hero = this.player.getComponent("Player");
//实现onTouchBegan事件回调函数
cc.log(touch)
var touchLocX = touch.getLocation().x;
if(touchLocX < cc.winSize.width/2) {
hero.node.runAction(hero.setJumpRightUpAction());//精灵跳跃
}
else if (touchLocX > cc.winSize.width/2) {
hero.node.runAction(hero.setJumpLeftUpAction());//精灵跳跃
}
cc.log("touchLocX: " + touchLocX );
//hero.node.runAction(hero.setJumpUpAction());//精灵跳跃
}, this);
},
/*=================================================================Update=================================================================*/
update (dt) {
this.ScoreLabel.string = ' ' + G_Score;
},
});
上图中player就是篮球的组件。写惯了U3D,所以我就懒的用代码获取组件了。听说
Cocos Creator的开发者和U3D的开发者是同一个人。难怪我怎么感觉使用起来很熟悉呢。
/*====================================================================*/
Player.js
cc.Class({
extends: cc.Component,
properties: {
/*======球体的影子======*/
Ball_2 : {
default: null,
type: cc.Node
},
/*======分数特效实体======*/
ScorePrefab: {
default: null,
type: cc.Prefab
},
/*======蓝板框左======*/
BasketMoveLeft: {
default: null,
type: cc.Node
},
/*======蓝板框右======*/
BasketMoveRight: {
default: null,
type: cc.Node
},
//主角跳跃持续时间
jumpTime:1,
//主角跳跃高度
jumpHeight:200,
//掉落速度
maxMoveSpeed:1,
//球的左右移动大小
xSpeed: 150,
accel:1
},
/*==================================================================================================================================================== */
//球体上跳
setJumpUpAction:function(){
// this.jumpHeight = 200;
//向上跳动
var jumpUp = cc.moveBy(this.jumpTime, cc.p(0,this.jumpHeight)).easing(cc.easeCubicActionOut());
return jumpUp;
},
//球体右上角跳
setJumpRightUpAction:function(){
// this.jumpHeight = 200;
//向上跳动
var rotate = cc.rotateBy(1, -720);
cc.log("xSpeed = " + this.xSpeed);
var jumpUp = cc.moveBy(this.jumpTime, cc.p(-this.xSpeed,this.jumpHeight)).easing(cc.easeCubicActionOut());
return cc.spawn(rotate , jumpUp);
},
//球体左上角跳
setJumpLeftUpAction:function(){
//向上跳动
var rotate = cc.rotateBy(1, 720);
cc.log("xSpeed = " + this.xSpeed);
var jumpUp = cc.moveBy(this.jumpTime, cc.p(this.xSpeed,this.jumpHeight)).easing(cc.easeCubicActionOut());
return cc.spawn(rotate , jumpUp);
},
//掉落
setJumpDownAction: function(){
var jumpDown = cc.moveBy(this.jumpTime, cc.p(0,this.jumpHeight)).easing(cc.easeCubicActionIn());
return jumpDown;
},
setJumpRunAction:function(){
//初始化跳跃动作
this.jumpAction = this.setJumpUpAction();
//掉落动作
this.maxMoveSpeed = this.setJumpDownAction();
var seq = cc.sequence(this.jumpAction, this.maxMoveSpeed);
this.node.runAction(seq);
},
BallDownMove:function(){
//下落
var heroDown = cc.moveBy(0.8, cc.p(0, -5));
return heroDown;
},
// ScoreLabelAction: function() {
// this.ScoreLabel.active = true;
// var moveby = this.ScoreLabel.runAction(cc.moveBy(1, cc.p(0,50)));
// var Score = this.ScoreLabel.runAction(cc.fadeOut(1));
// var calfun = cc.callFunc(function(){
// this.ScoreLabel.active = false;
// this.ScoreLabel.opacity = 255;
// this.ScoreLabel.runAction(cc.fadeIn(0));
// }, this);
// var seq = cc.sequence( moveby, Score, calfun);
// this.ScoreLabel.runAction(seq);
// },
//蓝板框前进移动特效
Basket_MoveIn: function(){
var PosY = (cc.random0To1() * 350) - 200;
this.BasketMoveLeft.setPosition(-255, PosY);
this.BasketMoveRight.setPosition(445, PosY);
G_Temp = 1;
},
//蓝板框回退移动特效
Basket_MoveBack: function(){
var PosY = (cc.random0To1() * 350) - 200;
this.BasketMoveLeft.setPosition(-455, PosY);
this.BasketMoveRight.setPosition(255, PosY);
G_Temp = -1;
},
//碰撞系统回掉
onBeginContact: function (contact, selfCollider, otherCollider) {
if( (otherCollider.node.groupIndex == 2) ){
var pref = cc.instantiate(this.ScorePrefab);
pref.parent = this.node.parent;
var Vecx = this.node.getPositionX();
var Vecy = this.node.getPositionY();
console.log("Vecx: " + Vecx);
console.log("Vecy: " + Vecy);
//node.convertToNodeSpaceAR(cc.v2(100, 100));
pref.setPosition(Vecx,Vecy + 100);
/*======= 分数实体化运动轨迹特效 =======*/
var moveby = pref.runAction(cc.moveBy(2, cc.p(0,50)));
var Score = pref.runAction(cc.fadeOut(2.0));
var seq = cc.spawn( moveby, Score);
//pref.runAction(cc.fadeIn(1.0));
pref.runAction(seq);
/*======= 球进篮计分器+1 =======*/
G_Score = G_Score + 1;
/*======重置时间进度条======*/
this.Prog.progress = 1;
// if (G_Temp == 1) {
// this.Basket_MoveBack();
// }else if (G_Temp == -1) {
// this.Basket_MoveIn();
// }
/*=====延迟一秒执行下列函数=====*/
this.scheduleOnce(function() {
pref.removeFromParent();
console.log("111111111111");
}.bind(this), 1);
}
},
/*==================================================================================================================================================== */
// use this for initialization
onLoad: function () {
//cc.log("X: ");
G_Temp = 1;
G_Score = 0;
/*=========================进一球,得一分,时间重置========================= */
this.Bar = cc.find("Canvas/ProgressBarTest");
this.Prog = this.Bar.getComponent(cc.ProgressBar);
/*=========================调用运动函数=========================*/
this.setJumpRunAction();
// 主角当前水平方向速度
this.xSpeed = 50;
},
//
update: function (dt) {
/*=========================设置篮球的影子跟随篮球运动=========================*/
this.Ball_2.setPosition(cc.v2( this.node.x , -480));
//精灵下落移动
this.node.runAction(this.BallDownMove());
},
});
介绍一下,Ball_2 是篮球的影子组建。因为在游戏中需要使用篮球的影子使游戏更加逼真,所以我这里直接使用。
ScorePrefab 是加分特效,这里我做成了Prefab。BasketMove是我之前打算做的篮板框随机产生位置。因为出现了BUG到目前还没解决,所以我打算放一边。其他的属性请看代码注释吧。
progressBar是进度条的设置,我这边是用来控制游戏的时间的。这里主要的属性是progress,只要调整progress的大小就可以控制进度条的加载了。当进度条为0时,代表游戏结束,将会弹出结算界面。具体请看代码:
ProgressBarTest.js
cc.Class({
extends: cc.Component,
properties: {
speed: 0.1,
horizontalBarReverse: {
default: null,
type: cc.ProgressBar
},
},
// LIFE-CYCLE CALLBACKS:
onLoad: function () {
//this.horizontalBarReverse.progress = 1;
//this.game = this.node.parent.getComponent('game');
},
start: function () {
this.horizontalBarReverse.progress = 1;
},
update: function (dt){
this._updateProgressBar(this.horizontalBarReverse, dt);
},
_updateProgressBar: function(progressBar, dt){
var progress = progressBar.progress;
this._pingpong = progress >= 0;
if(progress > 0 && this._pingpong){
progress -= dt * this.speed;
}
else {
// //游戏时间到弹出游戏结算界面
cc.director.preloadScene("SettlementScene");
cc.director.loadScene("SettlementScene");
}
progressBar.progress = progress;
},
});
ButtonEvent.js专门用来设置按钮的一些操作的。
cc.Class({
extends: cc.Component,
properties: {
ScoreLabel: {
default: null,
type: cc.Label
},
},
// LIFE-CYCLE CALLBACKS:
// onLoad () {},
start () {
},
update (dt) {
/*=========================更新界面的分数=========================*/
this.ScoreLabel.string = ' ' + G_Score;
},
/*=========================按钮事件=========================*/
ClickEvent(event, customEventData) {
switch (Math.floor(customEventData)) {
case 0:
//继续游戏
cc.director.preloadScene("Dunk");
cc.director.loadScene("Dunk")
break;
case 1:
//返回主界面
cc.director.preloadScene("Start");
cc.director.loadScene("Start")
break;
case 2:
console.log("好友接力");
break;
case 3:
console.log("邀请好友挑战");
break;
case 4:
console.log("观看视频,接着玩");
break;
case 5:
console.log("好友助力,接着玩");
break;
case 6:
cc.director.preloadScene("GameOver");
cc.director.loadScene("GameOver");
console.log("立即跳过");
break;
default:
cc.log("default");
break;
}
}
});
时间进度为0时就会弹出上图的界面,由于之前想直接实体化该界面 的,但发现实体化之后出现了弹出该界面之后游戏还能继续,所以我这里就直接把它做成一个单独的场景。
开始界面。这里没啥重点,请看代码。
Start_Scene.js
cc.Class({
extends: cc.Component,
properties: {
//player 节点,用于获取主角弹跳的高度,控制主角行动
player: {
default: null,
type: cc.Node
},
//更新分数的Label
ScoreLabel: {
default: null,
type: cc.Label
},
},
onLoad () {
//开启冲力,感觉没啥用
cc.director.getPhysicsManager().enabled = true;
cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
// cc.PhysicsManager.DrawBits.e_pairBit |
// cc.PhysicsManager.DrawBits.e_centerOfMassBit |
cc.PhysicsManager.DrawBits.e_jointBit |
cc.PhysicsManager.DrawBits.e_shapeBit;
cc.director.getPhysicsManager().debugDrawFlags = 0;
/*==========================开启碰撞检测系统==========================*/
var manager = cc.director.getCollisionManager();
manager.enabled = true;
/*==========================开启物理碰撞==========================*/
this.physicsManager = cc.director.getPhysicsManager();
this.physicsManager.enabled = true;
/*==========================触摸监听==========================*/
this.node.on(cc.Node.EventType.TOUCH_START,function(touch){
//角色绑定控件
var hero = this.player.getComponent("Player");
//实现onTouchBegan事件回调函数
cc.log(touch)
var touchLocX = touch.getLocation().x;
if(touchLocX < cc.winSize.width/2) {
hero.node.runAction(hero.setJumpRightUpAction());//精灵跳跃
}
else if (touchLocX > cc.winSize.width/2) {
hero.node.runAction(hero.setJumpLeftUpAction());//精灵跳跃
}
cc.log("touchLocX: " + touchLocX );
//hero.node.runAction(hero.setJumpUpAction());//精灵跳跃
}, this);
},
/*=================================================================Update=================================================================*/
update (dt) {
this.ScoreLabel.string = ' ' + G_Score;
},
});
这里还有一个,是我设置的全局变量的脚本,里面包含一些常用的变量。在上面的场景中我们可以看到一个经常被使用到的变量,Score。这是用来更新分数的,所以我这里把他做成了全局变量。具体请看代码。
GlobalVariable.js
/*======分数全局变量====== */
window.G_Score = 0;
/*======= 判断篮板的移动方向 =======*/
window.G_Temp = 1;
/*======空心球的个数====== */
window.G_Hollow_Number = 0;
/*======擦板球的个数====== */
window.G_Bank_Number = 0;
/*======压哨球的个数====== */
window.G_Buzzer_Number = 0;
/*======高抛求的个数====== */
window.G_SellHigh_Number = 0;
先这样,后期有补充再添加。不喜勿喷啊。我是第一次接触cocos Creator。