登录内测(欢迎小伙伴们通过右侧登录按钮进行注册和登录)
解惑phaser创建对象
作者:channingbreeze
日期:2017-08-27
phaser小站有很多Phaser的实例,这里面涉及到创建对象的方法就很多了。有的使用new,有的使用game.add,有的使用game.make,那么这些方法到底有什么不同,为什么有时候能显示对象,有时候不能显示?这篇文章给你解惑。

很多刚进群的朋友,都会问一个问题。比如想创建一个精灵,就会去找到文档。

然后又去看下官方示例,是这样写的:

发现参数对不上,于是就说文档看不懂,不知道怎么用,在群里就开始问了,那么问的人多了,就有必要有人来把这个问题总结一下。

还有一类问题,是这样,有的人发现了下面这段代码,用的是game.make,又犯晕了,到底啥时候用game.add,啥时候用game.make


问题梳理:

其实问题主要集中在3个点,就是new Sprite怎么用?game.add做了什么?game.addgame.make有什么区别?下面一个一个来解答。

首先回答new怎么用?很简单,按照文档就行。这里我给出代码:(代码是在https://www.phaser-china.com/example-detail-74.html例子上面使用编辑功能进行快速验证)

// 前面两个参数代表游戏区域 800x600 px
// Phaser.AUTO表示自动选择Canvas或者webGL
// 'phaser-example'表示将游戏区域放在id为phaser-example的元素中
// 最后一个参数指定回调,preload预加载资源,create创建游戏
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });
 
function preload() {
           // 加载一个图片,之后可通过 einstein 来引用
    game.load.image('einstein', 'assets/pics/ra_einstein.png');
}
 
function create() {
           // 在(0,0)位置显示该图片
    //game.add.sprite(0, 0, 'einstein');
    var sprite = new Phaser.Sprite(game, 0, 0, 'einstein');
}

但是这样运行之后,我们并没有看到任何精灵显示出来,原因也很简单,我们这里只是创建了精灵,但是没有显示它!怎么把它显示出来呢?把它加到游戏世界里。我们在代码中添加一句话:game.world.add(sprite);

// 前面两个参数代表游戏区域 800x600 px
// Phaser.AUTO表示自动选择Canvas或者webGL
// 'phaser-example'表示将游戏区域放在id为phaser-example的元素中
// 最后一个参数指定回调,preload预加载资源,create创建游戏
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });
 
function preload() {
           // 加载一个图片,之后可通过 einstein 来引用
    game.load.image('einstein', 'assets/pics/ra_einstein.png');
}
 
function create() {
           // 在(0,0)位置显示该图片
    //game.add.sprite(0, 0, 'einstein');
    var sprite = new Phaser.Sprite(game, 0, 0, 'einstein');
    game.world.add(sprite);
}

这时候精灵就显示出来了。这里我们学习了怎么用new的方式显示精灵,并且得到一个重要的信息。new只是创建了精灵,要让它显示,需要再添加到世界里,或者添加到任何一个已经显示的组里面。

 

那么game.add做了什么呢?聪明的人应该已经猜到了,game.add就是把这两步封装了一下呗!没错!

在这里我们还需要说明一下,game.add到底是什么东西。首先,它是一个对象,没错吧?js里什么东西不都是对象么?那么它是一个什么对象呢?文档里有:

看到了?它是一个GameObjectFactory对象。那么很多人都在问,我没有定义game.add啊,它是怎么来的?很简单,这是phaser自带的对象,当你new Phaser.Game的时候,game里面的所有对象就都已经有了,那么game里面到底有哪些对象呢?看我的翻译文档:https://www.phaser-china.com/docs-cn/doc-game.html

成员里面的东西,都是game里自带的,而且第一个就是add,说的很清楚,它是Phaser.GameObjectFactory的引用。好了,那么为什么game.add.sprite的参数是用game.add.sprite(0, 0, 'einstein');这种方式呢?这里我怎么去找文档呢?

这就要用到文档搜索功能,https://www.phaser-china.com/search-result.html,在这里输入函数名,那么函数名是什么呢?game.add.sprite,刚刚说了,game.add是一个对象,那么game.add.sprite(xxx)就是调用对象的函数啊,所以函数名是?大声告诉我,s!!p!!r!!i!!t!!e!!,对了,就是sprite,把它输进去:https://www.phaser-china.com/search-result.html?text=sprite

点一下搜索,就看到了所有的结果,好神奇!

第一个结果就是new Sprite,卧槽,怎么参数还是对不上?别着急,你看错文档了,我们找的是game.add.sprite对不对?那么应该找game.add下面的方法对吧?那么game.add是什么,大声告诉我!对了,它是Phaser.GameObjectFactory的引用,所以我们要找GameObjectFactory的文档,这里一共9个结果呢,我们往下翻,看到:

这才是GameObjectFactory里面的sprite方法啊,这时候就发现,参数已经对上了。

好了,上述就是文档搜索的使用说明。

 

那么还有一个问题,game.addgame.make有什么区别?还是一样的思路,我们先搞清楚game.make是什么,这里不赘述,如果还不会,把上面几段再看一遍,然后,我们在文档中找到game.make.sprite的参数列表,在例子里试一下不就知道了么?

// 前面两个参数代表游戏区域 800x600 px
// Phaser.AUTO表示自动选择Canvas或者webGL
// 'phaser-example'表示将游戏区域放在id为phaser-example的元素中
// 最后一个参数指定回调,preload预加载资源,create创建游戏
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });
 
function preload() {
           // 加载一个图片,之后可通过 einstein 来引用
    game.load.image('einstein', 'assets/pics/ra_einstein.png');
}
 
function create() {
           // 在(0,0)位置显示该图片
    game.make.sprite(0, 0, 'einstein');
    // var sprite = new Phaser.Sprite(game, 0, 0, 'einstein');
    // game.world.add(sprite);
}

同样,在这里,我们没有看到任何精灵显示,把代码改一改呢?怎么改,我想聪明的同学已经猜到了:

// 前面两个参数代表游戏区域 800x600 px
// Phaser.AUTO表示自动选择Canvas或者webGL
// 'phaser-example'表示将游戏区域放在id为phaser-example的元素中
// 最后一个参数指定回调,preload预加载资源,create创建游戏
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });
 
function preload() {
           // 加载一个图片,之后可通过 einstein 来引用
    game.load.image('einstein', 'assets/pics/ra_einstein.png');
}
 
function create() {
           // 在(0,0)位置显示该图片
    var sprite = game.make.sprite(0, 0, 'einstein');
    // var sprite = new Phaser.Sprite(game, 0, 0, 'einstein');
    game.world.add(sprite);
}

这样,精灵又显示出来了。也就是说game.make也只是创建精灵,并不会把它添加到游戏世界中去。它相当于对new Sprite的封装。

 

不知道有没有同学会有疑问,为什么可以用new Sprite,还要提供game.make.sprite呢?其实这里使用的是工厂模式,phaser框架通过工厂模式创建对象,有很多优点,这里就涉及到一些设计模式的东西了,我不展开讲,有兴趣的同学可以加QQ群我们一起讨论。这里我举一个最简单的场景,就是反射。没有工厂模式之前,我们只能new Sprite这样写,但是有工厂模式之后,我们可以这样写:

var type = 'sprite'
game.make[type](xxx)

明白了吧?sprite就可以放进变量里,然后这个变量可以赋其他值啊,如果type=”group”,这时候的代码逻辑就变成game.make.group了,那么如果把type从配置文件里读取出来呢?哈哈,这就是框架们要做的事情啦。好了,这里点到为止。


总结一下,new Sprite可以用,用完之后只是创建了对象,如果要显示,需要加到游戏世界里,game.make是用工厂模式对new Sprite的封装,game.add是再封装,把创建和显示都做了。那么new Group,new Graphics,就是一样的啦,大家自己举一反三吧!