用Phaser來製做一個html5遊戲——flappy bird (一)

Phaser是一個簡單易用且功能強大的html5遊戲框架,利用它能夠很輕鬆的開發出一個html5遊戲。在這篇文章中我就教你們如何用Phaser來製做一個前段時間很火爆的遊戲:Flappy Bird,但願你們看後也能作出本身的html5遊戲。你們能夠先點擊這裏來試玩一下我已經作好的這個遊戲,感覺一下Phaser的遊戲效果,遊戲的完整代碼我已經放到github上了。支持的瀏覽器:IE9+、Firefox、Chrome、Opera、Safari以及移動端的能支持html5的瀏覽器,推薦使用谷歌瀏覽器,由於它性能最好。html

phaser.js的源碼能夠到它在github上的託管裏去下載,遊戲要用到的圖片聲音等素材資源請點擊這裏下載。Phaser的使用很是簡單,只須要引入它的主文件,而後在頁面中指定一個用來放置canvas的元素,而後實例化一個 Game 對象就能夠了。html5

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>game</title>
<script src="js/phaser.js"></script>
</head>
<body>
<div id="game"></div>
<script>
var game = new Phaser.Game(288,505,Phaser.AUTO,'game'); //實例化一個Phaser的遊戲實例
</script>
</body>
</html>
咱們來看看Phaser.Game這個函數都有哪些參數:
Phaser.Game(width, height, renderer, parent, state, transparent, antialias, physicsConfig)

width: 遊戲的寬度,也就是用來渲染遊戲的canvas的寬度,單位爲pxgit

height: 遊戲的高度,也就是用來渲染遊戲的canvas的高度,單位爲pxgithub

renderer: 使用哪一種渲染方式,Phaser.CANVAS 爲使用html5畫布,Phaser.WEBGL 爲使用性能更加好的WebGL來渲染,Phaser.AUTO爲自動偵測,若是瀏覽器支持WebGL則使用WebGL,不然使用Canvascanvas

parent: 用來放置canvas元素的父元素,能夠是一個元素id,也能夠是dom元素自己,phaser會自動建立一個canvas並插入到這個元素中。api

state: state能夠理解爲場景,在這裏指定state表示讓遊戲首先加載這個場景,但也能夠不在這裏指定state,而在以後的代碼中決定首先加載哪一個state。關於state我後面還會有詳細的說明。瀏覽器

transparent: 是否使用透明的canvas背景app

antialias: 是否啓用抗鋸齒框架

physicsConfig: 遊戲物理系統配置參數dom

以上全部參數都是可選的,它們的默認值以及更詳細的信息能夠看這裏,通常咱們只需指定前面那4到5個參數就好了。

 

實例化Game對象後,接下來要作的就是建立遊戲會用到的各類場景了,也就是上面說的state,那麼怎麼才能建立一個state呢?state能夠是一個js自定義對象,也能夠是一個函數,只要它們存在preload、create、update這三個方法中的任意一個,就是一個合法的state。

//state能夠是一個自定義對象
var state1 = {
    preload : function(){ },
    create : function(){ },
    update : function(){ }    
}

//state也能夠是一個構造函數
var state2 = function(){
    this.preload = function(){ };
    this.create = function(){ };
    this.update = function(){ };
}

//只要存在preload、create、update三個方法中的一個就能夠了
var state3 = function(){
    this.update = function(){  };
}

//固然state裏也能夠存在其餘屬性或方法
var state4 = function(){
    this.create = function(){ };
    this.aaa = function(){ }; //其餘方法
    this.bbb = 'hello'; //其餘屬性
}

 

其中的preload方法,是用來加載資源的,它會最早執行。create方法是用來初始化以及構建場景的,它要等到在preload里加載的資源所有加載完成後才執行。最後update方法是更新函數,它會在遊戲的每一幀都執行,以此來創造一個動態的遊戲。

在這個遊戲中,咱們會用到4個state,咱們能夠經過game.state.add()方法來給遊戲添加state,而後用game.state.start()方法來調用state,詳細信息請看state的文檔

var game = new Phaser.Game(288,505,Phaser.AUTO,'game'); 

game.States = {}; //建立一個對象來存放要用到的state
game.State.boot = function(){ ... }  //boot場景,用來作一些遊戲啓動前的準備
game.State.prelaod = function(){ ... } //prelaod場景,用來顯示資源加載進度
game.State.menu = function(){ ... } //menu場景,遊戲菜單
game.State.play = function(){ ... } //play場景,正式的遊戲部分

//把定義好的場景添加到遊戲中
game.state.add('boot',game.States.boot);
game.state.add('preload',game.States.preload); 
game.state.add('menu',game.States.menu); 
game.state.add('play',game.States.play);
 
//調用boot場景來啓動遊戲
game.state.start('boot');
 
 

製做資源加載進度條

遊戲要用到的一些圖片、聲音等資源都須要提早加載,有時候若是資源不少,就有必要作一個資源加載進度的頁面,提升用戶等待的耐心。這裏咱們用一個state來實現它,命名爲preload。

由於資源加載進度條須要一個進度條的背景圖片,因此在製做這個state前,咱們還須要另外一個最基礎的state,用來加載那張進度條圖片,咱們命名爲boot。

game.States.boot = function(){
    this.preload = function(){
        game.load.image('loading','assets/preloader.gif'); //加載進度條圖片資源
    };
    this.create = function(){
        game.state.start('preload'); //加載完成後,調用preload場景
    };
}

 

Phaser中資源的加載都是經過 Phaser.Loader 這個對象的方法來完成的,遊戲實例的load屬性就是指向當前遊戲的Loader對象,在咱們這裏就是game.load。Loader對象有許多方法,不一樣的方法能夠加載不一樣的資源,例如加載圖片咱們用的是game.load.image()方法,具體的方法列表請自行參考文檔

在preload這個場景中,咱們須要把遊戲後面會用到的全部資源都進行加載,而後還要展現一個加載進度條給用戶看。Loader對象提供了一個 setPreloadSprite 方法,只要把一個sprite對象指定給這個方法,那麼這個sprite對象的寬度或高度就會根據當前加載的百分比自動調整,達到一個動態的進度條的效果。

game.States.preload = function(){
    this.preload = function(){
        var preloadSprite = game.add.sprite(50,game.height/2,'loading'); //建立顯示loading進度的sprite
        game.load.setPreloadSprite(preloadSprite);  //用setPreloadSprite方法來實現動態進度條的效果
        
        //如下爲要加載的資源
        game.load.image('background','assets/background.png'); //遊戲背景圖
        game.load.image('ground','assets/ground.png'); //地面
        game.load.image('title','assets/title.png'); //遊戲標題
        game.load.spritesheet('bird','assets/bird.png',34,24,3); //
        game.load.image('btn','assets/start-button.png');  //按鈕
        game.load.spritesheet('pipe','assets/pipes.png',54,320,2); //管道
        game.load.bitmapFont('flappy_font', 'assets/fonts/flappyfont/flappyfont.png', 'assets/fonts/flappyfont/flappyfont.fnt');//顯示分數的字體
        game.load.audio('fly_sound', 'assets/flap.wav');//飛翔的音效
        game.load.audio('score_sound', 'assets/score.wav');//得分的音效
        game.load.audio('hit_pipe_sound', 'assets/pipe-hit.wav'); //撞擊管道的音效
        game.load.audio('hit_ground_sound', 'assets/ouch.wav'); //撞擊地面的音效

        game.load.image('ready_text','assets/get-ready.png'); //get ready圖片
        game.load.image('play_tip','assets/instructions.png'); //玩法提示圖片
        game.load.image('game_over','assets/gameover.png'); //gameover圖片
        game.load.image('score_board','assets/scoreboard.png'); //得分板
    }
    this.create = function(){
        game.state.start('menu'); //當以上全部資源都加載完成後就能夠進入menu遊戲菜單場景了
    }
}

上面咱們提到了Sprite對象,也就是遊戲開發中俗稱的精靈,一樣在Phaser中sprite對象也是製做遊戲過程當中用得最多的也是最重要的一個對象之一。咱們能夠用一幅圖片來建立一個sprite,而後用Phaser提供給咱們的衆多屬性和方法來對它進行操做。上面咱們是利用game.add.sprite()來建立sprite的,而且建立後會自動把它添加到當前的遊戲中,game.add表明的是Phaser.GameObjectFactory對象,該對象提供了了一系列快捷方法來方便咱們建立遊戲的各類組件。咱們這裏製做的資源加載進度頁面很是簡單,大概就是下面這個樣子:

1

 

製做遊戲菜單頁面

資源加載完成後就該進入到遊戲菜單頁面了,說是菜單頁,但咱們這裏只是提供一個開始遊戲的按鈕而已,做爲教程就別搞那麼複雜啦。作好後的效果以下:

menu下面咱們就來實現這個頁面。

首先是背景圖與地面,咱們看到這兩個東西是會動的,地面移動動的速度快一些,背景圖慢一些,在Phaser中有專門的東西來處理這種效果,叫作TileSprite,什麼是TileSprite呢?TileSprite本質上仍是一個sprite對象,不過這個sprite的貼圖是能夠移動的,而且會自動平鋪來彌補移動後的空缺,因此咱們的素材圖片要是平鋪後看不出有縫隙,就能夠拿來當作TileSprite的移動貼圖了。TileSprite的貼圖既能夠水平移動也能夠垂直移動,或者二者同時移動,咱們只須要調用TileSprite對象的autoScroll(x,y)方法就可使它的貼圖動起來了,其中x是水平方向的速度,y是垂直方向的速度。

game.States.menu = function(){
    this.create = function(){
        var bg = game.add.tileSprite(0,0,game.width,game.height,'background'); //看成背景的tileSprite 
        var ground = game.add.tileSprite(0,game.height-112,game.width,112,'ground').autoScroll(-100,0); //看成地面的tileSprite
        bg.autoScroll(-10,0); //讓背景動起來
        ground.autoScroll(-100,0); //讓地面動起來
    }
}

 

而後來製做遊戲標題,遊戲標題flappy bird這幾個字是一張圖片,而後那個鳥是一個sprite,而且咱們在sprite上執行了動畫,使它的翅膀看起來是在動的。我要說的是怎麼在sprite對象上實現動畫。首先在加載鳥的圖片時,咱們加載的不當當就是一張鳥的圖片,咱們加載的是一個這樣的圖片:bird

咱們看到這張圖片有三隻鳥,更確切的說是一隻鳥的三個狀態,或者說是動畫中的三個幀。那咱們怎樣讓他變成動畫呢?在Loader對象中有一個spritesheet的方法,就是專門用來加載這種多幀圖片的,咱們看一下這個方法:

spritesheet(key, url, frameWidth, frameHeight, frameMax, margin, spacing)

key : 給這張圖片指定的名稱,之後在建立sprite等對象時會要用到的

url: 圖片的地址

frameWidth :  圖片中每幀的寬度

frameHeight : 圖片中每幀的高度

frameMax : 最多有幾幀

margin : 每幀的外邊距

spacing : 每幀之間的間隔

咱們上面那張鳥的圖片,每個鳥的寬高分別是34px和24px,因此frameWidth應該是34,frameHeight是24,而後咱們這個動畫有三幀,frameMax爲3,幀與幀之間沒有間隙,margin與spacing都爲0。實際上spritesheet方法就是能讓咱們加載一個圖片,並在這個圖片上劃分出幀來,之後使用這個圖片的sprite就能夠用這些幀來播放動畫啦。要在sprite上實現動畫,咱們首先還得先定義一個動畫,就是定義這個動畫是由哪些幀組成的。sprite對象有個animations屬性,表明的是Phaser中專門管理動畫的對象:AnimationManager,該對象有一個add方法,用來添加動畫,還有一個play方法,用來播放動畫,它們具體的參數能夠參閱文檔。

下面再說一個很是重要的對象:Phaser.Group,也就是組。組至關於一個父容器,咱們能夠把許多對象放進一個組裏,而後就可使用組提供的方法對這些對象進行一個批量或是總體的操做。好比要使組裏的對象贊成進行一個位移,只須要對組進行位移就能夠了,又好比要對組裏的全部對象都進行碰撞檢測,那麼就只須要對這個組對象進行碰撞檢測就好了。下面咱們要製做的這個遊戲標題是由一張文字圖片和一支鳥組成的,咱們就是把這兩個東西放在一個組中,而後來進行總體的操做。

game.States.menu = function(){
    this.create = function(){
        ......
        
        var titleGroup = game.add.group(); //建立存放標題的組
        titleGroup.create(0,0,'title'); //經過組的create方法建立標題圖片並添加到組裏
        var bird = titleGroup.create(190, 10, 'bird'); //建立bird對象並添加到組裏
        bird.animations.add('fly'); //給鳥添加動畫
        bird.animations.play('fly',12,true); //播放動畫
        titleGroup.x = 35; //調整組的水平位置
        titleGroup.y = 100; //調整組的垂直位置
        game.add.tween(titleGroup).to({ y:120 },1000,null,true,0,Number.MAX_VALUE,true); //對這個組添加一個tween動畫,讓它不停的上下移動
    }
}

 

 

上面代碼中的Tween對象,是專門用來實現補間動畫的。經過game.add的tween方法獲得一個Tween對象,這個方法的參數是須要進行補間動畫的物體。而後咱們可使用Tween對象的to方法來實現補間動畫。

 

to(properties, duration, ease, autoStart, delay, repeat, yoyo)

properties :  一個js對象,裏面包含着須要進行動畫的屬性,如上面代碼中的 {y:120}

duration : 補間動畫持續的時間,單位爲毫秒

ease : 緩動函數,默認爲勻速動畫

autoStart : 是否自動開始

delay : 動畫開始前的延遲時間,單位爲毫秒

repeat : 動畫重複的次數,若是須要動畫永遠循環,則把該值設爲 Number.MAX_VALUE

yoyo : 若是該值爲true,則動畫會自動反轉

 

最後是添加一個開始遊戲的按鈕。Phaser提供了Button對象讓咱們能很簡單的實現一個按鈕。

game.States.menu = function(){
    this.create = function(){
        ......

        var btn = game.add.button(game.width/2,game.height/2,'btn',function(){//添加一個按鈕
            game.state.start('play'); //點擊按鈕時跳轉到play場景
        });
        btn.anchor.setTo(0.5,0.5); //設置按鈕的中心點
    }
}

 

Phaser中不少對象都有一個anchor屬性,它表示這個物體的中心點,物體的位置平移、旋轉的軸,都是以這個中心點爲參照的。因此上面代碼中咱們要使按鈕水平垂直居中,除了要把按鈕的x,y屬性分別設爲遊戲的寬高的一半外,還要把按鈕的中心點設爲按鈕的中心。

 

最後咱們把全部代碼合起來,獲得了menu這個state的最終代碼,該state只須要一個create方法就好了:

game.States.menu = function(){
    this.create = function(){
        game.add.tileSprite(0,0,game.width,game.height,'background').autoScroll(-10,0); //背景圖
        game.add.tileSprite(0,game.height-112,game.width,112,'ground').autoScroll(-100,0); //地板
        var titleGroup = game.add.group(); //建立存放標題的組
        titleGroup.create(0,0,'title'); //標題
        var bird = titleGroup.create(190, 10, 'bird'); //添加bird到組裏
        bird.animations.add('fly'); //添加動畫
        bird.animations.play('fly',12,true); //播放動畫
        titleGroup.x = 35;
        titleGroup.y = 100;
        game.add.tween(titleGroup).to({ y:120 },1000,null,true,0,Number.MAX_VALUE,true); //標題的補間動畫
        var btn = game.add.button(game.width/2,game.height/2,'btn',function(){//按鈕
            game.state.start('play');
        });
        btn.anchor.setTo(0.5,0.5);
    }
}

 

第二部分教程:

用Phaser來製做一個html5遊戲——flappy bird (二)

相關文章
相關標籤/搜索