Cocos Creator實現大炮英雄,附程式碼!
遊戲預覽
開始場景
搭建開始場景
擺放一個背景圖,在背景圖上新增背景地面、開始按鈕、4個角色選擇按鈕、遊戲logo。
建立遊戲指令碼
1. 實現開始按鈕的回撥,點選開始按鈕,跳轉到遊戲場景。跳轉場景方法如下:
cc.director.preloadScene('playScene', function () { cc.director.loadScene('playScene'); });
2. 實現選擇角色按鈕的回撥,點選某個角色時,先將其他角色設定為未選中狀態,再將當前選擇的角色設為選中狀態,最後用cc.sys.localStorage.setItem(“key”,value);方法本地儲存選擇的角色型別。
3. 在onLoad()方法中,呼叫cc.sys.localStorage.getItem(“key”);方法獲取到本地儲存的角色型別,並設定角色按鈕的選中狀態。
4. 遊戲中音效必不可少,點選各個按鈕時,都需要播放音效,方法如下:
//播放音效 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. 給角色按鈕繫結回撥,方法和給開始按鈕繫結回撥完全一樣,只是繫結的函式不同。
遊戲場景
遊戲玩法是控制我方英雄的發炮角度,如果打中敵方英雄就得分,否則會被敵方英雄的炮彈打中,如果我方英雄血量為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);
獲取程式碼
關注公眾號,傳送【大炮英雄】,獲取程式碼。