热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用Phaser来制作一个html5游戏——flappybird(一)【转】

Phaser是一个简单易用且功能强大的html5游戏框架,利用它可以很轻松的开发出一个html5游戏。在这篇文章中我就教大家如何用Phaser来制作一个前段时间很火爆的游戏:Fla

Phaser是一个简单易用且功能强大的html5游戏框架,利用它可以很轻松的开发出一个html5游戏。在这篇文章中我就教大家如何用Phaser来制作一个前段时间很火爆的游戏:Flappy Bird,希望大家看后也能做出自己的html5游戏。大家可以先点击这里来试玩一下我已经做好的这个游戏,感受一下Phaser的游戏效果,游戏的完整代码我已经放到github上了。支持的浏览器:IE9+、Firefox、Chrome、Opera、Safari以及移动端的能支持html5的浏览器,推荐使用谷歌浏览器,因为它性能最好。 phaser.js的源码可以到它在github上的托管里去下载,游戏要用到的图片声音等素材资源请点击这里下载。Phaser的使用非常简单,只需要引入它的主文件,然后在页面中指定一个用来放置canvas的元素,然后实例化一个 Game 对象就可以了。












实例化Game对象后,接下来要做的就是创建游戏会用到的各种场景了,也就是上面说的state,那么怎么才能创建一个state呢?state可以是一个js自定义对象,也可以是一个函数,只要它们存在preload、create、update这三个方法中的任意一个,就是一个合法的state。

//state可以是一个自定义对象
var state1 = {
    preload : function(){ },
    create : function(){ },
    update : function(){ }    
}
//state也可以是一个构造函数
var state2 = function(){
    this.preload = function(){ };
    this.create = function(){ };
    this.update = function(){ };
}
//只要存在preload、create、update三个方法中的一个就可以了
var state3 = function(){
    this.update = function(){  };
}
//当然state里也可以存在其他属性或方法
var state4 = function(){
    this.create = function(){ };
    this.aaa = function(){ }; //其他方法
    this.bbb = 'hello'; //其他属性
}

在这个游戏中,我们会用到4个state,我们可以通过game.state.add()方法来给游戏添加state,然后用game.state.start()方法来调用state,详细信息请看state的文档

var game = new Phaser.Game(288,505,Phaser.AUTO,'game'); 
game.States = {}; //创建一个对象来存放要用到的state
game.State.boot = function(){ ... }  //boot场景,用来做一些游戏启动前的准备
game.State.prelaod = function(){ ... } //prelaod场景,用来显示资源加载进度
game.State.menu = function(){ ... } //menu场景,游戏菜单
game.State.play = function(){ ... } //play场景,正式的游戏部分
//把定义好的场景添加到游戏中
game.state.add('boot',game.States.boot);
game.state.add('preload',game.States.preload); 
game.state.add('menu',game.States.menu); 
game.state.add('play',game.States.play);
 
//调用boot场景来启动游戏
game.state.start('boot');


制作资源加载进度条

游戏要用到的一些图片、声音等资源都需要提前加载,有时候如果资源很多,就有必要做一个资源加载进度的页面,提高用户等待的耐心。这里我们用一个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场景
    };
}

在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游戏菜单场景了
    }
}

首先是背景图与地面,我们看到这两个东西是会动的,地面移动动的速度快一些,背景图慢一些,在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); //让地面动起来
    }
}

下面再说一个非常重要的对象: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动画,让它不停的上下移动
    }
}

game.States.menu = function(){    this.create = function(){
        ......        var btn = game.add.button(game.width/2,game.height/2,'btn',function(){//添加一个按钮
            game.state.start('play'); //点击按钮时跳转到play场景        });
        btn.anchor.setTo(0.5,0.5); //设置按钮的中心点    }
}

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);
    }
}


推荐阅读
  • pyecharts 介绍
    一、pyecharts介绍ECharts,一个使用JavaScript实现的开源可视化库,可以流畅的运行在PC和移动设备上,兼容当前绝大部 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了如何使用PHP代码将表格导出为UTF8格式的Excel文件。首先,需要连接到数据库并获取表格的列名。然后,设置文件名和文件指针,并将内容写入文件。最后,设置响应头部,将文件作为附件下载。 ... [详细]
  • Python操作MySQL(pymysql模块)详解及示例代码
    本文介绍了使用Python操作MySQL数据库的方法,详细讲解了pymysql模块的安装和连接MySQL数据库的步骤,并提供了示例代码。内容涵盖了创建表、插入数据、查询数据等操作,帮助读者快速掌握Python操作MySQL的技巧。 ... [详细]
  • JavaScript简介及语言特点
    本文介绍了JavaScript的起源和发展历程,以及其在前端验证和服务器端开发中的应用。同时,还介绍了ECMAScript标准、DOM对象和BOM对象的作用及特点。最后,对JavaScript作为解释型语言和编译型语言的区别进行了说明。 ... [详细]
  • 本文介绍了网页播放视频的三种实现方式,分别是使用html5的video标签、使用flash来播放以及使用object标签。其中,推荐使用html5的video标签来简单播放视频,但有些老的浏览器不支持html5。另外,还可以使用flash来播放视频,需要使用object标签。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
author-avatar
苦蔷薇1988
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有