用phaserjs开发了好多游戏了,但是对phaser还是了解不深,只知道怎么去用,今天就特意花点时间研究下phaser的状态管理到底是怎么回事。

首先,new Phaser.Game,以下是Phaser.Game的部分源码:

Phaser.Game = function (width, height, renderer, parent, state, transparent, antialias, physicsConfig) {

    /**
* @property {number} id - Phaser Game ID
* @readonly
*/
this.id = Phaser.GAMES.push(this) - 1; ...........................(省略的代码)
// Parse the configuration object (if any)
if (arguments.length === 1 && typeof arguments[0] === 'object')
{
this.parseConfig(arguments[0]);
}
else
{
this.config = { enableDebug: true }; if (typeof width !== 'undefined')
{
this._width = width;
} if (typeof height !== 'undefined')
{
this._height = height;
} if (typeof renderer !== 'undefined')
{
this.renderType = renderer;
} if (typeof parent !== 'undefined')
{
this.parent = parent;
} if (typeof transparent !== 'undefined')
{
this.transparent = transparent;
} if (typeof antialias !== 'undefined')
{
this.antialias = antialias;
} this.rnd = new Phaser.RandomDataGenerator([(Date.now() * Math.random()).toString()]); this.state = new Phaser.StateManager(this, state);
} this.device.whenReady(this.boot, this); return this; };

先看this.device.whenReady(this.boot, this);这段代码,源码的意思是设备准备就绪或者dom文档准备就绪后就执行boot,说白了就是DOMContentLoaded这个事件或者window的load事件的回调,一切准备就绪,执行boot,boot源码如下:

boot: function () {

        if (this.isBooted)
{
return;
} this.onPause = new Phaser.Signal();
this.onResume = new Phaser.Signal();
this.onBlur = new Phaser.Signal();
this.onFocus = new Phaser.Signal(); this.isBooted = true; PIXI.game = this; this.math = Phaser.Math; this.scale = new Phaser.ScaleManager(this, this._width, this._height);
this.stage = new Phaser.Stage(this); this.setUpRenderer(); this.world = new Phaser.World(this);
this.add = new Phaser.GameObjectFactory(this);
this.make = new Phaser.GameObjectCreator(this);
this.cache = new Phaser.Cache(this);
this.load = new Phaser.Loader(this);
this.time = new Phaser.Time(this);
this.tweens = new Phaser.TweenManager(this);
this.input = new Phaser.Input(this);
this.sound = new Phaser.SoundManager(this);
this.physics = new Phaser.Physics(this, this.physicsConfig);
this.particles = new Phaser.Particles(this);
this.create = new Phaser.Create(this);
this.plugins = new Phaser.PluginManager(this);
this.net = new Phaser.Net(this); this.time.boot();
this.stage.boot();
this.world.boot();
this.scale.boot();
this.input.boot();
this.sound.boot();
this.state.boot(); if (this.config['enableDebug'])
{
this.debug = new Phaser.Utils.Debug(this);
this.debug.boot();
}
else
{
this.debug = { preUpdate: function () {}, update: function () {}, reset: function () {}, isDisabled: true };
} this.showDebugHeader(); this.isRunning = true; if (this.config && this.config['forceSetTimeOut'])
{
this.raf = new Phaser.RequestAnimationFrame(this, this.config['forceSetTimeOut']);
}
else
{
this.raf = new Phaser.RequestAnimationFrame(this, false);
} this._kickstart = true; if (window['focus'])
{
if (!window['PhaserGlobal'] || (window['PhaserGlobal'] && !window['PhaserGlobal'].stopFocus))
{
window.focus();
}
} if (this.config['disableStart'])
{
return;
} if (this.cache.isReady)
{
this.raf.start();
}
else
{
this.cache.onReady.addOnce(function () {
this.raf.start();
}, this);
} }

很有序的初始化一些事件回调和方法,其中world,stage等等都有boot初始化方法,整个Phaser里Phaser.Stage只在这里实例化一次,仅此一次,游戏的舞台就只有这一个stage,stage继承PIXI.DisplayObjectContainer,到这里就都清楚了。

Phaser.World也仅此一次被实例化,它继承自Phaser.Group,Phaser.Group也继承自PIXI.DisplayObjectContainer,但是实例化它的时候,默认是把它添加到Phaser.World里的,

if (parent === undefined)
{
parent = game.world;
}

所以Group都是在World里,除非显示指定stage为其parent,实际开发几乎没这个必要。

Phaser.GameObjectFactory类封装了Phaser的组件,如image,sprite等,显示组件基本都是通过game.add直接被添加到World里(bitmapData除外这里不作研究):
image: function (x, y, key, frame, group) {

        if (group === undefined) { group = this.world; }

        return group.add(new Phaser.Image(this.game, x, y, key, frame));

    },

接下来看下this.state = new Phaser.StateManager(this, state);这段代码,Phaser.StateManager也是仅被实例化一次,主要用来管理游戏state的,构造函数有两个参数game和state,game就是我们的游戏对象,stage是默认的

boot: function () {

        this.game.onPause.add(this.pause, this);
this.game.onResume.add(this.resume, this); if (this._pendingState !== null && typeof this._pendingState !== 'string')
{
this.add('default', this._pendingState, true);
} },

默认state的key为'default',通过game.state.add添加state的源码:

add: function (key, state, autoStart) {

        if (autoStart === undefined) { autoStart = false; }

        var newState;

        if (state instanceof Phaser.State)
{
newState = state;
}
else if (typeof state === 'object')
{
newState = state;
newState.game = this.game;
}
else if (typeof state === 'function')
{
newState = new state(this.game);
} this.states[key] = newState; if (autoStart)
{
if (this.game.isBooted)
{
this.start(key);
}
else
{
this._pendingState = key;
}
} return newState; },

就是一个包含init,preload,create等的object或function,或者是Phaser.State类,这个类就是封装一个state包含的所有方法,所有方法没有任何实现。

game.state.start源码:

start: function (key, clearWorld, clearCache) {

        if (clearWorld === undefined) { clearWorld = true; }
if (clearCache === undefined) { clearCache = false; } if (this.checkState(key))
{
// Place the state in the queue. It will be started the next time the game loop begins.
this._pendingState = key;
this._clearWorld = clearWorld;
this._clearCache = clearCache; if (arguments.length > 3)
{
this._args = Array.prototype.splice.call(arguments, 3);
}
} },

就是检查下是否是一个State,没什么啊,其实真正的start是在preUpadte里,

preUpdate: function () {

        if (this._pendingState && this.game.isBooted)
{
var previousStateKey = this.current; // Already got a state running?
this.clearCurrentState(); this.setCurrentState(this._pendingState); this.onStateChange.dispatch(this.current, previousStateKey); if (this.current !== this._pendingState)
{
return;
}
else
{
this._pendingState = null;
} // If StateManager.start has been called from the init of a State that ALSO has a preload, then
// onPreloadCallback will be set, but must be ignored
if (this.onPreloadCallback)
{
this.game.load.reset(true);
this.onPreloadCallback.call(this.callbackContext, this.game); // Is the loader empty?
if (this.game.load.totalQueuedFiles() === 0 && this.game.load.totalQueuedPacks() === 0)
{
this.loadComplete();
}
else
{
// Start the loader going as we have something in the queue
this.game.load.start();
}
}
else
{
// No init? Then there was nothing to load either
this.loadComplete();
}
} },

start的时候,this._pendingState设置了当前的state,preUpdate方法先清除上一个state,再设置当前state,

setCurrentState里调用了link方法同时初始化一些事件监听,clearCurrentState方法调用了unlink方法同时移除一些事件监听,link方法如下:
link: function (key) {

        var state = this.states[key];

        state.game = this.game;
state.add = this.game.add;
state.make = this.game.make;
state.camera = this.game.camera;
state.cache = this.game.cache;
state.input = this.game.input;
state.load = this.game.load;
state.math = this.game.math;
state.sound = this.game.sound;
state.scale = this.game.scale;
state.state = this;
state.stage = this.game.stage;
state.time = this.game.time;
state.tweens = this.game.tweens;
state.world = this.game.world;
state.particles = this.game.particles;
state.rnd = this.game.rnd;
state.physics = this.game.physics;
state.key = key; },

由此可见每个状态都有game所拥有的几乎所有属性,所以每个state都相当于一个单独的game,包括init,preload,create等等。

setCurrentState:

setCurrentState: function (key) {

        var state = this.states[key];

        this.callbackContext = state;

        this.link(key);

        //  Used when the state is set as being the current active state
this.onInitCallback = state['init'] || this.dummy; this.onPreloadCallback = state['preload'] || null;
this.onLoadRenderCallback = state['loadRender'] || null;
this.onLoadUpdateCallback = state['loadUpdate'] || null;
this.onCreateCallback = state['create'] || null;
this.onUpdateCallback = state['update'] || null;
this.onPreRenderCallback = state['preRender'] || null;
this.onRenderCallback = state['render'] || null;
this.onResizeCallback = state['resize'] || null;
this.onPausedCallback = state['paused'] || null;
this.onResumedCallback = state['resumed'] || null;
this.onPauseUpdateCallback = state['pauseUpdate'] || null; // Used when the state is no longer the current active state
this.onShutDownCallback = state['shutdown'] || this.dummy; // Reset the physics system, but not on the first state start
if (this.current !== '')
{
this.game.physics.reset();
} this.current = key;
this._created = false; // At this point key and pendingState should equal each other
this.onInitCallback.apply(this.callbackContext, this._args); // If they no longer do then the init callback hit StateManager.start
if (key === this._pendingState)
{
this._args = [];
} this.game._kickstart = true; },

每个state在start的时候都会重新执行init,preload,create,update等方法一遍,this.onInitCallback.apply的时候还把参数传进来了,所以如果想start state的时候传参数,请定义个init方法,接受初始化传过来的data,这种模式犹如class的contructor一样使得

state之间相互独立,又可以相互传值,形成一条state网状链式结构,由于clearCurrentState默认clearWorld = true,所以在切换state的时候会先game.world.shutdown();相当于移除所有舞台元素,同时提供了shutdown方法用于关闭state时做的处理。

整个phaser的state流程是----》

初始化Phaser.Game可设置默认state ==》game.state.add(key,state);添加state,==》start state:game.state.start(key1) ==> 移除key1,game.state.start(key2) ==》如此循环,整个过程所有state共享game同时共享其所有方法和属性。

Phaser的初衷也是以最快的速度完成一个游戏,的确这种相互独立e又可以相互连接的state真是可以为开发节省很多很多时间。

设计思路:一个游戏先preload(一般之前会加个boot)=》menuState = 》gameState1=》gameState2=》gameState3等等=》overState  独立模块或场景都可添加state,UI界面最好是继承Group,不要做state,注意由于state切换的时候会destroy world,所以单例或共享View界面最好在start之前全部先移除,否则会出现destroy摧毁当前的单例view的child等所有 导致单例undefined 错误。

Phaserjs V2的state状态解析及技巧的更多相关文章

  1. Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)

    线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...

  2. SCI投稿过程总结、投稿状态解析、拒稿后对策及接受后期相关问答

    SCI投稿过程总结.投稿状态解析.拒稿后对策及接受后期相关问答   http://muchong.com/t-9174366-1 SCI投稿过程总结.投稿状态解析.拒稿后处理对策及接受后期相关问答综合 ...

  3. TCP协议 状态解析和状态统计

    一.三次握手和四次挥手 1.建立连接(三次握手)   (1)服务器会处于listen状态,客户端发送一个带SYN标志的TCP报文到服务器.   (2)服务器端回应客户端的请求,这是三次握手中的第2个报 ...

  4. 架构师成长之路5.3-Saltstack配置管理(State状态模块)

    点击架构师成长之路 架构师成长之路5.3-Saltstack配置管理(State状态模块) 配置管理工具: Pupper:1. 采用ruby编程语言:2. 安装环境相对较复杂:3.不支持远程执行,需要 ...

  5. C++设计模式-State状态模式

    State状态模式作用:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. UML图如下: State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为. ...

  6. nmap端口状态解析

    nmap端口状态解析 状态 说明 open 应用程序在该端口接收 TCP 连接或者 UDP 报文 closed 关闭的端口对于nmap也是可访问的, 它接收nmap探测报文并作出响应.但没有应用程序在 ...

  7. State状态设计模式

    1.状态模式:改变对象的行为 一个用来改变类的(状态的)对象. 2:问题:当你自己实现 State 模式的时候就会碰到很多细节的问题,你必须根据自己的需要选择合适的实现方法, 比如用到的状态(Stat ...

  8. 程序设计模式 —— State 状态模式

    我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...

  9. Spark Streaming揭秘 Day14 State状态管理

    Spark Streaming揭秘 Day14 State状态管理 今天让我们进入下SparkStreaming的一个非常好用的功能,也就State相关的操作.State是SparkStreaming ...

随机推荐

  1. 论文阅读 | BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain

    BadNets: 识别机器学习模型供应链中的漏洞 摘要 基于深度学习的技术已经在各种各样的识别和分类任务上取得了最先进的性能.然而,这些网络通常训练起来非常昂贵,需要在许多gpu上进行数周的计算;因此 ...

  2. mysql常用排查命令

    1.查看服务器使用状态 mysqladmin -uroot -p -S /tmp/mysql.sock -r -i 1 ext |\ awk -F"|" \ "BEGIN ...

  3. azkaban安装步骤

    安装包 1.得到软件包 azkaban-executor-server-2.5.0.tar.gz azkaban-sql-script-2.5.0.tar.gz azkaban-web-server- ...

  4. Java 中的动态代理

    一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者” ...

  5. MySQL创表--分页--自关联--

    创建表book create table t_book( id int unsigned auto_increment primary key, bookName varchar(255) defau ...

  6. DockerFile 编译语法详解

    Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像,本小结首先介绍Dockerfile典型的基本结构和它支持的众多指令,并具体讲解通过这些指令来编写定 ...

  7. Tomcat的安全性

    Web应用程序的一些内容是受限的,只有授权的用户在提供了正确的用户名和密码后才能查看他们,servlet技术支持通过配置部署 描述器(web.xml)来对这些内容进行访问控制,那么web容器是怎么样支 ...

  8. 十大经典排序算法(Python,Java实现)

    参照:https://www.cnblogs.com/wuxinyan/p/8615127.html https://www.cnblogs.com/onepixel/articles/7674659 ...

  9. 分布式---CAP和BASE理论

    3.CAP   分布式系统不可能同时满足一致性(C:Consistence),可用性(A:Avaliability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中的两 ...

  10. JS基础_其他进制的数字(了解)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...