一直想嘗試html5游戲的制作,閑來無事,發現了phaser這個html5的游戲開發框架,嘗試完成一個小游戲,此博文就作為自己的開發和學習的記錄。
1 什么是Phaser
Phaser是一個開源的桌面和移動HTML5 2D游戲開發框架,官網地址: http://www.phaser.io/
2 環境搭建
沒什么說的,官網下載phaser的js文件,html頁面進行引入
3 創建項目
創建一個項目文件StarCrash,文件層級如下:
assets: 存放項目需要用到的圖片,聲音,字體等資源
js : 存放項目需要用到的js文件,下載的phaser.min.js 可以放在此文件夾下
index.html : 游戲頁面html
4 開始搬磚
phaser代碼的基本結構
var game = new Phaser.Game(320, 568, Phaser.AUTO, 'StarCrash', { preload: preload, create: create, update: update}); //加載資源 function preload() { } //創建場景 function create(){ } //更新場景 function update(){ }
加載游戲資源
function preload() { //加載資源
game.load.image('bullet', 'assets/bullet.png');
game.load.image('e_bullet', 'assets/enemy-bullet.png');
game.load.spritesheet('s_explode', 'assets/smallexplode.png',64,64);
game.load.spritesheet('explode', 'assets/explode.png',128,128);
game.load.image('invader', 'assets/invader.png');
game.load.image('m_invader', 'assets/invader32x32x4.png');
game.load.image('player', 'assets/player.png');
game.load.image('background', 'assets/starfield.png');
}
使用的游戲資源都為phaser demo內的圖片,聲音暫未添加。
創建游戲場景
使用之前加載的游戲資源對游戲對象飛機子彈,敵人子彈,爆炸動畫,敵人都是以組(池)的方式進行創建,減少內存的創建和回收。監控鍵盤輸入對飛機對象進行操作。
function create(){ //創建背景 background = game.add.tileSprite(0, 0, 320,568, 'background'); game.physics.enable(background,Phaser.Physics.ARCADE); //創建飛機 player = game.add.sprite(160, 520, 'player'); player.anchor.setTo(0.5, 0.5); game.physics.enable(player, Phaser.Physics.ARCADE); //防止飛機飛出邊界 player.body.collideWorldBounds = true; //創建飛機子彈 bullets = game.add.group(); bullets.enableBody = true; bullets.physicsBodyType = Phaser.Physics.ARCADE; bullets.createMultiple(50, 'bullet'); bullets.setAll('anchor.x', 0.5); bullets.setAll('anchor.y', 1); bullets.setAll('outOfBoundsKill', true); bullets.setAll('checkWorldBounds', true); //創建敵人子彈組 ebullets = game.add.group(); ebullets.enableBody = true ; ebullets.physicsBodyType = Phaser.Physics.ARCADE; ebullets.createMultiple(30,'e_bullet'); ebullets.setAll('anchor.x',0.5); ebullets.setAll('anchor.y',1); ebullets.setAll('outOfBoundsKill', true); ebullets.setAll('checkWorldBounds', true); enemy = new Enemy(); enemy.init(); //創建爆炸動畫 explosions = game.add.group(); explosions.createMultiple(30, 's_explode'); explosions.forEach(enemyExplosion, this); //得分 scoreStr = "分數:" scoreText = game.add.text(game.world.centerX,16,scoreStr + score, { font: '16px Arial', fill: '#fff' }); scoreText.anchor.setTo(0.5,0.5); //提示信息 infoText = game.add.text(game.world.centerX,game.world.centerY,' ', { font: '24px Arial', fill: '#fff' }); infoText.anchor.setTo(0.5, 0.5); infoText.visible = false; //控制 cursors = game.input.keyboard.createCursorKeys(); fireButton = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); }
創建敵人
創建敵人方法
//敵人 function Enemy(){ this.init = function () { //初始化創建創建敵人池 this.enemies = game.add.group(); this.enemies.enableBody = true; this.enemies.physicsBodyType = Phaser.Physics.ARCADE; this.enemies.createMultiple(50, 'invader'); this.enemies.setAll('anchor.x', 0.5); this.enemies.setAll('anchor.y', 0.5); this.enemies.setAll('outOfBoundsKill', true); this.enemies.setAll('checkWorldBounds', true); this.maxWidth = game.width - game.cache.getImage('invader').width; // 產生敵人的定時器 game.time.events.loop(Phaser.Timer.SECOND * 2, this.create, this); } //創建敵人 this.create =function(){ enemyobj = this.enemies.getFirstExists(false); if(enemyobj){ enemyobj.reset(game.rnd.integerInRange(0, this.maxWidth), game.cache.getImage('invader').height); enemyobj.body.velocity.y = 50; } } // this.crashPlayer = function(player,enemy){ enemy.kill(); playerDead(); } this.shootPlayer = function (player,ebullet) { ebullet.kill(); playerDead(); } this.fire = function () { liveEnemies.length = 0; //存活的敵人 this.enemies.forEachAlive(function (obj) { liveEnemies.push(obj); }); //獲取敵人子彈 ebullet = ebullets.getFirstExists(false); if(ebullet && liveEnemies.length > 0){ //隨機敵人的索引 var random=game.rnd.integerInRange(0,liveEnemies.length-1); //獲取隨機敵人 var ranEnemy = liveEnemies[random]; //子彈從敵人位置射出 ebullet.reset(ranEnemy.body.x + 8,ranEnemy.body.y + 16); //子彈射向飛機 game.physics.arcade.moveToObject(ebullet,player,120); EFireTimer = game.time.now + 2000; } } }
更新場景
實現背景頁面的滾動,玩家的操作反饋
function update(){ // Scroll the background background.tilePosition.y += 3; player.body.velocity.setTo(0, 0); //左 if(cursors.left.isDown){ player.body.velocity.x = -200; } //右 else if (cursors.right.isDown) { player.body.velocity.x = 200; } //上 else if(cursors.up.isDown){ player.body.velocity.y = -200; } //下 else if(cursors.down.isDown){ player.body.velocity.y = 200; } // 發射子彈 if (fireButton.isDown) { fireBullet(); } //敵人發射子彈 if (game.time.now > EFireTimer) { enemy.fire(); } //飛機碰撞敵人 game.physics.arcade.overlap(enemy.enemies ,player, enemy.crashPlayer, null, this); //子彈碰撞敵人 game.physics.arcade.overlap(bullets,enemy.enemies , hitEnemy, null, this); //敵人子彈碰撞飛機 game.physics.arcade.overlap(ebullets,player,enemy.shootPlayer,null,this); }
玩家發射子彈
function fireBullet(){ if(game.time.now > bullettime){ // 獲取子彈組里的第一顆子彈 bullet = bullets.getFirstExists(false); if(bullet){ bullet.reset(player.x, player.y - 8); bullet.body.velocity.y = -300; bullettime = game.time.now + 500; } } }
擊中敵人
//擊中敵人 function hitEnemy(bullet,enemy){ bullet.kill(); //播放爆炸動畫 var explosion = explosions.getFirstExists(false); explosion.reset(enemy.body.x,enemy.body.y); explosion.play('s_explode', 10, false, true); //刷新得分 score += 1; scoreText.text = scoreStr + score; enemy.kill(); }
敵人爆炸
//敵人爆炸 function enemyExplosion(obj) { obj.anchor.x = 0.5; obj.anchor.y = 0.5; obj.animations.add('s_explode'); }
飛機爆炸
//飛機爆炸 function playerDead(){ player.kill(); //播放爆炸動畫 var explosion = explosions.getFirstExists(false); explosion.reset(player.body.x,player.body.y); explosion.play('s_explode', 30, false, true); //顯示游戲結束文字 infoText.text = " GAME OVER \n Click to restart"; infoText.visible = true; //點擊重新開始 game.input.onTap.addOnce(restartGame,this); }
重新開始
//重新開始 function restartGame(){ //清除敵人 enemy.enemies.callAll('kill'); //清除敵人子彈 ebullets.callAll('kill'); //隱藏gameover infoText.visible = false; //刷新分數 score = 0; scoreText.text = scoreStr + score; //復活玩家 player.revive().reset(160,520); }
至此,簡單的飛機游戲就完成了,有幾點不足之處:
(1)沒有加載聲音資源
(2)未實現不同類型敵人,后續可以擴展敵人方法,增加不同敵人類型
代碼比較丑陋,也是抱着學習phaser的態度,未對代碼進行優化,也算是phaser的基本入門吧,游戲比較簡單,后期擴展的點還是挺多的,有時間可以繼續優化。