使用Phaser開發你的第一個H5遊戲(一)
本文來自網易雲社群
作者:王鴿
不知你是否還記得當年風靡一時的2048這個遊戲,一個簡單而又不簡單的遊戲,總會讓你在空閒時間玩上一會兒。
在這篇文章裡,我們將使用開源的H5框架——Phaser來重現這個遊戲。這裡你可以瞭解到遊戲內的狀態管理、Sprite元件物件等,以及如何使用Preload、Create等方法。
H5遊戲框架眾多,為何選擇它?
由於近幾年H5的火熱,H5遊戲框架如雨後春筍般出現,甚至有很多定位不是遊戲開發的框架都被歸到這個範疇中。那麼為什麼選擇Phaser?以下是我選擇它的原因:
支援原生JS。
可以方便地在Canvas和WebGL之間切換。
定位明確,專注H5遊戲開發。
完善的文件及示例。
持續更新,目前Phaser 3正在開發。
2048遊戲的最終呈現效果如下
開發準備
首先訪問Phaser官網http://www.phaser.io,下載JavaScript版本的Phaser,並搭建好專案結構
專案檔案結構如下:
在index.html中引入相關js檔案,定義一個div作為phaser生成canvas的父容器
<!DOCTYPE html> <head> <meta charset="UTF-8" /> <title>2048</title> <script src="js/phaser.min.js"></script> <script src="js/Menu.js"></script> <script src="js/Game.js"></script> <script src="js/index.js"></script> <style> body { margin: 0; padding: 0; } canvas { margin: 0 auto; } .game { position: absolute; width: 100%; height: 100%; } </style> </head> <body> <div id="game" >"game"></div> </body>
遊戲是如何進行的
在html檔案中我們已經引入了Phaser庫,這使我們擁有了一個名為Phaser的全域性物件,通過這個物件,我們可以訪問Phaser庫中哪些用於構建遊戲的方法和函式。
現在我們使用Phaser物件來建立一個遊戲例項,這個物件用來代表整個遊戲,我們會為他新增不同的狀態。
index.js,在其中建立遊戲例項,註冊各個遊戲狀態以及啟動遊戲。
//例項化遊戲物件,引數為寬、高、渲染方式,父容器 window.game = new Phaser.Game(240, 400, Phaser.CANVAS, 'game'); //新增狀態,引數為狀態應用的Key值,狀態所包含的物件 game.state.add('Menu', Menu); game.state.add('Game', Game); //狀態切換 開始遊戲 game.state.start('Menu');
Phaser中的“狀態(state)”管理使遊戲的場景切換變得非常容易,此處的“狀態”可以看理解為不同的遊戲介面,2048這個遊戲比較簡單,只需要首頁和遊戲內兩個介面即可。
主頁狀態,由menu.js處理,用於載入遊戲資源並顯示遊戲開始介面,點選開始按鈕後切換到遊戲狀態並且開始遊戲。
遊戲狀態,由game.js處理,用於顯示遊戲介面、控制遊戲邏輯,遊戲結束後顯示分數面板
接下來初始化選單狀態物件(Menu),在Menu.js中定義一個新物件Menu併為它新增函式。狀態啟動時,首先會呼叫物件內的preload函式,通常載入遊戲所需資源會在這一步進行;載入完成後,呼叫create函式,初始化遊戲介面以及邏輯物件等等。
var Menu = { preload: function () { //載入影象,引數為建立元件時所使用的Key值,檔案路徑 game.load.image('background', 'assets/bg.png'); game.load.image('btnStart', 'assets/btn-start.png'); game.load.image('btnRestart', 'assets/btn-restart.png'); game.load.image('logo', 'assets/logo.png'); game.load.image('btnTryagain', 'assets/btn-tryagain.png'); }, create: function () { //建立重複元件,可以重複圖片 一般用於重複紋理的底圖等 game.add.tileSprite(0, 0, game.width, game.height, 'background'); //建立圖片,此處是遊戲logo,引數為x,y,載入圖片是所儲存的Key值 var logo = game.add.image(0, 0, 'logo'); logo.reset((game.width - logo.width) / 2, (game.height - logo.height) / 2 - 50); //開始按鈕用來啟動遊戲 var startBtn = game.add.sprite(0, 0, 'btnStart'); startBtn.reset((game.width - startBtn.width) / 2, (game.height - startBtn.height) / 2 + 100); //開啟元件點選監聽,並新增監聽事件 startBtn.inputEnabled = true; startBtn.events.onInputDown.add(this.startGame); }, startGame: function () { //轉換狀態至遊戲介面 game.state.start('Game'); } };
至此,啟動介面已經完成了,開啟本地web伺服器後,在瀏覽器中開啟index.html,就可以看到遊戲的啟動介面了。
接著在Game.js開始處理遊戲的介面以及邏輯
var Game = { create: function () { //新增背景 game.add.tileSprite(0, 0, game.width, game.height, 'background'); //變數用於儲存遊戲分數 this.score = 0; this.best = 0; //文字樣式,font:字型字號等 fill:顏色 var titleStyle = { font: "bold 12px Arial", fill: "#4DB3B3", boundsAlignH: "center" }; var scoreStyle = { font: "bold 20px Arial", fill: "#FFFFFF", boundsAlignH: "center" }; var scoreSprite = game.add.sprite(10, 10); //使用graphics繪製圖形作為介面UI var scoreGraphics = game.add.graphics(0, 0); scoreGraphics.lineStyle(5, 0xA1C5C5); scoreGraphics.beginFill(0x308C8C); //繪製一個帶圓角的矩形 scoreGraphics.drawRoundedRect(0, 0, 70, 50, 10); scoreGraphics.endFill(); //把圖形新增到父容器上,便於整體調整位置等 scoreSprite.addChild(scoreGraphics); //新增文字 引數為x,y,文字內容,文字樣式 var scoreTitle = game.add.text(0, 5, "SCORE", titleStyle); scoreTitle.setTextBounds(0, 0, 70, 50); //把文字新增到父容器上,便於整體調整位置等 scoreSprite.addChild(scoreTitle); this.scoreText = game.add.text(0, 20, this.score, scoreStyle); this.scoreText.setTextBounds(0, 0, 70, 50); scoreSprite.addChild(this.scoreText); ...... //新增鍵盤方向件的監聽以及監聽事件 var up = this.game.input.keyboard.addKey(Phaser.Keyboard.UP); up.onDown.add(function () {...}); var down = this.game.input.keyboard.addKey(Phaser.Keyboard.DOWN); down.onDown.add(function () {...}); var left = this.game.input.keyboard.addKey(Phaser.Keyboard.LEFT); left.onDown.add(function () {...}); var right = this.game.input.keyboard.addKey(Phaser.Keyboard.RIGHT); right.onDown.add(function () {...}); ...... //獲取手勢滑動的X軸差值和Y軸差值 用於計算滑動方向 var deltaX = this.game.input.activePointer.position.x - this.game.input.activePointer.positionDown.x; var deltaY = this.game.input.activePointer.position.y - this.game.input.activePointer.positionDown.y; ......
2048這個遊戲的規則非常簡單,開發的思路也非常明確,維護一個4*4的陣列,每次觸發移動事件時遍歷陣列,進行方向上的疊加判斷,然後在陣列中尋找空格,隨機生成新的數字,如果沒有則遊戲結束。相關的一些開發思路以及演算法優化在此也就不詳述了,大家可以自行查閱。
資料推薦
雖然這個遊戲非常簡單,但通過這個專案,可以瞭解到Phaser的多個方面。如果對此感興趣,可以再深入接觸以下資料:
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社群。
相關文章:
【推薦】 #3.14 Piday#我的圓周率日
【推薦】 網易雲資料庫架構設計實踐