[phaser3入门探坑]使用phaser3制作山寨马里奥
前言
phaser是一個優秀的前端canvas庫,封裝了很多底層的實現,可以用來制作游戲,h5場景等。今年1月新發布了phaser3,到今天為止已經更新到了3.30。
聲明
本游戲來自于phaser小站的官方教程,加入了一些個人的注釋,本文旨在幫助各位觀眾老爺快速上手。各位看官也可以直接移步phaser官網查看教程
小貼士
每一個步驟后面都貼了代碼,如果因為我的寫作方式讓您難以接受,可以直接到每個步驟后面復制代碼
準備工作
你需要一份phaser3.js
也可能需要一份文檔
如果有一份隨時查閱的范例當然更好
一個本地服務器
一份包含素材的空[項目]()
開始制作
這里是為觀眾老爺們準備的github倉庫,有我們需要的素材和腳本文件
git clone https://github.com/YexChen/canvas_game.git制作基本的游戲場景
打開我們的項目文件夾,修改index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="js/phaser.min.js"></script><style>body{}</style> </head> <body><script>//生成配置文件const config = {//初始化游戲類型type : Phaser.AUTO,width : 800,height : 600,//物理引擎physics : {default : 'arcade',arcade : {//重力設置gravity : {y : 300},debug : false}},//場景設置scene : {preload,create,update}}//初始化游戲let game = new Phaser.Game(config)//游戲主要函數function preload(){}function create(){}function update(){}</script> </body> </html>然后在命令行運行http-server,打開瀏覽器,效果是不是出來了呢?
加載主要素材
在preload函數中加入以下代碼段:
this.load.image("sky","./img/sky.png")this.load.image("star","./img/star.png")this.load.image("ground","./img/platform.png")this.load.image("bomb","./img/bomb.png")this.load.spritesheet("dude","./img/dude.png",{frameWidth:32,frameHeight:48})spritesheet是精靈圖的加載方式,frameWidth是每幀的寬度,frameHeight是幀的高度,有興趣的朋友們可以量一量
加載主要場景
摸了這么久的魚,也該看點成果了吧,我們來制作主場景:
在create函數中加入:
保存,刷新,我們的界面上是不是出現了一片藍天呢?
讓我們來繼續添加場景吧,緊跟著上一句輸入以下代碼:
platforms = this.physics.add.staticGroup()platforms.create(400,568,"ground").setScale(2,2).refreshBody()platforms.create(600,400,"ground")platforms.create(0,300,"ground")platforms.create(600,200,"ground")platforms.create(0,100,"ground") create(x,y,imagename) selScale(x,y):把圖片縮放x,y倍,如果不設置y的話就按x的倍數縮放 這個refreshbody大家可以去掉,后面會有驚喜的這樣場景就繪制出來了,各位看官也可以自己設置參數,制作屬于自己的游戲場景
盡量不要做出這種反人類設計就行。。emmm,你的游戲你做主咯
可能內容多,大家可能會打錯地方,發一下完整的代碼段:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="js/phaser.min.js"></script><style>body{}</style> </head> <body><script>//生成配置文件const config = {//初始化游戲類型type : Phaser.AUTO,width : 800,height : 600,//物理引擎physics : {default : 'arcade',arcade : {//重力設置gravity : {y : 300},debug : false}},//場景設置scene : {preload,create,update}}//初始化游戲let game = new Phaser.Game(config)//游戲主要函數function preload(){this.load.image("sky","./img/sky.png")this.load.image("star","./img/star.png")this.load.image("ground","./img/platform.png")this.load.image("bomb","./img/bomb.png")this.load.spritesheet("dude","./img/dude.png",{frameWidth:32,frameHeight:48})}function create(){this.add.image(400,300,"sky")platforms = this.physics.add.staticGroup()platforms.create(400,568,"ground").setScale(2,2).refreshBody()platforms.create(600,400,"ground")platforms.create(0,300,"ground")platforms.create(600,200,"ground")platforms.create(0,100,"ground")}function update(){}</script> </body> </html>人物的制作
什么都有了,主角怎么能少呢? 緊接著上一行,寫下代碼: player = this.physics.add.sprite(100,450,'dude')刷新一下,是不是看到我們的男主角生成出來。。然后又入土為安了呢?
聰明的你應該會想到:是缺少了碰撞函數,那么,讓我們來添加碰撞函數吧,緊接著添加:
刷新頁面,哇塞
嗯,這不是我們想要的結果,至少不是我的。。我們好像忘記給障礙物添加碰撞了,我們來加一下吧:
this.physics.add.collider(player,platforms) 大家還記得哪個refreshbody嗎?如果你當時刪掉了它,那么碰撞就還是不會成立(話說這種東西作者去內置一個方法不就好了么)這里貼出目前完整的代碼:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="js/phaser.min.js"></script><style>body{}</style> </head> <body><script>//生成配置文件const config = {//初始化游戲類型type : Phaser.AUTO,width : 800,height : 600,//物理引擎physics : {default : 'arcade',arcade : {//重力設置gravity : {y : 300},debug : false}},//場景設置scene : {preload,create,update}}//初始化游戲let game = new Phaser.Game(config)//游戲主要函數function preload(){this.load.image("sky","./img/sky.png")this.load.image("star","./img/star.png")this.load.image("ground","./img/platform.png")this.load.image("bomb","./img/bomb.png")this.load.spritesheet("dude","./img/dude.png",{frameWidth:32,frameHeight:48})}function create(){this.add.image(400,300,"sky")platforms = this.physics.add.staticGroup()platforms.create(400,568,"ground").setScale(2,2).refreshBody()platforms.create(600,400,"ground")platforms.create(0,300,"ground")platforms.create(600,200,"ground")platforms.create(0,100,"ground")player = this.physics.add.sprite(100,450,'dude')player.setBounce(0.2)player.setCollideWorldBounds(true)this.physics.add.collider(player,platforms)}function update(){}</script> </body> </html>添加動畫效果和鍵盤控制器
要是不能操控的話,那這游戲也太佛系了,我們來添加一動畫效果吧
Phaser類有個anims成員,用來管理所有的動畫效果(說白了就是改變圖片嘛),接下來我們通過代碼感受一下,添加到上述代碼后面:
然后我們初始化遙控器吧:
cursors = this.input.keyboard.createCursorKeys()按下鍵盤方向鍵上下左右,誒?為什么沒反應?
我們好像忘記在update函數中監聽鍵盤了,難怪沒反應,
在update函數中添加以下代碼:
好,現在移動我們人物,哇,走的怎么這么慢!各位自己改下參數吧,每個人都有不同的游戲愛好,你一定可以找到最適合自己的配置的,當然啦,也可以玩出滑冰模式,月球模式,鬼畜模式,神仙模式,鬼人正邪模式等等。。開發游戲主要靠想象力對吧
貼一下我們的代碼
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="js/phaser.min.js"></script><style>body{}</style> </head> <body><script>//生成配置文件const config = {//初始化游戲類型type : Phaser.AUTO,width : 800,height : 600,//物理引擎physics : {default : 'arcade',arcade : {//重力設置gravity : {y : 300},debug : false}},//場景設置scene : {preload,create,update}}//初始化游戲let game = new Phaser.Game(config)//游戲主要函數function preload(){this.load.image("sky","./img/sky.png")this.load.image("star","./img/star.png")this.load.image("ground","./img/platform.png")this.load.image("bomb","./img/bomb.png")this.load.spritesheet("dude","./img/dude.png",{frameWidth:32,frameHeight:48})}function create(){this.add.image(400,300,"sky")platforms = this.physics.add.staticGroup()platforms.create(400,568,"ground").setScale(2,2).refreshBody()platforms.create(600,400,"ground")platforms.create(0,300,"ground")platforms.create(600,200,"ground")platforms.create(0,100,"ground")player = this.physics.add.sprite(100,450,'dude')player.setBounce(0.2)player.setCollideWorldBounds(true)this.physics.add.collider(player,platforms)this.anims.create({key : 'left',frames : this.anims.generateFrameNumbers('dude',{start : 0,end : 3}),frameRate : 10,repeat : -1})this.anims.create({key : 'turn',frames : [{key : 'dude',frame : 4}],frameRate : 20})this.anims.create({key : 'right',frames : this.anims.generateFrameNumbers('dude',{start : 5,end : 8}),frameRate : 10,repeat : -1})cursors = this.input.keyboard.createCursorKeys()}function update(){if(cursors.left.isDown){player.setVelocityX(-50)player.anims.play("left",true)}else if(cursors.right.isDown){player.setVelocityX(50)player.anims.play("right",true)}else{player.setVelocityX(0)player.anims.play('turn')}if(cursors.up.isDown && player.body.touching.down){player.setVelocityY(-300)}}</script> </body> </html>早苗教你畫星星
好了,人物有了,接下來應該做點道具了吧,我們來畫點星星,在create函數中添加代碼:
stars = this.physics.add.group({key : 'star',repeat : 11,setXY : {x: 20,y: 0,stepX:70}})stars.children.iterate(function(child){//設置一下碰撞效果child.setBounceY(Phaser.Math.FloatBetween(0.4,0.8))})this.physics.add.collider(stars,platforms) 我們初始化了一些星星,添加了小小的碰撞效果,然而。。。并不能吃到星星!就像一大盤香噴噴羊蝎子在你面前你卻不能吃(我這篇博客定到晚12點發就好了)
因為沒有寫星星和男主的碰撞函數,我們來在后面寫一行
this.physics.add.overlap(player,stars,collectStar,null,this) overlap(obj1,obj2,overcallback,processcallback,回掉中的上下文(this))然后在文件底部加一個函數:
function collectStar(player,star){//讓star實體消失star.disableBody(true,true)}好了,現在可以正常的吃星星了
貼上目前的代碼段:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="js/phaser.min.js"></script><style>body{}</style> </head> <body><script>//生成配置文件const config = {//初始化游戲類型type : Phaser.AUTO,width : 800,height : 600,//物理引擎physics : {default : 'arcade',arcade : {//重力設置gravity : {y : 300},debug : false}},//場景設置scene : {preload,create,update}}//初始化游戲let game = new Phaser.Game(config)//游戲主要函數function preload(){this.load.image("sky","./img/sky.png")this.load.image("star","./img/star.png")this.load.image("ground","./img/platform.png")this.load.image("bomb","./img/bomb.png")this.load.spritesheet("dude","./img/dude.png",{frameWidth:32,frameHeight:48})}function create(){this.add.image(400,300,"sky")platforms = this.physics.add.staticGroup()platforms.create(400,568,"ground").setScale(2,2).refreshBody()platforms.create(600,400,"ground")platforms.create(0,300,"ground")platforms.create(600,200,"ground")player = this.physics.add.sprite(100,450,'dude')player.setBounce(0.2)player.setCollideWorldBounds(true)this.physics.add.collider(player,platforms)this.anims.create({key : 'left',frames : this.anims.generateFrameNumbers('dude',{start : 0,end : 3}),frameRate : 10,repeat : -1})this.anims.create({key : 'turn',frames : [{key : 'dude',frame : 4}],frameRate : 20})this.anims.create({key : 'right',frames : this.anims.generateFrameNumbers('dude',{start : 5,end : 8}),frameRate : 10,repeat : -1})cursors = this.input.keyboard.createCursorKeys()stars = this.physics.add.group({key : 'star',repeat : 11,setXY : {x: 20,y: 0,stepX:70}})stars.children.iterate(function(child){//設置一下碰撞效果child.setBounceY(Phaser.Math.FloatBetween(0.4,0.8))})this.physics.add.collider(stars,platforms)this.physics.add.overlap(player,stars,collectStar,null,this)}function update(){if(cursors.left.isDown){player.setVelocityX(-200)player.anims.play("left",true)}else if(cursors.right.isDown){player.setVelocityX(200)player.anims.play("right",true)}else{player.setVelocityX(0)player.anims.play('turn')}if(cursors.up.isDown && player.body.touching.down){player.setVelocityY(-400)}}function collectStar(player,star){//讓star實體消失star.disableBody(true,true)}</script> </body> </html>計分系統和炸彈,以及游戲結束
如果這個游戲沒有計分系統和炸彈的話,那么這個游戲也太過于佛系了
在preload前面加上一行:
然后在create函數中尾部添加:
bombs = this.physics.add.group()scoreText = this.add.text(16,16,"score : 0",{fontSize: '32px',fill: "#000"}) 這是一個炸彈群組,我們在所有星星被吃光以后使用這個群組添加炸彈修改collectstar函數為:
function collectStar(player,star){//讓star實體消失star.disableBody(true,true)score += 1000scoreText.setText("score :"+ score)if(stars.countActive(true) === 0){stars.children.iterate(function(child){child.enableBody(true,child.x,0,true,true)})var x = (player.x<400)?Phaser.Math.Between(400,800):Phaser.Math.Between(0,400)var bomb = bombs.create(x,16,'bomb')bomb.setBounce(true)bomb.setCollideWorldBounds(true)bomb.setVelocity(Phaser.Math.Between(-200,200),20)bomb.allowGravity = false}}然后在create函數中加上碰撞:
this.physics.add.collider(bombs,platforms)this.physics.add.collider(player,bombs,bombbbb,null,this)在文件尾部加上撞擊函數:
function bombbbb(){this.physics.pause()//涂色,我覺得綠綠的比較好看player.setTint(0x00ff00)player.anims.play("turn")gameover = true}至此,我們的游戲就大功告成啦。。誒,好像我的人物還能動?這個問題就留給大家自己解決了哈哈
完整代碼:
總結
以上是生活随笔為你收集整理的[phaser3入门探坑]使用phaser3制作山寨马里奥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 隐马尔可夫模型与语音识别
- 下一篇: SaaS从业者必读:一文读懂如何衡量与优