媒介
phaser作为一款盛行的游戏/动画框架,遭到许多web开辟者的喜爱,近来笔者在逛意大利开辟者:emanueleferonato论坛的时刻发现了这款小游戏,所以就照着申明做了一下,在这里记录下来.
开辟预备
nodejs+npm
http-server插件
phaser剧本
飞刀和靶子的图象
或许
git clone https://github.com/YexChen/canvas_game.git
这个项目内里有phaser的剧本和须要的图象文件
最先制造
搭建基本的phaser项目
建立一个基本的html文件,引入phaser文件
<!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.js"></script>
</head>
<body>
<script>
</script>
</body>
</html>
别忘了在当前目录下启动http-server,启动服务器.翻开localhost:8080(或其他端口)来检察项目
那末如今,我们须要干什么呢?
我们如今须要在页面加载时加载一个游戏实例,代码以下:
let game,knifeGroup
let gameConfig = {
rotateSpeed : 5,
throwSpeed : 150,
minAngle : 10
}
window.onload = function(){
game = new Phaser.Game({
type: Phaser.CANVAS,
width: 600,
height: 700,
backgroundColor: 0xdddddd,
scene: [playGame]
})
}
Phaser.Game 是phaser游戏的构建函数,定义了实例的范例,宽高,背景色彩,场景等信息,人人能够console.log(Phaser)看一下定义.
playGame是接下来的场景.
gameConfig 是游戏的参数,轻易修正
接下来我们定义一下我们的场景:
class playGame extends Phaser.Scene{
constructor(){
super("playGame")
}
preload(){
}
create(){
}
update(){
}
}
场景在游戏中相当於戏曲中的每一幕,经由过程Phaser.Scene.start来举行挪用.
在Phaser游戏中,场景建立时会先运转preload函数,用来预加载图片模子.然后运转create函数,实行初始化代码,末了在每一步中挪用update函数更新
预加载图片
preload(){
this.load.image("target","image/target.png")
this.load.image("knife","image/knife.png")
}
在preload中到场以上代码,把图片注册进来.
加载物体
create(){
this.target = this.add.image(game.config.width/2,game.config.height/5 *2,"target").setScale(0.5,0.5)
this.target.depth = 1
this.knife = this.add.image(game.config.width/2,game.config.height/5*4,"knife").setScale(0.5,0.5)
this.knifeGroup = this.add.group()
console.log(this)
}
this.add.image经由过程供应的宽高和上一步中供应的url来天生Image范例的对象(和原生的不一样!),
对象的原型链上的setScale(x,y)函数能够调解图象的缩放.
knifeGroup 是空的group对象,用来寄存今后的飞刀鸠合
让我们的图象动起来
修正update函数:
update(){
this.target.angle += gameOptions.rotateSpeed
}
好的,至此我们的项目基本就完毕了,接下来来做飞刀的逻辑吧
扔飞刀逻辑
我们起首须要监听用户的鼠标事宜,能够运用Phaser内置的函数来完成,在created中到场:
this.canThrow = true
this.input.on("pointerdown",this.throwKnife,this)
throwKnife 是我们扔飞刀的处置惩罚函数,我们写在update背面:
throwKnife(){
if(!this.canThrow){
return
}
this.canThrow = false
this.tweens.add({
targets: [this.knife],
y: this.target.y+this.knife.height/8 * 3,
duration: gameOptions.throwSpeed,
callbackScope: this,
onComplete: function(tween){
},
})
}
我们在用户按下鼠标左键时,检测是不是可扔,假如可扔的话就让我们的飞刀做一个tweens动画,this.tweens是一个tweens管理器,官方文档比较残废,部份参数以下:
target : tweens动画目的
y : 目的的y坐标,
duration: 动画时候
callbackScope: 回调函数的this值
onComplete: 完成时的回调函数
飞刀插上去今后,我们要推断这个飞刀是不是是和别的飞刀的重合,笔者这里的推断体式格局是在每个飞刀插到盘面上时把当前轮盘的角度保留下来,当下一次扔掷的时刻推断当前盘面旋转度和以往的旋转度间隔是不是小于最小值,假如小于最小值就游戏完毕,不然就插一次飞刀.
我们在上面的onComplete函数内里写下代码:
let isLegal = true
let children = this.knifeGroup.getChildren()
for(var i=0;i<children.length;i++){
let child = children[i]
if(Math.abs(Phaser.Math.Angle.ShortestBetween(this.target.angle,child.impactAngle))<gameOptions.minAngle){
isLegal = false
break
}
}
if(isLegal){
this.canThrow = true
let newKnife = this.add.image(this.target.x,this.target.y+this.knife.height/8 * 3,"knife").setScale(0.5,0.5)
newKnife.impactAngle = this.target.angle
this.knifeGroup.add(newKnife)
this.knife.y = game.config.height/5 * 4
}
else{
this.tweens.add({
targets: [this.knife],
y: game.config.height+this.knife.height,
rotation: 5,
duration: gameOptions.throwSpeed*4,
callbackScope: this,
onComplete(tween){
this.scene.start("playGame")
}
})
}
我们推断之前一切飞刀的impactAngle值,假如没有和当前角度相差10度的,我们就插进去新的飞刀,不然播放动画今后重启游戏.
更新每一把飞刀的位置
好的,我们扔飞刀的逻辑已完成了,接下来我们只须要遍历每个knifeGroup内里的子飞刀的位置,并在update更新函数内里更新他们的位置,游戏就算做完了.
在update函数内里增加:
update(){
this.target.angle += gameOptions.rotateSpeed
let children = this.knifeGroup.getChildren()
for(var i=0;i< children.length;i++){
let child = children[i]
child.angle += gameOptions.rotateSpeed
let ang = Phaser.Math.DegToRad(child.angle)
child.x = this.target.x - Math.sin(ang) * this.target.width/4
child.y = this.target.y + Math.cos(ang) * this.target.width/4
}
}
我们在飞刀挪动时盘算每一步偏移的角度,从而推断出子飞刀child的x,y位移.
我们的小游戏就做完了,完全代码以下,趁便做了下记分牌:
<!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.js"></script>
</head>
<body>
<script>
let game,knifeGroup,scoreText,score
let gameOptions = {
rotateSpeed : 5,
throwSpeed : 150,
minAngle : 10
}
window.onload = function(){
game = new Phaser.Game({
type: Phaser.CANVAS,
width: 600,
height: 700,
backgroundColor: 0xdddddd,
scene: [playGame]
})
}
class playGame extends Phaser.Scene{
constructor(){
super("playGame")
}
preload(){
this.load.image("target","image/target.png")
this.load.image("knife","image/knife.png")
}
create(){
this.target = this.add.image(game.config.width/2,game.config.height/5 *2,"target").setScale(0.5,0.5)
this.target.depth = 1
this.knife = this.add.image(game.config.width/2,game.config.height/5*4,"knife").setScale(0.5,0.5)
this.knifeGroup = this.add.group()
console.log(this)
this.canThrow = true
this.input.on("pointerdown",this.throwKnife,this)
score = 0
scoreText = this.add.text(16,16,"score:0",{fontSize:"32px",fill:"#000"})
}
update(){
this.target.angle += gameOptions.rotateSpeed
let children = this.knifeGroup.getChildren()
for(var i=0;i< children.length;i++){
let child = children[i]
child.angle += gameOptions.rotateSpeed
let ang = Phaser.Math.DegToRad(child.angle)
child.x = this.target.x - Math.sin(ang) * this.target.width/4
child.y = this.target.y + Math.cos(ang) * this.target.width/4
}
}
throwKnife(){
if(!this.canThrow){
return
}
this.canThrow = false
this.tweens.add({
targets: [this.knife],
y: this.target.y+this.knife.height/8 * 3,
duration: gameOptions.throwSpeed,
callbackScope: this,
onComplete: function(tween){
let isLegal = true
let children = this.knifeGroup.getChildren()
for(var i=0;i<children.length;i++){
let child = children[i]
if(Math.abs(Phaser.Math.Angle.ShortestBetween(this.target.angle,child.impactAngle))<gameOptions.minAngle){
isLegal = false
break
}
}
if(isLegal){
this.canThrow = true
let newKnife = this.add.image(this.target.x,this.target.y+this.knife.height/8 * 3,"knife").setScale(0.5,0.5)
newKnife.impactAngle = this.target.angle
this.knifeGroup.add(newKnife)
this.knife.y = game.config.height/5 * 4
score += 100
scoreText.setText("score:" +score)
}
else{
this.tweens.add({
targets: [this.knife],
y: game.config.height+this.knife.height,
rotation: 5,
duration: gameOptions.throwSpeed*4,
callbackScope: this,
onComplete(tween){
this.scene.start("playGame")
}
})
}
},
})
}
}
</script>
</body>
</html>