<!-- 第三天,繼續視頻教程做練習和讀代碼。今天主要三個練習,第一個是場景跳轉,第二個是通過鍵盤監聽實現node節點上下左右自由移動,第三個是下雨特效,使用到預構節點。這些內容都來源昨天說的那個視頻教程,感覺蠻有用的,今天第三天,使用學到的這些應該能做個簡陋版的打飛機了,飛機移動和射擊都能夠實現了。對於不停刷新獲取坐標的方法再搞清楚點,就能夠做敵機被擊落或者掉血的操作了-->
第一個:做一個場景切換練習。代碼如下:<!-- 類似網頁跳轉,知道有加載和預加載。教程有提到鍵盤監聽需要點擊下屏幕,我試着把它作為第二個場景,點擊開始之后加載到需要鍵盤監聽的場景時候不需要點一下屏幕,就可以讓圖片上下左右移動了,可能這就是不同於網頁吧,在這種類似bug的需要點一下的要求上,跳轉場景並不等同於跳轉網頁,有類似於將某些共有加載項傳遞到下一個場景的感覺。瞎猜的。-->
這個練習用到兩個jsp文件,一個是控制第一個場景到中間游戲正文,一個是從正文到游戲結束的跳轉。按照順序為code1,code2.

1 cc.Class({ 2 extends: cc.Component, 3 4 properties: { 5 6 }, 7 8 // LIFE-CYCLE CALLBACKS: 9 10 onLoad () { 11 this.node.on('mousedown',function(){ 12 cc.director.loadScene('game'); 13 }); 14 }, 15 16 start () { 17 }, 18 19 // update (dt) {}, 20 });

1 cc.Class({ 2 extends: cc.Component, 3 4 properties: { 5 timeLabel:{ 6 default:null, 7 type:cc.Label 8 } 9 }, 10 11 onLoad () { 12 var times = 500; 13 this.schedule( 14 function(){ 15 times--; 16 this.timeLabel.string = times; 17 if(times===0){ 18 cc.director.loadScene('gameover'); 19 } 20 },1) 21 }, 22 23 start () { 24 25 }, 26 27 // update (dt) {}, 28 });
scheduler 是負責觸發回調函數的類。通常情況下,建議使用 cc.director.getScheduler() 來獲取系統定時器。 <!-- 之前做雨點效果的時候,明明生成一次,function里面也是return的一個sequence的動作,結果一直在下雨,滿屏幕都是,后來找到原因是因為寫到了update代碼塊里面去了,scheduler類似update,可以自定義循環的間隔,次數,延遲。api表示通常情況下,建議使用 cc.director.getScheduler() 來獲取系統定時器。-->就是一個定時器控制,能夠對控制器進行管理,包括加速減速,對定時器里面的函數的優先級進行管理。它的一個方法是schedule,就是使用它來完成循環動作。對label標簽倒計時操作的。<!--教程里是直接this.schedule,在api建議使用寫法是 cc.director.getScheduler().schedule(callback,target,interval,repeat,delay,paused) 下面詳細說參數是什么-->
schedule 定時器。
(method) cc.Scheduler.schedule(callback: Function, target: any, interval: number, paused?: boolean): void (+1 overload)
參數分別是 回調函數,目標對象,區間數,重復數,延遲數,是否暫停。一般回用到的是,callback的函數,target的目標和延遲數。<!-- 你可以直接就是this.schedule()就開始用,四個參數,第一個函數,第二個是間隔,第三個是次數,第四個是延遲數。如果按照api里的寫法,第二個目標是必須寫的,我測試過,要寫個this,不然會報錯加載不上場景,但是this.schedule()就不需要。估計是這樣寫就是默認參數為this-->
第二個:實現雨點特效。
代碼:

1 cc.Class({ 2 extends: cc.Component, 3 4 properties: { 5 hj : { 6 default: null, 7 type: cc.Prefab 8 }, 9 /* plane : { 10 default: null, 11 type: cc.Node 12 }*/ 13 14 }, 15 16 // LIFE-CYCLE CALLBACKS: 17 18 // onLoad () {}, 19 newHJ:function(position) { 20 var newHJ = cc.instantiate(this.hj); 21 this.node.addChild(newHJ,100); 22 newHJ.setPosition(position); 23 var hjdown = cc.moveBy(cc.random0To1()*5+1,cc.p(0,-this.node.height-100)); 24 var hjfilish = cc.callFunc(newHJ.removeFromParent,newHJ); 25 newHJ.runAction(cc.sequence(hjdown,hjfilish)); 26 }, 27 start () { 28 29 }, 30 31 getStartPosition: function(){ 32 var y = this.node.height/2+100; 33 var x = cc.random0To1()*960-480; 34 return cc.p(x,y); 35 }, 36 onLoad: function () { 37 38 this.schedule(function(){ 39 this.newHJ(this.getStartPosition()); 40 },3,3,3 41 ); 42 /* this.schedule( function () { 43 this.newHJ(cc.p(this.plane.x,this.plane.y)) 44 },1)*/ 45 }, 46 update (dt) { 47 48 }, 49 50 });
主要使用到的關鍵字有 instantiate addChild random0To1 callFunc removeFromParent
instantiate 克隆指定的任意類型的對象,或者從 Prefab 實例化出新節點。
function cc.instantiate<any>(original: any): any (+1 overload) 就是返回一個新的對象,可以用來克隆任何對象。克隆出一個之后,可以通過.original。返回一個原始對象。 <!--original:原件 overload:過載 Instantiate 時,function 和 dom 等非可序列化對象會直接保留原有引用,Asset 會直接進行淺拷貝,可序列化類型會進行深拷貝。)-->
addChild 添加子節點。Secene.addChild(),node.addChild(Child,locaZorder,tag),三個參數,一個是子節點對象。第二個是增加的子節點的層級,第三個是可選的標簽標記.<!--可能在生成大量的節點需要單獨出來進行操作的時候會用到這個參數。想雨點效果這種就不需要。>
random0To1 返回一個0到1之間隨機的浮點數。<!-- 大概用法,比如你想要獲得正600到負六百中間的隨機數,寫法就是 c.random0To1()*1200-600。大概思路就是,假設返回值為x,則 0<x<1,不等式兩邊同時乘一個1200,就是0到1200,再不等式兩邊同時減去600就等到想要的結果了。舉個特殊的例子,123到234,123<x<234,等式兩邊減去123,然后同時除(234-123),就回到了 0<x<1 我知道你懂了。-->
callFunc 執行回調函數 callFunc(function(){},target,date) 返回一個ActionInstant 即時動作 <!-- 我理解傳入一個函數和一個目標,然后把函數處理目標的過程封裝成一個即時動作返回。-->
ActionStant 即時動作,和ActionInterval事件間隔動作 都是繼承於finiteTimeAction 有限時間動作。<!--暫時沒遇到返回ActionStant的,callFunc是第一個。之前遇到ActionInterval有moveBy和moveTo能返回一個ActionInterval對象-->
removeFromParent 從父節點刪除該節點。如果不傳入 cleanup 參數或者傳入 true
,那么這個節點上所有綁定的事件、action 都會被刪除。建議調用這個 API 時總是傳入 false
參數。如果該節點上的所有操作和回調都應該刪除,則為false。<!--我以為是移除,結果解釋是刪除這個節點上綁定的事件和action。那么問題來了,這個節點還在不在呢。我覺得應該是在的,只是斷掉了所有的聯系,變成了孤兒。api里面解釋是如果這個一個孤節點,什么事情都不會發生。讓節點回到孤獨,斷了它身上所有的牽絆。-->
第三個,利用鍵盤事件監聽,實現圖片的上下左右等八個方向的自由移動。
代碼

1 cc.Class({ 2 extends: cc.Component, 3 4 properties: { 5 speed:0, 6 plane:{ 7 default:null, 8 type:cc.Node 9 } 10 11 }, 12 setInputControl: function() { 13 var self = this; 14 var listener = { 15 event:cc.EventListener.KEYBOARD, 16 onKeyPressed: function(KeyCode,event){ 17 switch(KeyCode){ 18 case cc.KEY.a: 19 self.accLeft = true; 20 break; 21 case cc.KEY.d: 22 self.accRight = true; 23 break; 24 case cc.KEY.w: 25 self.accUp = true; 26 break; 27 case cc.KEY.s: 28 self.accDown = true; 29 break; 30 } 31 }, 32 onKeyReleased: function(KeyCode,event){ 33 switch(KeyCode){ 34 case cc.KEY.a: 35 self.accLeft = false; 36 break; 37 case cc.KEY.d: 38 self.accRight = false; 39 break; 40 case cc.KEY.w: 41 self.accUp = false; 42 break; 43 case cc.KEY.s: 44 self.accDown = false; 45 break; 46 } 47 }, 48 }; 49 cc.eventManager.addListener(listener,self.node); 50 }, 51 52 onLoad () { 53 //定義四個方向是否發生移動的變量 54 this.accLeft = false; 55 this.accRight = false; 56 this.accDown = false; 57 this.accUp = false; 58 this.setInputControl(); 59 }, 60 61 start () { 62 63 }, 64 test :function () { 65 if(this.accLeft && this.plane.x>-389){ 66 this.plane.x -= this.speed; 67 } 68 if(this.accRight && this.plane.x<389){ 69 this.plane.x += this.speed; 70 } 71 if(this.accUp && this.plane.y<260){ 72 this.plane.y += this.speed; 73 } 74 if(this.accDown && this.plane.y>-260){ 75 this.plane.y -= this.speed; 76 } 77 }, 78 update (dt) { 79 this.test(); 80 /*if (this.plane.x>-389) { 81 this.test(); 82 }else{ 83 this.plane.x++;} 84 if (this.plane.x<389) { 85 this.test(); 86 }else{ 87 this.plane.x--;} 88 if (this.plane.y>-260) { 89 this.test(); 90 }else{ 91 this.plane.y++;} 92 if (this.plane.y>-260) { 93 this.test(); 94 }else{ 95 this.plane.y--;}*/ 96 }, 97 });
關鍵字:
event.getCurrentTarget() 返回其監聽器觸發事件的節點
event
}
EventListener 官方api中的用法如下。
stener.create({ event: cc.EventListener.KEYBOARD,
onKeyPressed: function (keyCode, event) { cc.log('pressed key: ' + keyCode); },
onKeyReleased: function (keyCode, event) { cc.log('released key: ' + keyCode); } });
// Create ACCELERATION EventListener. cc.EventListener.create({ event: cc.EventListener.ACCELERATION, callback: function (acc, event) { cc.log('acc: ' + keyCode); } }); 加速器事件監聽器類型 <!-- 加速器事件監聽器暫時不知道是什么,把例子先寫到這里 :
// Create ACCELERATION EventListener. cc.EventListener.create({ event: cc.EventListener.ACCELERATION, callback: function (acc, event) { cc.log('acc: ' + keyCode); } });
-->
類似的有 removeListener(),從事件管理器中移除事件監聽器。
<!-- 關於事件監聽還有很多不懂,這里想記錄寫法。后面在慢慢學習 -->