1
1
遊戲預覽
1
2
開始場景
擺放一個背景圖,在背景圖上添加背景地面、開始按鈕、4個角色選擇按鈕、遊戲logo。
1. 實現開始按鈕的回調,點擊開始按鈕,跳轉到遊戲場景。跳轉場景方法如下:
cc.director.preloadScene('playScene', function () {
cc.director.loadScene('playScene');
});
//播放音效
playSound : function(name, isLoop){
cc.loader.loadRes(name, cc.AudioClip, function (err, clip) {
if(err){
return;
}
let audioID = cc.audioEngine.playEffect(clip, isLoop);
});
},
1. 將腳本拖到start場景的屬性檢查器中,並將腳本中聲明的屬性和組件關聯起來,如下圖:
2. 給開始按鈕綁定回調事件,選中開始按鈕,在屬性檢查器中,找到Button屬性,將ClickEvents值改成1,表示有一個點擊事件,再按照如下方式將函數和組件關聯起來:
3. 給角色按鈕綁定回調,方法和給開始按鈕綁定回調完全一樣,只是綁定的函數不同。
1
03
遊戲場景
遊戲玩法是控制我方英雄的發炮角度,如果打中敵方英雄就得分,否則會被敵方英雄的炮彈打中,如果我方英雄血量爲0則遊戲結束。
1. 遊戲主界面:包含背景,地面,我方英雄,分數文本,返回主界面按鈕。
2. 結算界面:包含遮罩層,最高得分文本,當前得分文本,重新開始按鈕,返回主界面按鈕。
gamePlay.js腳本是遊戲的核心,主要方法如下:
1. 開啓物理系統:
cc.director.getPhysicsManager().enabled = true;
2. 設置重力加速度:
cc.director.getPhysicsManager().gravity = cc.v2(0, -640);
3. 添加觸摸監聽,事件分爲TOUCH_START(開始)、TOUCH_MOVE(移動)、TOUCHCANCEL(取消)、TOUCH_END(結束)四個狀態,方法如下:
this.node.on(cc.Node.EventType.TOUCH_START, this.onEventStart, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onEventMove, this);
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onEventCancel, this);
this.node.on(cc.Node.EventType.TOUCH_END, this.onEventEnd, this);
4. 當開始觸摸屏幕時,觸發開始的回調onEventStart(),回調中開啓定時器,每隔0.03秒角度加1,並改變炮臺的角度,方法如下:
//更新炮管角度
updateGunAngle : function(){
this.shootLineImg.active = true;
this._curAngle = 0;
this.gunSchedule = function(){
if (this._curAngle < 90){
this._curAngle += 1;
this.myGunImg.angle = this._curAngle;
}
};
this.schedule(this.gunSchedule, 0.03);
},
5. 當結束觸摸時,觸發結束的回調onEventEnd(),回調中關閉定時器,方法如下:
//停止更新炮管
stopGunAngle(){
this.unschedule(this.gunSchedule);
this.shootLineImg.active = false;
},
6. 敵人開炮,需要先調整角度再發炮,炮的角度通過敵方子彈和我方英雄的座標可計算出來,方法如下:
//敵方開炮
enemyOpenFire : function(){
//敵方子彈世界座標
let enemyBulletPos = this._enemyNode.enemyBulletWorldPos();
//我方英雄世界座標
let myHeroPos = this.myHeroImg.parent.convertToWorldSpaceAR(cc.v2(this.myHeroImg.position.x, this.myHeroImg.position.y + 30));
//計算夾角
let lenX = Math.abs(enemyBulletPos.x - myHeroPos .x);
let lenY = Math.abs(enemyBulletPos.y - myHeroPos .y);
let angle = Math.atan2(lenY, lenX) * 180 / Math.PI;
//設置敵方小火炮的角度
this._enemyNode.setGunAngle(angle);
//計算炮運行的距離
let len = Math.sqrt(Math.pow(lenX, 2) + Math.pow(lenY, 2));
this._enemyNode.gunAni(len);
this.playSound("sound/enemyBullet", false);
},
7. 更換紋理方法:
//更換紋理
setImgTexture : function(str, node){
cc.loader.loadRes(str, cc.SpriteFrame, function (err, spriteFrame) {
if (err) {
cc.error(err.message || err);
return;
}
node.getComponent(cc.Sprite).spriteFrame = spriteFrame;
}.bind(this));
},
敵人腳本包含敵人,柱子,敵方炮彈等信息,腳本中的主要方法有:
1. 隨機設置柱子的高度:
//調整敵方柱子高度
setColumnHight : function(){
//隨機獲取高度
let y = Math.floor(Math.random() * -250) - 100;
this.cloumn.position = cc.v2(this._winSize.width / 2 + 100, y);
},
2. 敵人進出場的動作:
//敵人進場動作
comeOnAni : function(){
this.setColumnHight();
let w = Math.floor(Math.random() * (this._winSize.width / 4));
this.cloumn.runAction(cc.sequence(cc.moveTo(1.0, cc.v2(w, this.cloumn.position.y)), cc.callFunc(() =>{
this.enemyHeroImg.active = true;
this.enemyGunImg.active = true;
this.enemyAni();
}, this)));
},
//敵方柱子運動
enemyMove : function(){
this.enemyHeroImg.active = false;
this.enemyGunImg.active = false;
this.cloumn.runAction(cc.sequence(cc.moveTo(1.0, cc.v2(-this._winSize.width / 2 - 100, this.cloumn.position.y)), cc.callFunc(() =>{
if(this.callBack){
this.callBack();
}
})));
},
3. 敵人開炮:
//炮運動
gunAni : function(len){
let bulletPos = this.enemyBulletImg.position;
this.enemyBulletImg.runAction(cc.sequence(cc.moveTo(0.3, cc.v2(len, 0)), cc.callFunc(() =>{
if(this.hitHeroCallBack){
this.hitHeroCallBack();
}
this.enemyBulletImg.position = bulletPos;
})));
},
碰撞腳本是給需要做碰撞檢測的剛體用的,在碰撞腳本中做碰撞監聽,當觸發監聽後,再調用相應的回調。比如我方子彈需要監聽與牆壁,敵人,柱子等物體的碰撞,那麼我們先給子彈綁定好碰撞組件,如下圖:
再在代碼中實現碰撞的回調並保存下來,方法如下:
//碰撞監聽
contactFunction (selfCollider, otherCollider){
if(this.callBack){
this.callBack(selfCollider, otherCollider);
}
},
contactCallBack (callBack){
this.callBack = callBack;
},
最後在碰撞開始的監聽中調用回調,方法如下:
onBeginContact ( contact, selfCollider, otherCollider){
if(selfCollider.tag == 0 && otherCollider.tag == 0){
cc.log("onBeginContact..."); //碰撞開始
this.contactFunction(selfCollider, otherCollider);
}
},
遊戲中有英雄角色的等待和走路動作,敵人等待動作,如果在編輯器做動畫,編輯的個數比較多,所以我的做法是通過修改紋理達到動畫效果,用法是將這個腳本綁定到需要播放動畫的節點上,並設置一張大圖,方法如下:
使用方法:
playAni(nameStr, count, dt, isLoop){
this.stopAni();
this.node.getComponent(cc.Sprite).spriteFrame = this.bigImg.getSpriteFrame(nameStr + 0);
let array = [];
for(let i = 0; i < count; i++){
array.push(cc.delayTime(dt));
array.push(cc.callFunc(() =>{
this.node.getComponent(cc.Sprite).spriteFrame = this.bigImg.getSpriteFrame(nameStr + i);
}));
}
if(isLoop){
this.node.runAction(cc.repeatForever(cc.sequence(array)));
}
else{
this.node.runAction(cc.sequence(array));
}
},
參數分別是圖片名稱,圖片張數,間隔時間,是否循環,調用方法:
this.shieldImg.getComponent("spriteFrameAni").playAni("shield", 4, 0.1, true);
1
4
獲取代碼
關注公衆號,發送【大炮英雄】,獲取代碼。