Phaserjs基础教程第二节:加载图片、文字和动画

 游戏场景的创建是游戏开发的基础,而游戏场景又是由各种图片、模型、文字等构成的,我们本节就来学习怎么加载资源到游戏场景中。

 (注:本教程所使用的所有示例资源均来自官方实例库,如果自己想动手却又没有资源,可以到https://github.com/photonstorm/phaser-examples下载所有实例。)

       一、加载图片:

 首先,我们加载一张简单的图片,代码如下:

var game = newPhaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload,create: create});
function preload() {
    //  给路径所在位置的图片定义一个唯一的关键字,这个关键字在所有的图片中必须是唯一的。
    game.load.image('imageKey','assets/sprites/phaser2.png');
}

function create() {
       //参数:x坐标,y坐标,图片关键字
    game.add.sprite(0, 0, 'imageKey');
}

 这段代码中,我们只使用了preload和create两个方法,因为我们只是加载了图片和创建场景,并没有进行其他操作,所以并没有定义其他状态。

       这里,我们需要了解下sprite的概念,sprite的翻译是精灵,它在phaser中是一个对象,具体来讲,它是一个具有结构(纹理)、可以运行动画、支持输入事件和物理学的游戏对象。所以,我们一般讲会进行操作的图片和动画对象等都定义成sprite对象。

       在上面的例子中,因为我们没有设置背景,所以自动填充为黑色,下面我们添加一张背景图片:

var game = newPhaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload,create: create});
function preload() {
    //  给路径所在位置的图片定义一个唯一的关键字,这个关键字在所有的图片中必须是唯一的。
    game.load.image('space','assets/pics/thalion-rain.png');
}
function create() {
var bg = game.add.tileSprite(0, 0, 800, 600, 'space');
//var bg = game.add.sprite(0, 0, 'space');
}

 因为背景图片需要填充整个游戏区域,而sprite对象并不支持填充区域的宽高,所以我们选择了tileSprite对象,tileSprite对象可以对图片进行裁剪或平铺填充设定区域,你可以切换注释行尝试下添加两种对象的不同。

当然,你也可以直接填充一个颜色作为背景色:

function create() {
       //注意,这里的颜色只支持16进制的数字或者字符串
    game.stage.backgroundColor = 0xfff00;
//  game.stage.backgroundColor = '#ff0000';
}

二、加载文字

       如果只是单纯的在游戏中显示文字的话,很简单,查看代码:

var game = newPhaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { create: create });

//设置文本样式:大小、字体、颜色、排列方向
var textStyle= { font: "48px Arial", fill: "#ff0044", align:"center" };
functioncreate() {
       //game.world.centerX:视图中心的x坐标
       //game.world.centerY:视图中心的y坐标
    var text =game.add.text(game.world.centerX, game.world.centerY, "你好,欢迎来到Phaser的世界", textStyle);
    //锚点设置
 text.anchor.set(0.5, 0.5);
 //text.scale.setTo(0.5);
 //text.angle = 90;
 //text.alpha = 0.5;
}

 这里要介绍几个基础且常用的属性:anchor、scale、angle、alpha。

 anchor(锚点):取值范围0~1,其实就是,元素(图片、文字等)中心与放置位置(添加到的坐标)相对于自身长宽的一个比例,比如(0,0)表示元素左上角坐标和放置位置坐标重合,(1,1)表示元素右下角坐标和放置位置坐标重合,(0.5,0.5)表示元素中心和放置位置重合,其他则根据元素长宽比例来设置。

 scale(缩放比例):相对于元素原始尺寸的比例。

 angle(角度):一个有效的数字,一般取值0~360.

 alpha(透明度):也就是rgba中的a,取值范围0~1.

       可是游戏嘛,很多时候都常常使用一些类似于艺术字之类的炫酷字体,那就没办法用textStyle设置文字样式了,这个时候,我们就需要借助一个叫做BitmapText(位图文本,如果不知道什么叫位图的话,可以百度一下概念),使用BitmapText对象,我们不仅可以自定义字体,还可以定义角度、透明度、颜色等属性,先来看一个简单的例子:

var game = newPhaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload,create: create, render: render });

function preload() {
       //加载位图字体图片和配置文件
       //bitmapFont(key, textureURL, atlasURL,atlasData, xSpacing, ySpacing)
       //参数:关键字,纹理图片路径,配置文件(xml或json格式,如果不带后缀,默认解析成xml格式),atlasData,字符间距,行间距
       //atlasData:暂时没有用到,根据api翻译的理解,应该是如果配置文件有多层的话,这里可以选择其中的一层
    game.load.bitmapFont('desyrel','assets/fonts/bitmapFonts/desyrel.png', 'assets/fonts/bitmapFonts/desyrel.xml');
}
 
var line1;
var line2;
function create() {
       //顺便查看下anchor、tint、scale、alpha效果
    var text1 = game.add.bitmapText(400, 70,'desyrel', 'Anchor.x = 0', 64);
    var text2 = game.add.bitmapText(400, 270,'desyrel', 'Anchor.x = 0.5', 64);
    text2.anchor.x = 0.5;
    var text3 = game.add.bitmapText(400, 470,'desyrel', 'Anchor.x = 1', 64);
    text3.anchor.x = 1;
    //设置文本颜色
    text3.tint = 0xFF0000;
    text3.scale.set(0.8);
    text3.alpha = 0.5;
       //添加两条中心线
    line1 = new Phaser.Line(400, 0, 400, 600);
    line2 = new Phaser.Line(0, 300, 800, 300);
} 
function render() {
       //显示中心线
    game.debug.geom(line1);
    game.debug.geom(line2);
}

下面是使用到的图片:

       如果纹理图片被整合到其他图片中,和另外的图片合成了一张新图片,照样也可以设置位图字体(不过此方法为2.7版本新增方法,2.6以下不支持):

var game = newPhaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload,create: create });
function preload() {
    //  加载纹理图片和图片地图集数据
    game.load.atlas('atlas','assets/sprites/atlas-mixed.png', 'assets/sprites/atlas-mixed.json');
    //  加载位图字体配置文件
    game.load.xml('fontData','assets/fonts/bitmapFonts/desyrel.xml');
}
var bmpText;
functioncreate() {
       // addBitmapFontFromAtlas方法为2.7版本新增的
       //参数:定义字体的关键字,图片资源关键字,图片中字体部分的关键字,字体配置文件,配置文件格式,字符间隔,行间距
    game.cache.addBitmapFontFromAtlas('myFont','atlas', 'desyrel', 'fontData', 'xml', 0, 0);
    // 添加位图字体:x,y,字体关键字,文本,字体大小
    bmpText = game.add.bitmapText(0, 100,'myFont', 'A Bitmap Font\nfrom a Texture Atlas', 64);
    bmpText.align = 'center';
    bmpText.centerX = 400;

    //  还可以添加同一张图片的其他元素:一个绿球
    var ball = game.add.sprite(20, 100,'atlas', 'wizball');
}

       其实还有一种简单的导入文字资源的方式,只需要加载一张图片就行了,不过在这张图片中,每个字符或者空格都要占有相同大小的位置,还要定义好文字的位置,这样才可以使用,查看下面示例:

 这是Phaser.RetroFont已经定义好的字符:

 要使用的图片如下:

 代码如下:

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload,create: create, update: update });
function preload() {
    game.load.image('goldFont','assets/fonts/retroFonts/gold_font.png');
    game.load.image('bluePink','assets/fonts/retroFonts/bluepink_font.png');
}
var font1;
var font2;
var image1;
var image2;
function create() {
       console.log(Phaser);
       //前缀,空格对应空格
    font1 = game.add.retroFont('goldFont', 16,16, "!     :() ,?." +Phaser.RetroFont.TEXT_SET10, 20, 0, 0);
    font1.text = "phaser brings you retrostyle bitmap fonts";
    image1 = game.add.image(game.world.centerX,48, font1);
    image1.anchor.set(0.5);
 font2 = game.add.retroFont('bluePink', 32,32, Phaser.RetroFont.TEXT_SET2, 10);
 font2.setText("phaser 2\nin thehouse", true, 0, 8, Phaser.RetroFont.ALIGN_CENTER);
 image2 = game.add.image(game.world.centerX,220, font2);
    image2.anchor.set(0.5);

       //每两秒钟随机变换一次颜色
    game.time.events.loop(Phaser.Timer.SECOND *2, change, this);
}

function change(){
       //代码的作用是生成一个类似0xXXXXXX这样的16进制数字
    image2.tint = Math.random() * 0xFFFFFF;
}
function update() {
       //game.time.physicsElapsed = 1/60
       image2.rotation += (2 *game.time.physicsElapsed);
}

       这个时候,你可以想象一下如果游戏中的提示全部用中文特效来做,你要做多少个字的特效?

 三、加载动画

 大家都知道,动画其实就是由一帧一帧的图片组成的,所以动画的本质就是让一系列的图片按照顺序以特定的时间间隔显示出来。Phaser也一样,它的动画实际上就是加载了一张(或几张)png图片,然后按照固定的宽高截取图片中相应位置的内容作为动画的一帧,按照规定的顺序逐一显示,形成动画。说起来有点绕口,下面还是直接看例子吧:

 1.加载顺序、固定位置动画:

 http://phaser.io/docs/2.6.2/Phaser.Loader.html#spritesheet

 先来看个示例:

var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload,create: create });

function preload() {
       //39X40是每个画面的尺寸
    game.load.spritesheet('mummy', 'assets/sprites/metalslug_monster39x40.png',39, 40);
} 
function create() {
       //将sprite添加到场景中
    var mummy = game.add.sprite(300, 200,'mummy');
 //因为图片太小,放大为原来的两倍显示
 mummy.scale.set(2); 
    //添加一个名叫walk的动画
    //因为我们没有设置其他参数,所以它会执行mummy中所有的frame
    var walk = mummy.animations.add('walk');
    //开始动画,每秒30帧,循环执行
    mummy.animations.play('walk', 30, true);
}

 上面的示例中,要加载的图片如下:


 这张图片一共有16个画面,图片大小156*160px,每个画面都占用了39*40px,按照顺序显示,就形成了上面的动画;可是如果画面数量不是16个呢,如果图片中有额外的空白呢?那么把代码修改下吧:

var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload,create: create }); 
function preload() {
       //37X45是每个frame的尺寸,画面并没有占满全部图片,所以添加一个参数:显示画面的数量
    game.load.spritesheet('mummy','assets/sprites/metalslug_mummy37x45.png', 37, 45, 18); 
} 
function create() {
       //将sprite添加到场景中
    var mummy = game.add.sprite(300, 200,'mummy');
    mummy.scale.set(2); 
    //添加一个名叫walk的动画
    //因为我们没有设置其他参数,所以它会执行mummy中所有的frame
    var walk = mummy.animations.add('walk');
    //开始动画,每秒30帧,循环执行
    mummy.animations.play('walk', 30, true);
}

 这个例子中,加载的图片如下:

 这张图片中,所有的画面同样是固定宽高,同样是按顺序排列,可是并没有填满整个图片,因此就需要显示一下动画中画面的数量。

 如果你的图片中所有画面并没有紧挨,而是有着固定的间距,那么你就需要在最后再添加两个参数,margin和spacing,分别表示垂直和水平的间距(我并没有找到合适的图片,所以这里不提供代码了)。 

 2.加载无序、随机位置动画:

 事实上,我们也不能保证制作的png图片中每个画面都有固定的长度和宽度(就算可以实现,也要花费设计人员很多的时间,毕竟是要按像素调整的)。比如下面这张图片,展示了一个机器人奔跑的动画:

 

 这个时候,我们可以使用atlasJSONHash函数来加载这张图片和配合它使用的json文件,代码如下:

var game = newPhaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload,create: create }); 

function preload() {
    game.load.atlasJSONHash('bot','assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
} 
function create() {
var bot = game.add.sprite(200, 200, 'bot');
// 定义一个名为run的动画 // 虽然我们没有规定任何画面,但是json文件里面已经定义好了 bot.animations.add('run'); // 执行动画run,帧数15,循环播放 bot.animations.play('run', 15, true); }

 这样动画就可以播放了。

 那么问题又来了,我们怎么生成一个和png图片匹配的json的文件呢?打开上面的json文件,你可以看到它是有固定的格式的,整个对象中包含了frames和meta两个属性,frames固定了所有画面截图位置和顺序,meta属性则显示了制作工具的地址和图片名称等信息。所以,其实json文件是可以通过工具生成的。

 这个工具叫做TexturePacker,下载地址:http://www.codeandweb.com/texturepacker,网站上提供了详细的使用教程,地址在这:https://www.codeandweb.com/blog/2014/12/17/creating-spritesheets-for-phaser-with-texturepacker,这个工具的作用就是把一系列png图片整合到一张图片上,生成适合各种框架使用的配置文件,因为我们使用的是phaser2,所以这里选择的格式是jsonHash,跟上面示例中一样,具体格式等可以参考网站,或者直接下载免费版本的工具。

  OK,这一节就就到这里,下一节来讲一些简单的交互操作。

上面的示例中,要加载的图片如下:
这张图片一共有16个画面,图片大小156*160px,每个画面都占用了39*40px,按照顺序显示,就形成了上面的动画;

可是如果画面数量不是16个呢,如果图片中有额外的空白呢?那么把代码修改下吧:
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值