如何使用phaser.js在Tizen上创建街机平台游戏

简介

Phaser.js 是当今最受欢迎和最多才多艺的 web 游戏引擎之一。 它是由一个大的社区和一个强大的开发人员团队支持。 众多的特点是快速安装过程和易用性。 此外值得一提,phaser.js 基于非常高效的画布和 WebGL 渲染引擎 — — pixi.js。 任何开发人员可以轻松地启动与 phaser.js 利用 javascript 制作游戏。

这篇文章将涵盖最重要的步骤来创建简单的街机游戏游戏 Tizen 使用 phaser.js。 作为深入窥探游戏机制,这篇文章提供伐木工人游戏应用程序作为示例,并在Tizen SDK 2.2.1 上进行测试。 示例应用程序建使用两个渲染性能测量的库-phaser.js 和 stats.js 构建而成。

Phaser 的更多信息可以在这里找到。 你也可以在这里找到很多有用的例子。  可以在这个页面上找到完整文件的 phaser.js 游戏引擎。

Phaser安装程序

设置库之前本身需要先更改屏幕方向参数要横向模式作为我们的动作游戏的 Tizen 应用程序将仅在横向模式显示。 你可以在 config.xml 文件中做,如下所示。

 

图 1-更改屏幕方向

 

你很容易安装 phaser.js。 首先你需要将 phaser.js 库路径添加到你主要的 html 文档的脚本标记。

 

<script src="js/phaser.min.js"></script>

 

现在,你可以编写JavaScript游戏代码了, 在JavaScript代码中可以使用phaser.js库的强大功能。 首先,我们要用如下的参数来创建一个新的Phaser.Game对象:游戏图版的宽度和高度以及渲染类型。 pixi.js为phaser.js提供了两种渲染模式 。 这两种模式是Phaser.CANVASPhaser.WEBGL。 您也将渲染模式指定为自动检测即Phaser.AUTO,如果设备支持WebGL渲染的话,优先级最高,如果不支持的话就会回退到画布模式。 下一个要传递的参数是要呈现的内容的 DOM 元素 id。 但是只能以括号结尾。 下面是一个很重要的参数:您需要为定义函数生命周期传递一个带有key-value对的对象。 您可以在下面查看到LumberJack游戏的phaser.js代码模板。 请注意,我们的游戏高度和window.innerWidth参数相等,游戏的宽度和window.innerHeight参数相等。 这不是错误,横向模式是必须的。

 

var game;

[…]

var gameHeight, gameWidth;

[…]

gameHeight = window.innerWidth;
gameWidth = window.innerHeight;

game = new Phaser.Game(gameWidth, gameHeight, Phaser.CANVAS, '', {preload: preloadGame, create: createGame, update: updateGame, render: renderGame});

function preloadGame() {
[…] // in this function preloading of the game assets takes place
}

function createGame() {
[…] // in this function we compose our stage with sprites, tile maps, etc.
}

function updateGame() {
[…] // this function is our main render loop of the game, the whole game logic goes here.
}

function renderGame() {
[…] // this function is not mandatory, but you can use it for performance measurement and on screen debugging.

}

加载游戏的assets

为了制作游戏,您需要有图形。 为了有图形,您需要在预加载函数中奖图形加载到您的游戏中,假设我们的LumberJack游戏是preloadGame()的游戏。 Phaser包含了许多灵活的方法来保证预加载游戏的assets是非常简单而快速的。 在我们的示例中,LumberJack游戏有两种assets。 它们是图片和spirtesheets。 Spritesheets 也是图片,但它们包含了动画的序列图片。 您可以在本文的图2中看到spritesheet大概的样子。 您要通过游戏对象中的load.image()load.spritesheet()方法来加载图片和spritesheets。 然后,您需要在参数中指定Phaser引擎中asset的名称,这样,我们就能在后面很轻松的引用asset了。 第二个参数是asset的路径。 对于spritesheet,您需要将宽度和高度作为load.image()方法的第三个和第四个参数,因为Phaser需要知道spritesheet提供的每个动画帧的大小。 还有一些其他的参数,比如marginsspacingframeMax,您可以在该文档中了解到更多信息。

 

[…]

function preloadGame() {

      game.load.image('background', 'images/bg.png');
      game.load.image('left', 'images/left.png');
      game.load.image('right', 'images/right.png');
      game.load.image('up', 'images/up.png');
      game.load.image('rock', 'images/log.png');
      game.load.image('ground_tile', 'images/floor_tile.png');
      game.load.image('hud', 'images/hudPoints.png');

      game.load.spritesheet('player','images/phaserPlayerSpriteSheet.png', 36, 36);
      game.load.spritesheet('collectable','images/itemSpriteSheet.png', 36, 36);

    }

[…]

 

 

图 2 - LumberJack人物移动的spritesheet

 

为了显示游戏的asset,您需要创建一个新的变量,比如“player”,并且通过game.add.sprite()方法为该变量分配一个新的sprite。 现在您就可以通过asset的名称来将asset显示在游戏的舞台上,如下面的示例代码所示。 它将我们的游戏人物动画放在屏幕的坐标为(100px, 200px)的地方。

 

[…]

player = game.add.sprite(100, 200, 'player');

player.animations.add('left', [0, 1, 2, 3, 4], 10, true);
player.animations.add('right', [6, 7, 8, 9, 10], 10, true);

[…]

 

正如你所看到的,您也可以添加命名了的基于spritesheet的动画。 在上面的示例中,有两个动画人物被创建了。 一个叫“left”,另一个叫“right”。 它们是人物的移动线路。 您必须要为spritesheet的序列帧提供一个帧数的数组。 您还需要指定spritesheet中帧的总数并设置动画是否需要循环。 这通过一个布尔型的变量来实现。 要启动或暂停人物动画,您只需要输入如下的命令:

 

[…]

player.animations.play('left');

[…]

player.animations.stop();

[…]

应用游戏物理

phaser.js库的主要价值在于它为开发者提供了不同的物理引擎。 您可以很轻松地指定您所需要的引擎,并能很快地建立您的游戏的快速标准。 现在,三个不同的物理引擎是可用的。 ARCADE物理引擎,主要用于像“Super Mario”这样的平台游戏。 p2引擎通过复杂的冲突系统让您能完全控制物理实体,N+引擎就是Ninja物理引擎。 最后一个是p2物理引擎的简化版本。 将来Phaser的版本将以Box2D物理引擎和Chipmunk物理引擎为特色。 我们的LumberJack示例游戏使用ARCADE物理引擎,所以在本文中我们将重点介绍怎样来设置ARCADE引擎。

在LumberJack游戏中,我们只需要在createGame()函数中用一句话就可以初始化引擎了。 您也可以为ARCADE引擎指定重力。

 

[…]

game.physics.startSystem(Phaser.Physics.ARCADE);
game.physics.arcade.gravity.y = 500;

[…]

 

执行这段代码后,您将可以使用sprite对象的实体变量将物理行为应用到特定的sprite上。  例如,我们可以让人物实体和物理世界的边界产生碰撞,这样人物就不会跑到屏幕外面了。 我们还可以让重力来影响人物。 或者使人物不能被其他的物理实体移动。 你也可以在 createGame() 函数中进行这些设置。 下面是一些例子。

 

[…]

player.body.allowGravity = true;
player.body.immovable = false;
player.body.collideWorldBounds = true;

[…]

 

如果您想要特定的物理实体对您有碰撞,您必须要在引擎中设置碰撞。 您可以像下面的代码一样,通过使用collide()方法来设置。 请记住,碰撞检查或者是告诉移动实体都要放置在Phaser引擎的updateGame()函数中,因为它必须被连续的检查。

 

[…]

game.physics.arcade.collide(player, layer1);

[…]

player.body.velocity.x = 200; // this will move the player body right

[…]

 

当碰撞在两个对象之间产生时,如果您想执行某些操作,你可以用game.physics.arcade为碰撞添加一个处理函数。 在LumberJack游戏中,碰撞处理函数用来检查人物和组条目之间的碰撞。 在人物和itemGroup中任何一个对象产生碰撞之后,游戏会添加点,并用kill()函数销毁可搜集的对象。 如下面的代码所示。

 

[…]

game.physics.arcade.collide(player, itemGroup, collisionHandler, null, this);

[…]

function collisionHandler(player, item) {    

    points++;

    pointsTxt.setText("COLLECTED:\n" + points);
    item.kill(); 
    
}

[…]

添加拼图地面和平台

每个平台游戏都需要有游戏中的英雄能行走的平台。 要建立这些平台,您可以使用Phaser中的拼图。 在建立任何类型的图画游戏中,使用拼图是简单且高效的。 要使用拼图,首先我们需要使用createGame()函数中的game.add.tilemap()方法来创建一张空的拼图。 第二步就是为我们的拼图分配一张拼图图片 - 您可以使用前面创建的拼图中的addTilesetImage()函数来实现。 第一个于鏊传递的参数是tileset的名称。 由于LumberJack示例游戏没有使用外部编辑器的tilesets,您可以传递null。 第二个参数是前面加载的assert的名称,该名称就代表了我们的拼图。 第三和第四个参数是图片的宽度和高度。 然后,您需要设置一张空的拼图层。 您可以使用拼图中的create()方法来实现。 第一个参数是层的名称,该名称将会被注册到Phaser游戏引擎中。 然后,您需要指定游戏等级的宽度和高度参数,该参数是在拼图中衡量的。 最后两个参数会告诉游戏引擎拼图的大小(以像素为单位)。 最后,在建立我们的拼图直接之前要做的就是用层对象上的resizeWorld()方法来调整世界的大小。 这将设置Phaser物理世界的大小来匹配我们的拼图层的大小。

 

[…]

map = game.add.tilemap();
map.addTilesetImage(null,'ground_tile', 36, 36);

layer1 = map.create('layer_1', 50, 10, 36, 36);
layer1.resizeWorld();

[…]

 

创建一个空的拼图后,接下来要做就是为我们的游戏制作一些基于拼图的地面和平台。 您可以以json格式加载整个等级到Phaser中。 但是本使用了手动加载的方法。 如下面的示例所示,您可以通过触发当前拼图中的putTile()函数来放置拼图。 该函数的第一个参数描述了拼图在拼图系统中的索引。 第二个和第三个参数告诉Phaser要将拼图放在整个拼图中的位置的x坐标和y坐标。 两个坐标都是以片为单位而不是像素。 最后一个参数描述了Phaser应该将当前的片放在拼图的哪一层。 最后就是要设置物理碰撞的拼图类型(基于拼图索引)。 您可以通过使用拼图对象中的setCollision()函数来实现。 该函数的第一个参数是用putTile()函数设置的拼图索引。 这将高速Phaser哪个拼图是碰撞者。 第二个参数是一个布尔类型的值,描述了碰撞是否生效。 LumberJack游戏中必须设置为true。 最后一个参数描述了哪一层会受到碰撞的影响。 您必须使用层的字符串名称。

 

[…]

(var i=0; i<50; i++) {
    map.putTile(0, i, 9, 'layer_1');  // GROUND
}   

for (var i=10; i<19; i++) {
    map.putTile(0, i, 7, 'layer_1');  // PLATFORM 1
}   

for (var i=20; i<26; i++) {
      map.putTile(0, i, 5, 'layer_1');  // PLATFORM 2
} 

for (var i=28; i<31; i++) {
      map.putTile(0, i, 3, 'layer_1');  // PLATFORM 3
}            

for (var i=32; i<39; i++) {
      map.putTile(0, i, 7, 'layer_1');  // PLATFORM 4
}          

for (var i=43; i<50; i++) {
      map.putTile(0, i, 4, 'layer_1');  // PLATFORM 5
} 
             
map.setCollision(0, true, 'layer_1');

[…]

 

 

图 3 - 最终的LumberJack示例游戏预览

总结

本文中,我们展现了如何使用phaser.js在Tizen上创建平台游戏。 您学习了如何设置库以及如何准备的游戏的舞台。 您同时还学习了预加载游戏assets如图片和spritesheets并将它们放到游戏舞台的知识。 最后,您还学习到了怎样使用arcade进行碰撞处理和使用拼图来设置游戏等级。 我们希望这些信息能帮助您在Tizen上创建基于Phaser的游戏。 想了解更多的建立街机平台游戏的信息,请参考本文提供的LumberJack游戏的源代码。

 

 
文件附件: