1. 程式人生 > >從零到一:用Phaser.js寫意地開發小遊戲(Chapter 3

從零到一:用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'8080);
載入資源集合

同樣可以用作載入圖片序列,但這種用法主要用於載入類似於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');

現在,開始介面是這樣子的:

小結

這一節我們介紹了載入場景,分步驟介紹了載入資源、監聽載入完成的事件以及新增一個最小的載入展示時間,其中“新增一個最小的載入展示時間”是偏實際應用的內容,非必須。

在文章的最後我們還向場景中加入了主角、背景、標題和開始提示等元素,來豐富開始場景。順帶一說,這次的示例是做一個接蘋果的遊戲,一句話說完就是控制主角接住每一個從天上掉下來的蘋果,否則就算輸。

那麼如何利用這些資源構建出遊戲的玩法,蘋果怎麼掉,怎麼控制主角等等,將是下一節的內容。

未完待續