Phaser是一个简单易用且功能强大的html5游戏框架,利用它可以很轻松的开发出一个html5游戏。
项目上线一周,闲来无事,捣鼓一个新的框架吧!
1.Phaser的使用非常简单,只需要引入它的主文件,然后在页面中指定一个用来放置canvas的元素,然后实例化一个 Game 对象就可以了。当然如果不指定canvas元素的存放位置会默认到body里面。
html代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html> <head> <meta content="yes" name="apple-mobile-web-app-capable"/> <meta content="yes" name="apple-touch-fullscreen"/> <meta content="black" name="apple-mobile-web-app-status-bar-style"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" /> <meta charset="utf-8" /> <title>flappy bird</title> <style type="text/css"> *{ padding: 0px; margin: 0px; } </style> </head> <body> <script src="js/phaser.min.js"></script> <script src="js/game.js"></script> </body> </html>
|
2.然后实例化一个Game对象
部分代码如下:
1 2 3 4
| window.onload = function(){ var renderMode = Phaser.Device.isAndroidStockBrowser() ? Phaser.CANVAS: Phaser.AUTO; game = new Phaser.Game(320, 505, renderMode, null, bootState); }
|
稍微解析下Phaser.Game这个函数
1
| Phaser.Game(width, height, renderer, parent, state, transparent, antialias, physicsConfig)
|
width: 渲染游戏的canvas的宽度
height: 渲染游戏的canvas的高度
renderer: 渲染方式,Phaser.CANVAS为画布,Phaser.WEBGL为WebGL来渲染,Phaser.AUTO为自动侦测
parent: 用来放置canvas元素的父元素,可以是一个元素id,也可以是dom元素本身,phaser会自动创建一个canvas并插入到这个元素中,实测不带会追加到body
state: state可以理解为场景,在这里指定state表示让游戏首先加载这个场景,但也可以不在这里指定state,而在之后的代码中决定首先加载哪个state。
transparent: 是否使用透明的canvas背景
antialias: 是否启用抗锯齿
physicsConfig: 游戏物理系统配置参数
3.实例化Game对象后,接下来要做的就是创建游戏的各种场景(state)。state可以是一个js自定义对象,也可以是一个函数,只要它们存在preload、create、update这三个方法中的任意一个,就是一个合法的state。
ex:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| var state1 = { preload : function(){}, create : function(){}, update : function(){} }
var state2 = function(){ this.preload = function(){}; this.create = function(){}; this.update = function(){}; }
var state3 = function(){ this.update = function(){}; }
var state4 = function(){ this.create = function(){}; this.funcA = function(){}; this.funcB = 'hello'; }
|
其中
- preload是预加载(最先执行)
- create是初始化以及构建场景
- update是更新函数,会在游戏的每一帧都执行,以此来创造一个动态的游戏。
在文中代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var bootState = function(){ this.preload = function(){}; this.create = function(){}; this.update = function(){}; } var preloadState = function(){ this.preload = function(){}; this.create = function(){}; this.update = function(){}; } var menuState = function(){ this.preload = function(){}; this.create = function(){}; this.update = function(){}; } var playState = function(){ this.preload = function(){}; this.create = function(){}; this.update = function(){}; }
|
4.制作资源加载进度条
游戏要用到的一些图片、声音等资源都需要提前加载,有时候如果资源很多,就有必要做一个资源加载进度的页面,提高用户体验,这时在预加载场景用到的进度条需要在一个基础的场景来加载,命名这个场景为bootState。
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bootState = function(){ this.preload = function(){ game.load.image('loading','assets/preloader.gif'); }; this.create = function(){ game.canvas.style.backgroundColor = "#000000"; game.canvas.oncontextmenu = function(e) { e.preventDefault() }; game.stage.disableVisibilityChange = true; game.device.desktop ? this.scale.scaleMode = Phaser.ScaleManager.EXACT_FIT : this.scale.scaleMode = Phaser.ScaleManager.EXACT_FIT; game.scale.pageAlignHorizontally = true; game.scale.pageAlignVertically = true; game.scale.refresh(); this.scale.forcePortrait = true; this.input.maxPointers = 1;
game.state.add('preloadState',preloadState); game.state.start('preloadState'); }; }
|
5.加载资源
Phaser中资源的加载都是通过 Phaser.Loader 这个对象的方法来完成的,游戏实例的load属性就是指向当前游戏的Loader对象,在我们这里就是game.load。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| preloadState = function(){ this.preload = function(){ var preloadSprite = game.add.sprite(35,game.height/2,'loading'); game.load.setPreloadSprite(preloadSprite);
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'); game.load.image('play_tip','assets/instructions.png'); game.load.image('game_over','assets/gameover.png'); game.load.image('score_board','assets/scoreboard.png'); } this.create = function(){ game.state.add('menuState',menuState); game.state.start('menuState'); } }
|
6.制作游戏菜单页面
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| menuState = 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.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.add('playState',playState); game.state.start('playState'); }); btn.anchor.setTo(0.5,0.5); } }
|
TileSprite本质上还是一个sprite对象,TileSprite的贴图既可以水平移动也可以垂直移动,或者两者同时移动,我们只需要调用TileSprite对象的autoScroll(x,y)方法就可以使它的贴图动起来
7.游戏主场景
部分代码:
启用物理系统,默认是关闭的
1
| game.physics.enable(object, system, debug)
|
object : 要开启物理系统的对象,可以是单个对象,也可以是一个包含多个对象的数组
system : 要启用的物理系统,默认为 Phaser.Physics.ARCADE,Phaser目前支持三种物理引擎,分别是Arcade ,P2 以及 Ninja。
debug : 是否开启调试
鼠标点击事件
1 2 3
| var input = game.input; var signal = input.onDown; signal.add(function(){});
|
计时器
Phaser提供Timer对象来实现
1 2
| loop(delay, callback, callbackContext, arguments); repeat(delay, repeatCount, callback, callbackContext, arguments);
|
ex:
1 2
| game.time.events.loop(time, function(){}, this); game.time.events.stop(false);
|
重力和速度
Phaser.Physics.Arcade.Body 对象,也就是当你是用arcade物理引擎时 sprite.body 所指向的对象,拥有很多跟物理相关的属性和方法。其中的 gravity 对象代表重力,它有x和y两个属性,分别代表水平方向和垂直方向的重力。我们可以使用它的 setTo(x,y)方法来同事设置两个方向的重力。设置了重力的物体,它的运动会受到重力的影响,与真实生活中的物理现象是一致的。然后这个body它还有一个 velocity 对象,表示物体的速度,跟重力一样,都分水平和垂直两个方向,也可以用setTo(x,y)方法来设置。一旦给物体设置了合适的速度,它便能动了
碰撞检测
在Arcade物理引擎中,碰撞检测主要用到两个函数,一个是collide,还有一个是overlap。
声音的播放
ex:
1 2 3
| game.load.audio('score_sound', 'assets/score.wav'); this.soundScore = game.add.sound('score_sound'); this.soundScore.play();
|