系列教程
CocosCreator教程(初識篇)
CocosCreator教程(編輯器篇)html
ProjectName(新建項目) ├──assets ├──library ├──local ├──packages ├──settings ├──temp └──project.json
子結構 | 功能 |
---|---|
assets | 與資源管理器的內容同步,遊戲的核心目錄(每一個文件都有相應.meta文件) |
library | 這裏文件的結構和資源的格式將被處理成最終遊戲發佈時須要的形式 |
local | 編輯器使用習慣記錄(如:窗體佈局) |
settings | 項目設置 |
project.json | 版本控制,必須與assets共同存在 |
build | 打包導出目錄,構建項目時,自動生成 |
PS:.meta文件——記錄某資源在項目中的惟一標識,以及其配置信息,只有在編輯器中對資源作修改,.meta文件纔會實時變化。所以,不要在編輯器外,對資源的內容進行操做。node
自動釋放資源:切換場景後,上一個場景中的資源,從內存中釋放。
延遲加載資源:意味着不用等待全部資源加載完畢,才顯示場景。(快速切換場景,資源陸續在畫面顯示)web
普通圖,子層爲一張spriteFrame。json
建立方式:拖拽場景節點,到資源管理器。跨域
精靈圖,子層爲多張spriteFrame。(精靈圖合成軟件:TexturePacker、Zwoptex)數組
打包時,將所在目錄中的全部碎圖,合成爲圖集。瀏覽器
數字爲內容的圖集。緩存
動態字體:.ttf
位圖字體:.fnt + .png(存在於同一目錄)安全
小型動畫服務器
模式:web audio、dom audio
文件格式 | 功能 |
---|---|
.json | 骨骼數據 |
.png | 圖集紋理 |
.txt / .atlas | 圖集數據 |
文件格式 | 功能 |
---|---|
.tmx | 地圖數據 |
.png | 圖集紋理 |
.tsx tileset | 數據配置文件 |
操做流程:
(1)導出:文件 => 資源導出,選擇 .fire場景文件,輸出assets目錄的 .zip壓縮包。
(2)導入:文件 => 資源導入,選擇壓縮包源路徑、解壓路徑,輸出assets目錄內容。
基於size mode,儘可能去除spriteFrame無像素的部分,減少圖片尺寸。
類別 | 座標軸方向 |
---|---|
cocos座標系(世界、本地座標系) | x右、y上、z外 |
設備屏幕座標系 | x右、y下 |
做用:用於變換、子節點定位基準。
對攝像機、渲染組件的瞭解。
對widget、layout等UI組件的瞭解。
(1)建立動畫的基本流程
(2)時間曲線(雙擊動畫線,進入編輯窗口)
(3)事件管理(雙擊遊標、加減按鈕控制參數個數)
(4)腳本控制
碰撞組件(普通碰撞)
(1)editing——是否爲編輯模式
(2)regenerate points——計算圖形邊界,自定生成控制點,數值爲控制點的生成密度 / 準確度
(3)ctrl + 點擊——刪除控制點
(4)組件類型:矩形、圓形、多邊形
(5)設置碰撞組(項目 => 項目設置 => 分組設置):
制定分組 => 匹配分組 => 碰撞組件所在節點上,設置所屬分組
(6)腳本控制
Box2D物理引擎(高級碰撞)
(1)audioSource組件
(2)腳本控制
(1)定義 CCClass
var Sprite = cc.Class({ //... });
(2)實例化
var obj = new Sprite();
(3)判斷類型
cc.log(obj instanceof Sprite); //使用原生JS的instanceof
(4)構造函數(ctor)
var Sprite = cc.Class({ //使用ctor聲明構造函數 ctor: function () { cc.log(this instanceof Sprite); } });
(5)實例方法
var Sprite = cc.Class({ // 聲明一個名叫 "print" 的實例方法 print: function () { } });
(6)繼承(extends)
// 父類 var Shape = cc.Class(); // 子類 var Rect = cc.Class({ //使用 extends 實現繼承 extends: Shape });
(7)父構造函數
var Shape = cc.Class({ ctor: function () { cc.log("Shape"); // 實例化時,父構造函數會自動調用, } }); var Rect = cc.Class({ extends: Shape }); var Square = cc.Class({ extends: Rect, ctor: function () { cc.log("Square"); // 再調用子構造函數 } }); var square = new Square();
(8)完整聲明屬性
//簡單類型聲明 properties: { score: { //這幾個參數分別指定了 score 的默認值爲 0,在 屬性檢查器 裏,其屬性名將顯示爲:「Score (player)」,而且當鼠標移到參數上時,顯示對應的 Tooltip。 default: 0, displayName: "Score (player)", tooltip: "The score of player", } } //數組聲明 properties: { names: { default: [], type: [cc.String] // 用 type 指定數組的每一個元素都是字符串類型 }, enemies: { default: [], type: [cc.Node] // type 一樣寫成數組,提升代碼可讀性 }, } //get/set 聲明 properties: { width: { get: function () { return this._width; }, set: function (value) { this._width = value; } } }
properties經常使用參數
參數 | 做用 |
---|---|
default | 默認值 |
type | 限定屬性的數據類型 |
visible | 若爲false,則不在屬性檢查器面板中顯示該屬性 |
serializable | 若爲false,則不序列化(保存)該屬性 |
displayName | 在屬性檢查器面板中,顯示成指定名字 |
tooltip | 在屬性檢查器面板中,添加屬性的Tooltip |
(1)得到組件所在的節點
this.node
(2)得到其它組件
this.getComponent(組件名)
(3)得到其它節點及其組件
// Player.js cc.Class({ extends: cc.Component, properties: { player: { default: null, type: cc.Node } } }); //若是你將屬性的 type 聲明爲 Player 組件,當你拖動節點 "Player Node" 到 屬性檢查器,player 屬性就會被設置爲這個節點裏面的 Player 組件 // Cannon.js var Player = require("Player"); cc.Class({ extends: cc.Component, properties: { // 聲明 player 屬性,此次直接是組件類型 player: { default: null, type: Player } } }); //查找子節點 //返回子節點數組 this.node.children //返回對應的子節點 this.node.getChildByName(子節點名); //查找後代節點 cc.find(子節點/.../後代節點, this.node); //全局查找節點 cc.find(場景/節點/節點/...);
(4)訪問已有變量裏的值(經過模塊訪問
//專門開設一箇中介模塊,導出接口;在其餘模塊進行節點、組件、屬性的操做 // Global.js module.exports = { backNode: null, backLabel: null, }; // Back.js var Global = require("Global"); cc.Class({ extends: cc.Component, onLoad: function () { Global.backNode = this.node; Global.backLabel = this.getComponent(cc.Label); } }); // AnyScript.js var Global = require("Global"); cc.Class({ extends: cc.Component, start: function () { var text = "Back"; Global.backLabel.string = text; } });
(1)節點狀態和層級操做
//激活/關閉節點 this.node.active = true; this.node.active = false; //更改節點的父節點 this.node.parent = parentNode; //索引節點的子節點 //返回子節點數組 this.node.children //返回子節點數量 this.node.childrenCount
(2)更改節點的變換(位置、旋轉、縮放、尺寸)
//更改節點位置 //分別對 x 軸和 y 軸座標賦值 this.node.x = 100; this.node.y = 50; //使用setPosition方法 this.node.setPosition(100, 50); this.node.setPosition(cc.v2(100, 50)); //設置position變量 this.node.position = cc.v2(100, 50); //更改節點旋轉 this.node.rotation = 90; this.node.setRotation(90); //更改節點縮放 this.node.scaleX = 2; this.node.scaleY = 2; this.node.setScale(2); this.node.setScale(2, 2); //更改節點尺寸 this.node.setContentSize(100, 100); this.node.setContentSize(cc.size(100, 100)); this.node.width = 100; this.node.height = 100; //更改節點錨點位置 this.node.anchorX = 1; this.node.anchorY = 0; this.node.setAnchorPoint(1, 0);
(3)顏色和不透明度
//設置顏色 mySprite.node.color = cc.Color.RED; //設置不透明度 mySprite.node.opacity = 128;
4)經常使用組件接口
cc.Component 是全部組件的基類,任何組件都包括以下的常見接口:
接口 | 做用 |
---|---|
this.node | 該組件所屬的節點實例 |
this.enabled | 是否每幀執行該組件的 update 方法,同時也用來控制渲染組件是否顯示 |
update(dt) | 做爲組件的成員方法,在組件的 enabled 屬性爲 true 時,其中的代碼會每幀執行 |
onLoad() | 組件所在節點進行初始化時(節點添加到節點樹時)執行 |
start() | 會在該組件第一次 update 以前執行,一般用於須要在全部組件的 onLoad 初始化完畢後執行的邏輯 |
函數名 | 描述 |
---|---|
onLoad | 在節點首次激活時觸發,或者所在節點被激活的狀況下觸發 |
start | 在組件首次激活前 |
update | 動畫更新前 |
lateUpdate | 動畫更新後 |
onEnable | 當組件的 enabled 屬性從 false 變爲 true 時,或者所在節點的 active 屬性從 false 變爲 true 時(假若節點首次被建立且 enabled 爲 true,則會在 onLoad 以後,start 以前被調用) |
onDisable | 當組件的 enabled 屬性從 true 變爲 false 時,或者所在節點的 active 屬性從 true 變爲 false 時 |
onDestroy | 當組件或者所在節點調用了 destroy()時 |
(1)建立新節點
cc.Class({ extends: cc.Component, properties: { sprite: { default: null, type: cc.SpriteFrame, }, }, start: function () { //動態建立節點,並將它加入到場景中 var node = new cc.Node('Sprite'); var sp = node.addComponent(cc.Sprite); sp.spriteFrame = this.sprite; node.parent = this.node; } });
(2)克隆已有節點
// cc.Class({ extends: cc.Component, properties: { target: { default: null, type: cc.Node, }, }, start: function () { //克隆場景中的已有節點 var scene = cc.director.getScene(); var node = cc.instantiate(this.target); node.parent = scene; node.setPosition(0, 0); } });
(3)建立預製節點
// cc.Class({ extends: cc.Component, properties: { target: { default: null, type: cc.Prefab, //預製 }, }, start: function () { var scene = cc.director.getScene(); var node = cc.instantiate(this.target); node.parent = scene; node.setPosition(0, 0); } });
(4)銷燬節點
// cc.Class({ extends: cc.Component, properties: { target: cc.Node, }, start: function () { // 5 秒後銷燬目標節點 //銷燬節點並不會馬上被移除,而是在當前幀邏輯更新結束後,統一執行 setTimeout(function () { this.target.destroy(); }.bind(this), 5000); }, update: function (dt) { //判斷當前節點是否已經被銷燬 if (cc.isValid(this.target)) { this.target.rotation += dt * 10.0; } } });
PS:不要使用removeFromParent去銷燬節點。
緣由:調用一個節點的 removeFromParent 後,它不必定就能徹底從內存中釋放,由於有可能因爲一些邏輯上的問題,致使程序中仍然引用到了這個對象。
(1)加載和切換
//從當前場景,切換到MyScene場景 cc.director.loadScene("MyScene");
(2)經過常駐節點,進行場景資源管理和參數傳遞
//常駐節點:不隨場景切換,而自動銷燬,爲全部場景提供持久性信息 //設置常駐節點 cc.game.addPersistRootNode(myNode); //取消常駐節點,還原爲通常場景節點 cc.game.removePersistRootNode(myNode);
(3)場景加載回調
//fn:加載MyScene場景時觸發 cc.director.loadScene("MyScene", fn);
(4)預加載場景
//後臺預加載場景 cc.director.preloadScene("MyScene", fn); //有須要時,手動加載該場景 cc.director.loadScene("MyScene", fn);
(1)資源屬性的聲明
// NewScript.js cc.Class({ extends: cc.Component, properties: { //全部繼承自 cc.Asset 的類型都統稱資源,如 cc.Texture2D, cc.SpriteFrame, cc.AnimationClip, cc.Prefab 等 texture: { default: null, type: cc.Texture2D }, spriteFrame: { default: null, type: cc.SpriteFrame } } });
(2)靜態加載(在屬性檢查器裏設置資源)
// NewScript.js onLoad: function () { //拖拽資源管理器的資源,到屬性檢查器的腳本組件中,便可在腳本里拿到設置好的資源 var spriteFrame = this.spriteFrame; var texture = this.texture; spriteFrame.setTexture(texture); }
(3)動態加載
//動態加載的資源,須要存放於assets的子目錄resources中 //加載單個資源 //cc.loader.loadRes(resources的相對路徑, 類型(可選), 回調函數) //加載Prefab資源 cc.loader.loadRes("test assets/prefab", function (err, prefab) { var newNode = cc.instantiate(prefab); cc.director.getScene().addChild(newNode); }); //加載SpriteFrame var self = this; cc.loader.loadRes("test assets/image", cc.SpriteFrame, function (err, spriteFrame) { self.node.getComponent(cc.Sprite).spriteFrame = spriteFrame; }); //批量加載資源 //cc.loader.loadResDir(resources的相對路徑, 類型(可選), 回調函數) //加載test assets目錄下全部資源 cc.loader.loadResDir("test assets", function (err, assets) { // ... }); //加載test assets目錄下全部SpriteFrame,而且獲取它們的路徑 cc.loader.loadResDir("test assets", cc.SpriteFrame, function (err, assets, urls) { // ... }); //資源淺釋放 //cc.loader.releaseRes(resources的相對路徑, 類型(可選)) cc.loader.releaseRes("test assets/image", cc.SpriteFrame); cc.loader.releaseRes("test assets/anim"); //cc.loader.releaseAsset(組件名) cc.loader.releaseAsset(spriteFrame); // 資源深釋放,釋放一個資源以及全部它依賴的資源 var deps = cc.loader.getDependsRecursively('prefabs/sample');
(4)加載遠程資源和設備資源
//加載遠程資源 //遠程 url 帶圖片後綴名 var remoteUrl = "http://unknown.org/someres.png"; cc.loader.load(remoteUrl, function (err, texture) { //... }); //遠程 url 不帶圖片後綴名,此時必須指定遠程圖片文件的類型 remoteUrl = "http://unknown.org/emoji?id=124982374"; cc.loader.load({url: remoteUrl, type: 'png'}, function () { //... }); //加載設備資源 //用絕對路徑加載設備存儲內的資源,好比相冊 var absolutePath = "/dara/data/some/path/to/image.png" cc.loader.load(absolutePath, function () { //... });
加載限制:
一、原平生臺遠程加載不支持圖片文件之外類型的資源。
二、這種加載方式只支持圖片、聲音、文本等原生資源類型,不支持SpriteFrame、SpriteAtlas、Tilemap等資源的直接加載和解析。(須要後續版本中的AssetBundle支持)
三、Web端的遠程加載受到瀏覽器的CORS跨域策略限制,若是對方服務器禁止跨域訪問,那麼會加載失敗,並且因爲WebGL安全策略的限制,即使對方服務器容許http請求成功以後也沒法渲染。
(5)資源的依賴和釋放
// 直接釋放某個貼圖 cc.loader.release(texture); // 釋放一個 prefab 以及全部它依賴的資源 var deps = cc.loader.getDependsRecursively('prefabs/sample'); cc.loader.release(deps); // 若是在這個 prefab 中有一些和場景其餘部分共享的資源,你不但願它們被釋放,能夠將這個資源從依賴列表中刪除 var deps = cc.loader.getDependsRecursively('prefabs/sample'); var index = deps.indexOf(texture2d._uuid); if (index !== -1) deps.splice(index, 1); cc.loader.release(deps);
(1)監聽事件
//target是可選參數,用於綁定響應函數的調用者 //boolean是可選參數,默認爲false,表示冒泡流 this.node.on(event, fn, target, boolean);
(2)關閉監聽
this.node.off(event, fn, target, boolean);
(3)發射事件
//爲事件函數,提供參數,最多5個 this.node.emit(event, arg1, arg2, arg3);
(4)派送事件
//grandson.js //升級版的on,冒泡到的節點,所有註冊事件 this.node.dispatchEvent( new cc.Event.EventCustom('foobar', true) ); //father.js //在指定的上級節點中,註冊相同的事件,阻止事件冒泡,手動中止派送 this.node.on('foobar', function (event) { event.stopPropagation(); });
(5)事件對象(回調參數的event對象)
API 名 | 類型 | 意義 |
---|---|---|
type | String | 事件的類型(事件名) |
target | cc.Node | 接收到事件的原始對象 |
currentTarget | cc.Node | 接收到事件的當前對象,事件在冒泡階段當前對象可能與原始對象不一樣 |
getType | Function | 獲取事件的類型 |
stopPropagation | Function | 中止冒泡階段,事件將不會繼續向父節點傳遞,當前節點的剩餘監聽器仍然會接收到事件 |
stopPropagationImmediate | Function | 當即中止事件的傳遞,事件將不會傳給父節點以及當前節點的剩餘監聽器 |
getCurrentTarget | Function | 獲取當前接收到事件的目標節點 |
detail | Function | 自定義事件的信息(屬於 cc.Event.EventCustom) |
setUserData | Function | 設置自定義事件的信息(屬於 cc.Event.EventCustom) |
getUserData | Function | 獲取自定義事件的信息(屬於 cc.Event.EventCustom) |
(1)鼠標事件類型和事件對象
枚舉對象定義 | 對應的事件名 | 事件觸發的時機 |
---|---|---|
cc.Node.EventType.MOUSE_DOWN | mousedown | 當鼠標在目標節點區域按下時觸發一次 |
cc.Node.EventType.MOUSE_ENTER | mouseenter | 當鼠標移入目標節點區域時,不管是否按下 |
cc.Node.EventType.MOUSE_MOVE | mousemove | 當鼠標在目標節點在目標節點區域中移動時,不管是否按下 |
cc.Node.EventType.MOUSE_LEAVE | mouseleave | 當鼠標移出目標節點區域時,不管是否按下 |
cc.Node.EventType.MOUSE_UP | mouseup | 當鼠標從按下狀態鬆開時觸發一次 |
cc.Node.EventType.MOUSE_WHEEL | mousewheel | 當鼠標滾輪滾動時 |
函數名 | 返回值類型 | 意義 |
---|---|---|
getScrollY | Number | 獲取滾輪滾動的 Y 軸距離,只有滾動時纔有效 |
getLocation | Object | 獲取鼠標位置對象,對象包含 x 和 y 屬性 |
getLocationX | Number | 獲取鼠標的 X 軸位置 |
getLocationY | Number | 獲取鼠標的 Y 軸位置 |
getPreviousLocation | Object | 獲取鼠標事件上次觸發時的位置對象,對象包含 x 和 y 屬性 |
getDelta | Object | 獲取鼠標距離上一次事件移動的距離對象,對象包含 x 和 y 屬性 |
getButton | Number | cc.Event.EventMouse.BUTTON_LEFT或cc.Event.EventMouse.BUTTON_RIGHT或cc.Event.EventMouse.BUTTON_MIDDLE |
(2)觸摸事件類型和事件對象
枚舉對象定義 | 對應的事件名 | 事件觸發的時機 |
---|---|---|
cc.Node.EventType.TOUCH_START | touchstart | 當手指觸點落在目標節點區域內時 |
cc.Node.EventType.TOUCH_MOVE | touchmove | 當手指在屏幕上目標節點區域內移動時 |
cc.Node.EventType.TOUCH_END | touchend | 當手指在目標節點區域內離開屏幕時 |
cc.Node.EventType.TOUCH_CANCEL | touchcancel | 當手指在目標節點區域外離開屏幕時 |
API 名 | 類型 | 意義 |
---|---|---|
touch | cc.Touch | 與當前事件關聯的觸點對象 |
getID | Number | 獲取觸點的 ID,用於多點觸摸的邏輯判斷 |
getLocation | Object | 獲取觸點位置對象,對象包含 x 和 y 屬性 |
getLocationX | Number | 獲取觸點的 X 軸位置 |
getLocationY | Number | 獲取觸點的 Y 軸位置 |
getPreviousLocation | Object | 獲取觸點上一次觸發事件時的位置對象,對象包含 x 和 y 屬性 |
getStartLocation | Object | 獲取觸點初始時的位置對象,對象包含 x 和 y 屬性 |
getDelta | Object | 獲取觸點距離上一次事件移動的距離對象,對象包含 x 和 y 屬性 |
(3)其它事件
枚舉對象定義 | 對應的事件名 | 事件觸發的時機 |
---|---|---|
無 | position-changed | 當位置屬性修改時 |
無 | rotation-changed | 當旋轉屬性修改時 |
無 | scale-changed | 當縮放屬性修改時 |
無 | size-changed | 當寬高屬性修改時 |
無 | anchor-changed | 當錨點屬性修改時 |
PS:枚舉對象定義、事件名等價,在回調參數中,做用相同。
//全局系統事件的類型 cc.SystemEvent.EventType.KEY_DOWN //鍵盤按下 cc.SystemEvent.EventType.KEY_UP //鍵盤釋放 cc.SystemEvent.EventType.DEVICEMOTION //設備重力傳感 //綁定、解除全局系統事件 cc.systemEvent.on(event, fn, target, boolean); cc.systemEvent.off(event, fn, target, boolean);
(1)動做控制
// 執行動做 node.runAction(action); // 中止一個動做 node.stopAction(action); // 中止全部動做 node.stopAllActions(); // 給 action 設置 tag var ACTION_TAG = 1; action.setTag(ACTION_TAG); // 經過 tag 獲取 action node.getActionByTag(ACTION_TAG); // 經過 tag 中止一個動做 node.stopActionByTag(ACTION_TAG);
(2)容器動做
//順序執行 cc.sequence(action1, action2, ...); //併發執行 cc.spawn(action1, action2, ...); //指定次數,重複執行 cc.repeat(action, times) //無限次數,重複執行 cc.repeatForever(action) //改變更做速度倍率,再執行 cc.speed(action, rate)
(3)即時動做
cc.show() //當即顯示 cc.hide() //當即隱藏
(4)時間間隔動做
cc.moveTo() //移動到目標位置 cc.rotateTo() //旋轉到目標角度 cc.scaleTo() //將節點大小縮放到指定的倍數
(5)動做回調
var finished = cc.callFunc(fn, target, arg);
(6)緩動動做
var action = cc.scaleTo(0.5, 2, 2); //使用easeIn曲線,豐富動做表現 action.easing(cc.easeIn(3.0));
PS:可使用緩動系統,代替動做系統。(緩動系統的API更簡約)
//interval:以秒爲單位的時間間隔 //repeat:重複次數 //delay:開始延時 this.schedule(fn, interval, repeat, delay) this.unschedule(fn)
editor: { //executionOrder越小,該組件相對其它組件就會越先執行(默認爲0) //executionOrder只對 onLoad, onEnable, start, update 和 lateUpdate 有效,對 onDisable 和 onDestroy 無效 executionOrder: 1 }
(1)XMLHttpRequest——短鏈接
(2)WebSocket——長鏈接
對象池的概念
在同一場景中,須要屢次進行節點的生成、消失時,假如直接進行建立、銷燬的操做,就會很浪費性能。所以,使用對象池,存儲須要消失的節點,釋放須要生成的節點,達到節點回收利用的目的。
工做流程
(1)初始化對象池
properties: { enemyPrefab: cc.Prefab //準備預製資源 }, onLoad: function () { this.enemyPool = new cc.NodePool(); let initCount = 5; for (let i = 0; i < initCount; ++i) { let enemy = cc.instantiate(this.enemyPrefab); // 建立節點 this.enemyPool.put(enemy); // 經過 put 接口放入對象池 } }
(2)從對象池請求對象
createEnemy: function (parentNode) { let enemy = null; if (this.enemyPool.size() > 0) { // 經過 size 接口判斷對象池中是否有空閒的對象 enemy = this.enemyPool.get(); } else { // 若是沒有空閒對象,也就是對象池中備用對象不夠時,咱們就用 cc.instantiate 從新建立 enemy = cc.instantiate(this.enemyPrefab); } enemy.parent = parentNode; // 將生成的敵人加入節點樹 enemy.getComponent('Enemy').init(); //接下來就能夠調用 enemy 身上的腳本進行初始化 }
(3)將對象返回對象池
onEnemyKilled: function (enemy) { // enemy 應該是一個 cc.Node this.enemyPool.put(enemy); // 和初始化時的方法同樣,將節點放進對象池,這個方法會同時調用節點的 removeFromParent }
清除對象池
//手動清空對象池,銷燬其中緩存的全部節點 myPool.clear();
文章轉自:https://blog.csdn.net/ccnu027cs/article/details/101070069