從零到一:用Phaser.js寫意地開發小遊戲(Chapter 3
上一節我們搭建了遊戲的骨架,添加了四個遊戲場景,分別是載入、開始、遊戲、結束。那麼這一節我們來介紹載入這個場景,順帶豐富一下各個場景的基本內容。
Phaser.Loader
Phaser框架自帶的一個loader,支援載入多種型別的資源,下面是離線文件中的介紹的截圖,詳細的API可以查閱文件得知。
介紹幾個常用的載入資源的方法:(下列程式碼中的game預設為Phaser例項,通過new Phaser.Game賦值)
載入圖片
game.load.image('star', 'star.png');
載入音訊
game.load.audio('bg', 'bg.mp3)');
載入圖片序列
由於要指定幀的寬高,因此一般是動畫的連續幀,例如行走動畫的每一幀合成的圖片。
game.load.spritesheet('walk', 'walk.png', 80, 80);
載入資源集合
同樣可以用作載入圖片序列,但這種用法主要用於載入類似於TexturePacker打包出來的資源集合。相比於spritesheet一般是一連串的動畫幀合成的圖片,這種資源集合中的圖片可以是各種各樣的,和我們平常做網站會將icon、背景圖片等合成sprites一個道理。
打包出來的資源一般包括一個json和一張合成的圖片,json描述了合成圖片中每張圖片的寬高位置等資訊。
game.load.altasJSONArray('fly' , 'fly.png', 'fly.json');
正式開始
第一步:載入你需要的資源
上一節我們提過每個場景都有自己的生命週期,因此載入資源的操作應放在preload這個階段執行。當preload中的資源載入完畢後,則preload場景將進入create階段,示例程式碼如下:
// 載入場景
preload: function() {
this.preload = function() {
// 設定背景為黑色
game.stage.backgroundColor = '#000000';
// 載入遊戲資源
game.load.crossOrigin = 'anonymous' ; // 設定跨域
game.load.image('bg', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bg.png');
game.load.image('dude', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/dude.png');
game.load.image('green', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/green.png');
game.load.image('red', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/red.png');
game.load.image('yellow', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/yellow.png');
game.load.image('bomb', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bomb.png');
game.load.image('five', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/five.png');
game.load.image('three', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/three.png');
game.load.image('one', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/one.png');
game.load.audio('bgMusic', '//24haowan-cdn.shanyougame.com/pickApple2/assets/audio/bgMusic.mp3');
},
this.create = function() {
alert('載入完畢!');
}
}
// 實際應用場景改為window.innerWidth和window.innerHeight。
// 這裡是為了方便檢視示例。
var width = 320;
var height = 568;
// 建立遊戲例項
var game = new Phaser.Game(width, height, Phaser.AUTO, '#game');
// 定義場景
var states = {
// 載入場景
preload: function() {
this.preload = function() {
// 設定背景為黑色
game.stage.backgroundColor = '#000000';
// 載入遊戲資源
game.load.crossOrigin = 'anonymous'; // 設定跨域
game.load.image('bg', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bg.png');
game.load.image('dude', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/dude.png');
game.load.image('green', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/green.png');
game.load.image('red', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/red.png');
game.load.image('yellow', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/yellow.png');
game.load.image('bomb', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bomb.png');
game.load.image('five', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/five.png');
game.load.image('three', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/three.png');
game.load.image('one', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/one.png');
game.load.audio('bgMusic', '//24haowan-cdn.shanyougame.com/pickApple2/assets/audio/bgMusic.mp3');
},
this.create = function() {
alert('載入完畢!');
}
},
// 開始場景
created: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#777';
setTimeout(function() {
game.state.start('play');
}, 3000);
}
},
// 遊戲場景
play: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#444';
setTimeout(function() {
game.state.start('over');
}, 3000);
}
},
// 結束場景
over: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#000';
alert('遊戲結束!');
}
}
};
// 新增場景到遊戲示例中
Object.keys(states).map(function(key) {
game.state.add(key, states[key]);
});
// 啟動遊戲
game.state.start('preload');
第二步:監聽載入完成的事件
通常來說我們都需要反饋載入進度,例如一個進度條,或者是一個百分比的數字。於是我們接下來就需要監聽載入完成的事件了。
// 監聽載入完畢事件
game.load.onLoadComplete.add(function() {
alert('載入完畢!');
});
如果我們需要監聽到載入的進度,那麼可以用下面的方法:
// 新增進度文字
var progressText = game.add.text(game.world.centerX, game.world.centerY, '0%', {
fontSize: '60px',
fill: '#ffffff'
});
progressText.anchor.setTo(0.5, 0.5); // 設定錨點,用於居中
// 監聽載入完一個檔案的事件
game.load.onFileComplete.add(function(progress) {
progressText.text = progress + '%';
});
// 實際應用場景改為window.innerWidth和window.innerHeight。
// 這裡是為了方便檢視示例。
var width = 320;
var height = 568;
// 建立遊戲例項
var game = new Phaser.Game(width, height, Phaser.AUTO, '#game');
// 定義場景
var states = {
// 載入場景
preload: function() {
this.preload = function() {
// 設定背景為黑色
game.stage.backgroundColor = '#000000';
// 載入遊戲資源
game.load.crossOrigin = 'anonymous'; // 設定跨域
game.load.image('bg', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bg.png');
game.load.image('dude', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/dude.png');
game.load.image('green', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/green.png');
game.load.image('red', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/red.png');
game.load.image('yellow', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/yellow.png');
game.load.image('bomb', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bomb.png');
game.load.image('five', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/five.png');
game.load.image('three', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/three.png');
game.load.image('one', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/one.png');
game.load.audio('bgMusic', '//24haowan-cdn.shanyougame.com/pickApple2/assets/audio/bgMusic.mp3');
// 新增進度文字
var progressText = game.add.text(game.world.centerX, game.world.centerY, '0%', {
fontSize: '60px',
fill: '#ffffff'
});
progressText.anchor.setTo(0.5, 0.5);
// 監聽載入完一個檔案的事件
game.load.onFileComplete.add(function(progress) {
progressText.text = progress + '%';
});
// 監聽載入完畢事件
game.load.onLoadComplete.add(function() {
alert('載入完畢!');
});
},
this.create = function() {
// game.state.start('created');
}
},
// 開始場景
created: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#777';
setTimeout(function() {
game.state.start('play');
}, 3000);
}
},
// 遊戲場景
play: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#444';
setTimeout(function() {
game.state.start('over');
}, 3000);
}
},
// 結束場景
over: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#000';
alert('遊戲結束!');
}
}
};
// 新增場景到遊戲示例中
Object.keys(states).map(function(key) {
game.state.add(key, states[key]);
});
// 啟動遊戲
game.state.start('preload');
第三步:新增載入頁的最小展示時間
一般而言,我們做遊戲都會在loading介面放一個LOGO,作為展示宣傳用,那麼如果需要載入的資源體積很小的話,有可能載入介面就是一閃而過了。於是,根據我們開發的經驗,會設定一個最小的展示時間(例如3秒),在未到最小的展示時間前,即便資源已經載入完畢,也不會離開載入場景。
// 監聽載入完畢事件
game.load.onLoadComplete.add(onLoad);
// 最小展示時間,示例為3秒
var deadLine = false;
setTimeout(function() {
deadLine = true;
}, 3000);
// 載入完畢回撥方法
function onLoad() {
if (deadLine) {
// 已到達最小展示時間,可以進入下一個場景
game.state.start('created');
} else {
// 還沒有到最小展示時間,1秒後重試
setTimeout(onLoad, 1000);
}
}
// 實際應用場景改為window.innerWidth和window.innerHeight。
// 這裡是為了方便檢視示例。
var width = 320;
var height = 568;
// 建立遊戲例項
var game = new Phaser.Game(width, height, Phaser.AUTO, '#game');
// 定義場景
var states = {
// 載入場景
preload: function() {
this.preload = function() {
// 設定背景為黑色
game.stage.backgroundColor = '#000000';
// 載入遊戲資源
game.load.crossOrigin = 'anonymous'; // 設定跨域
game.load.image('bg', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bg.png');
game.load.image('dude', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/dude.png');
game.load.image('green', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/green.png');
game.load.image('red', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/red.png');
game.load.image('yellow', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/yellow.png');
game.load.image('bomb', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bomb.png');
game.load.image('five', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/five.png');
game.load.image('three', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/three.png');
game.load.image('one', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/one.png');
game.load.audio('bgMusic', '//24haowan-cdn.shanyougame.com/pickApple2/assets/audio/bgMusic.mp3');
// 新增進度文字
var progressText = game.add.text(game.world.centerX, game.world.centerY, '0%', {
fontSize: '60px',
fill: '#ffffff'
});
progressText.anchor.setTo(0.5, 0.5);
// 監聽載入完一個檔案的事件
game.load.onFileComplete.add(function(progress) {
progressText.text = progress + '%';
});
// 監聽載入完畢事件
game.load.onLoadComplete.add(onLoad);
// 最小展示時間,示例為3秒
var deadLine = false;
setTimeout(function() {
deadLine = true;
}, 3000);
// 載入完畢回撥方法
function onLoad() {
if (deadLine) {
// 已到達最小展示時間,可以進入下一個場景
game.state.start('created');
} else {
// 還沒有到最小展示時間,1秒後重試
setTimeout(onLoad, 1000);
}
}
}
},
// 開始場景
created: function() {
this.create = function() {
// 新增背景
var bg = game.add.image(0, 0, 'bg');
bg.width = game.world.width;
bg.height = game.world.height;
}
},
// 遊戲場景
play: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#444';
setTimeout(function() {
game.state.start('over');
}, 3000);
}
},
// 結束場景
over: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#000';
alert('遊戲結束!');
}
}
};
// 新增場景到遊戲示例中
Object.keys(states).map(function(key) {
game.state.add(key, states[key]);
});
// 啟動遊戲
game.state.start('preload');
順帶豐富一下開始場景吧
// 開始場景
created: function() {
this.create = function() {
// 新增背景
var bg = game.add.image(0, 0, 'bg');
bg.width = game.world.width;
bg.height = game.world.height;
// 新增標題
var title = game.add.text(game.world.centerX, game.world.height * 0.25, '小恐龍接蘋果', {
fontSize: '40px',
fontWeight: 'bold',
fill: '#f2bb15'
});
title.anchor.setTo(0.5, 0.5);
// 新增提示
var remind = game.add.text(game.world.centerX, game.world.centerY, '點選任意位置開始', {
fontSize: '20px',
fill: '#f2bb15'
});
remind.anchor.setTo(0.5, 0.5);
// 新增主角
var man = game.add.sprite(game.world.centerX, game.world.height * 0.75, 'dude');
var manImage = game.cache.getImage('dude');
man.width = game.world.width * 0.2;
man.height = man.width / manImage.width * manImage.height;
man.anchor.setTo(0.5, 0.5);
// 新增點選事件
game.input.onTap.add(function() {
game.state.start('play');
});
}
}
示例程式碼中使用了input的onTap事件,那麼input實際上還有其他事件,例如下圖中框住的就是我們最常用的幾個事件:
-
onDown - 對應touchstart/mousedown
-
onUp - 對應touchend/mouseup
-
onHold - 封裝了長按事件的實現
-
onTap - 封裝了點選事件的實現
另外還有滑動事件:
// 實際應用場景改為window.innerWidth和window.innerHeight。
// 這裡是為了方便檢視示例。
var width = 320;
var height = 568;
// 建立遊戲例項
var game = new Phaser.Game(width, height, Phaser.AUTO, '#game');
// 定義場景
var states = {
// 載入場景
preload: function() {
this.preload = function() {
// 設定背景為黑色
game.stage.backgroundColor = '#000000';
// 載入遊戲資源
game.load.crossOrigin = 'anonymous'; // 設定跨域
game.load.image('bg', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bg.png');
game.load.image('dude', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/dude.png');
game.load.image('green', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/green.png');
game.load.image('red', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/red.png');
game.load.image('yellow', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/yellow.png');
game.load.image('bomb', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/bomb.png');
game.load.image('five', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/five.png');
game.load.image('three', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/three.png');
game.load.image('one', '//24haowan-cdn.shanyougame.com/pickApple2/assets/images/one.png');
game.load.audio('bgMusic', '//24haowan-cdn.shanyougame.com/pickApple2/assets/audio/bgMusic.mp3');
// 新增進度文字
var progressText = game.add.text(game.world.centerX, game.world.centerY, '0%', {
fontSize: '60px',
fill: '#ffffff'
});
progressText.anchor.setTo(0.5, 0.5);
// 監聽載入完一個檔案的事件
game.load.onFileComplete.add(function(progress) {
progressText.text = progress + '%';
});
// 監聽載入完畢事件
game.load.onLoadComplete.add(onLoad);
// 最小展示時間,示例為3秒
var deadLine = false;
setTimeout(function() {
deadLine = true;
}, 3000);
// 載入完畢回撥方法
function onLoad() {
if (deadLine) {
// 已到達最小展示時間,可以進入下一個場景
game.state.start('created');
} else {
// 還沒有到最小展示時間,1秒後重試
setTimeout(onLoad, 1000);
}
}
}
},
// 開始場景
created: function() {
this.create = function() {
// 新增背景
var bg = game.add.image(0, 0, 'bg');
bg.width = game.world.width;
bg.height = game.world.height;
// 新增標題
var title = game.add.text(game.world.centerX, game.world.height * 0.25, '小恐龍接蘋果', {
fontSize: '40px',
fontWeight: 'bold',
fill: '#f2bb15'
});
title.anchor.setTo(0.5, 0.5);
// 新增提示
var remind = game.add.text(game.world.centerX, game.world.centerY, '點選任意位置開始', {
fontSize: '20px',
fill: '#f2bb15'
});
remind.anchor.setTo(0.5, 0.5);
// 新增主角
var man = game.add.sprite(game.world.centerX, game.world.height * 0.75, 'dude');
var manImage = game.cache.getImage('dude');
man.width = game.world.width * 0.2;
man.height = man.width / manImage.width * manImage.height;
man.anchor.setTo(0.5, 0.5);
// 新增點選事件
game.input.onTap.add(function() {
game.state.start('play');
});
}
},
// 遊戲場景
play: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#444';
setTimeout(function() {
game.state.start('over');
}, 3000);
}
},
// 結束場景
over: function() {
this.create = function() {
// TO-DO
game.stage.backgroundColor = '#000';
alert('遊戲結束!');
}
}
};
// 新增場景到遊戲示例中
Object.keys(states).map(function(key) {
game.state.add(key, states[key]);
});
// 啟動遊戲
game.state.start('preload');
現在,開始介面是這樣子的:
小結
這一節我們介紹了載入場景,分步驟介紹了載入資源、監聽載入完成的事件以及新增一個最小的載入展示時間,其中“新增一個最小的載入展示時間”是偏實際應用的內容,非必須。
在文章的最後我們還向場景中加入了主角、背景、標題和開始提示等元素,來豐富開始場景。順帶一說,這次的示例是做一個接蘋果的遊戲,一句話說完就是控制主角接住每一個從天上掉下來的蘋果,否則就算輸。
那麼如何利用這些資源構建出遊戲的玩法,蘋果怎麼掉,怎麼控制主角等等,將是下一節的內容。