游戏要用到的一些图片、声音等资源都需要提前加载,有时候如果资源很多,就有必要做一个资源加载进度的页面,提高用户等待的耐心。这里我们用一个state来实现它,命名为preload。

因为资源加载进度条需要一个进度条的背景图片,所以在制作这个state前,我们还需要另一个最基础的state,用来加载那张进度条图片,我们命名为boot。

复制代码

game.States.boot = function(){

this.preload = function(){

game.load.image('loading','assets/preloader.gif'); //加载进度条图片资源

};

this.create = function(){

game.state.start('preload'); //加载完成后,调用preload场景

};

}

复制代码

Phaser中资源的加载都是通过 Phaser.Loader 这个对象的方法来完成的,游戏实例的load属性就是指向当前游戏的Loader对象,在我们这里就是game.load。Loader对象有许多方法,不同的方法可以加载不同的资源,例如加载图片我们用的是game.load.image()方法,具体的方法列表请自行参考文档。

在preload这个场景中,我们需要把游戏后面会用到的所有资源都进行加载,然后还要展示一个加载进度条给用户看。Loader对象提供了一个 setPreloadSprite 方法,只要把一个sprite对象指定给这个方法,那么这个sprite对象的宽度或高度就会根据当前加载的百分比自动调整,达到一个动态的进度条的效果。

复制代码

game.States.preload = function(){

this.preload = function(){

var preloadSprite = game.add.sprite(50,game.height/2,'loading'); //创建显示loading进度的sprite

game.load.setPreloadSprite(preloadSprite); //用setPreloadSprite方法来实现动态进度条的效果

//以下为要加载的资源

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'); //get ready图片

game.load.image('play_tip','assets/instructions.png'); //玩法提示图片

game.load.image('game_over','assets/gameover.png'); //gameover图片

game.load.image('score_board','assets/scoreboard.png'); //得分板

}

this.create = function(){

game.state.start('menu'); //当以上所有资源都加载完成后就可以进入menu游戏菜单场景了

}

}

复制代码

上面我们提到了Sprite对象,也就是游戏开发中俗称的精灵,同样在Phaser中sprite对象也是制作游戏过程中用得最多的也是最重要的一个对象之一。我们可以用一幅图片来创建一个sprite,然后用Phaser提供给我们的众多属性和方法来对它进行操作。上面我们是利用game.add.sprite()来创建sprite的,并且创建后会自动把它添加到当前的游戏中,game.add代表的是Phaser.GameObjectFactory对象,该对象提供了了一系列快捷方法来方便我们创建游戏的各种组件。我们这里制作的资源加载进度页面非常简单,大概就是下面这个样子:

1

制作游戏菜单页面

资源加载完成后就该进入到游戏菜单页面了,说是菜单页,但我们这里只是提供一个开始游戏的按钮而已,作为教程就别搞那么复杂啦。做好后的效果如下:

menu下面我们就来实现这个页面。

首先是背景图与地面,我们看到这两个东西是会动的,地面移动动的速度快一些,背景图慢一些,在Phaser中有专门的东西来处理这种效果,叫做TileSprite,什么是TileSprite呢?TileSprite本质上还是一个sprite对象,不过这个sprite的贴图是可以移动的,并且会自动平铺来弥补移动后的空缺,所以我们的素材图片要是平铺后看不出有缝隙,就可以拿来当做TileSprite的移动贴图了。TileSprite的贴图既可以水平移动也可以垂直移动,或者两者同时移动,我们只需要调用TileSprite对象的autoScroll(x,y)方法就可以使它的贴图动起来了,其中x是水平方向的速度,y是垂直方向的速度。

复制代码

game.States.menu = function(){

this.create = function(){

var bg = game.add.tileSprite(0,0,game.width,game.height,'background'); //当作背景的tileSprite

var ground = game.add.tileSprite(0,game.height-112,game.width,112,'ground').autoScroll(-100,0); //当作地面的tileSprite

bg.autoScroll(-10,0); //让背景动起来

ground.autoScroll(-100,0); //让地面动起来

}

}

复制代码

然后来制作游戏标题,游戏标题flappy bird这几个字是一张图片,然后那个鸟是一个sprite,并且我们在sprite上执行了动画,使它的翅膀看起来是在动的。我要说的是怎么在sprite对象上实现动画。首先在加载鸟的图片时,我们加载的不当当就是一张鸟的图片,我们加载的是一个这样的图片:bird

我们看到这张图片有三只鸟,更确切的说是一只鸟的三个状态,或者说是动画中的三个帧。那我们怎样让他变成动画呢?在Loader对象中有一个spritesheet的方法,就是专门用来加载这种多帧图片的,我们看一下这个方法:

spritesheet(key, url, frameWidth, frameHeight, frameMax, margin, spacing)

key : 给这张图片指定的名称,以后在创建sprite等对象时会要用到的

url: 图片的地址

frameWidth : 图片中每帧的宽度

frameHeight : 图片中每帧的高度

frameMax : 最多有几帧

margin : 每帧的外边距

spacing : 每帧之间的间隔

我们上面那张鸟的图片,每一个鸟的宽高分别是34px和24px,所以frameWidth应该是34,frameHeight是24,然后我们这个动画有三帧,frameMax为3,帧与帧之间没有间隙,margin与spacing都为0。实际上spritesheet方法就是能让我们加载一个图片,并在这个图片上划分出帧来,以后使用这个图片的sprite就可以用这些帧来播放动画啦。要在sprite上实现动画,我们首先还得先定义一个动画,就是定义这个动画是由哪些帧组成的。sprite对象有个animations属性,代表的是Phaser中专门管理动画的对象:AnimationManager,该对象有一个add方法,用来添加动画,还有一个play方法,用来播放动画,它们具体的参数可以参阅文档。

下面再说一个非常重要的对象:Phaser.Group,也就是组。组相当于一个父容器,我们可以把许多对象放进一个组里,然后就可以使用组提供的方法对这些对象进行一个批量或是整体的操作。比如要使组里的对象同意进行一个位移,只需要对组进行位移就可以了,又比如要对组里的所有对象都进行碰撞检测,那么就只需要对这个组对象进行碰撞检测就行了。下面我们要制作的这个游戏标题是由一张文字图片和一支鸟组成的,我们就是把这两个东西放在一个组中,然后来进行整体的操作。

复制代码

game.States.menu = function(){

this.create = function(){

......

var titleGroup = game.add.group(); //创建存放标题的组

titleGroup.create(0,0,'title'); //通过组的create方法创建标题图片并添加到组里

var bird = titleGroup.create(190, 10, 'bird'); //创建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); //对这个组添加一个tween动画,让它不停的上下移动

}

}

复制代码

上面代码中的Tween对象,是专门用来实现补间动画的。通过game.add的tween方法得到一个Tween对象,这个方法的参数是需要进行补间动画的物体。然后我们可以使用Tween对象的to方法来实现补间动画。

to(properties, duration, ease, autoStart, delay, repeat, yoyo)

properties : 一个js对象,里面包含着需要进行动画的属性,如上面代码中的 {y:120}

duration : 补间动画持续的时间,单位为毫秒

ease : 缓动函数,默认为匀速动画

autoStart : 是否自动开始

delay : 动画开始前的延迟时间,单位为毫秒

repeat : 动画重复的次数,如果需要动画永远循环,则把该值设为 Number.MAX_VALUE

yoyo : 如果该值为true,则动画会自动反转

最后是添加一个开始游戏的按钮。Phaser提供了Button对象让我们能很简单的实现一个按钮。

复制代码

game.States.menu = function(){

this.create = function(){

......

var btn = game.add.button(game.width/2881064151,game.height/2,'btn',function(){//添加一个按钮

game.state.start('play'); //点击按钮时跳转到play场景

});

btn.anchor.setTo(0.5,0.5); //设置按钮的中心点

}

}

复制代码

Phaser中很多对象都有一个anchor属性,它表示这个物体的中心点,物体的位置平移、旋转的轴,都是以这个中心点为参照的。所以上面代码中我们要使按钮水平垂直居中,除了要把按钮的x,y属性分别设为游戏的宽高的一半外,还要把按钮的中心点设为按钮的中心。

最后我们把所有代码合起来,得到了menu这个state的最终代码,该state只需要一个create方法就行了:

复制代码

game.States.menu = 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到组里

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.start('play');

});

btn.anchor.setTo(0.5,0.5);

}

Phaser中很多对象都有一个anchor属性的更多相关文章

  1. 【性能优化】面试官:Java中的对象都是在堆上分配的吗?

    写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...

  2. Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法EDIT Object.defineProperty(obj, ...

  3. 【转载】Asp.Net中Cookie对象的作用以及常见属性

    Cookie对象是服务器为用户访问存储的特定信息,这些信息一般存储在浏览器中,服务器可以从提交的数据中获取到相应的Cookie信息,Cookie的最大用途在于服务器对用户身份的确认,即票据认证,用户会 ...

  4. 让NSArray数组中每个对象都调用的方法

    1. [array valueForKey:@"title"]; //Returns an array containing the results of invoking val ...

  5. 【阅读笔记:散列表】Javascript任何对象都是一个散列表(hash表)!

    什么是散列表? 散列表是Dictionary(字典)的一种散列表实现方式,字典传送门 一个很常见的应用是使用散列表来表示对象.Javascript语言内部就是使用散列表来表示每个对象.此时,对象的每个 ...

  6. Java中的对象都是在堆上分配的吗?

    作者:LittleMagic https://www.jianshu.com/p/8377e09971b8 为了防止歧义,可以换个说法: Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定 ...

  7. javascript中字符串对象常用的方法和属性

    前言 字符串是一种非常重要的数据类型,在Java等面向对象编程语言中,它代表对象类型,而在javascript中它却是一种基本数据类型,在开发的领域中,我们经常会碰到,无论是前端还是后台.比如后台验证 ...

  8. es6中的对象的可计算的属性名

    先简单的啰嗦一下对象的属性: var obj = { a:2 } 要访问obj中a的位置,方法:1. obj.a     //2            2..obj ["a"]   ...

  9. Powermockito 针对方法中new 对象的模拟,以及属性中new 对象的模拟

    PowerMocker 是一个功能逆天的mock 工具. 一,Powermockito 针对方法中new 对象的模拟 // 如何才能mock掉 WeChatConfigUtil 这个类,让 weCha ...

随机推荐

  1. Java for LeetCode 047 Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  2. Java for LeetCode 041 First Missing Positive

    Given an unsorted integer array, find the first missing positive integer. For example, Given [1,2,0] ...

  3. jquery给height拼接动态变量

    var sizeLength = "${list.size()}"; if(sizeLength==''){ sizeLength=0; } sizeLength=400*size ...

  4. July 21st, Week 30th Thursday, 2016

    What youth deemed crystal, age finds out was dew. 年少时的水晶,在岁月看来不过是露珠. As time goes by, we are gradual ...

  5. Android之记住密码与自动登陆实现

    本文主要讲述了利用sharedpreference实现记住密码与自动登陆功能 根据checkbox的状态存储用户名与密码 将结果保存在自定义的application中,成为全局变量 布局文件 < ...

  6. Jil序列化JSON

    使用Jil序列化JSON提升Asp.net web api 性能   JSON序列化无疑是Asp.net web api 里面性能提升最重要的一环. 在Asp.net web api 里面我们可以插入 ...

  7. Gym 100463A Crossings 逆序对

    Crossings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463 Description ...

  8. 【vijos1066】弱弱的战壕 线段树

    描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒 ...

  9. Kinect学习笔记(五)——更专业的深度图

           这一节的内容就是把深度图转换为彩色图,然后不再使用硬解码,而是继续采用sdk里面封装好的功能来减少测量的误差,以及避免转换为灰度图时,出现绿巨人时候的掉针的bug.       下面直接 ...

  10. C#学习笔记(八)——定义类的成员

    一.成员的定义 1.定义字段 class Myclass { public int MyInt; } 可以使用readonly关键字,表示这个字段只能在执行构造函数的过程中赋值,或者由初始化语句赋值. ...