zoukankan      html  css  js  c++  java
  • phaserjs 总结

    什么是Phaser?

    简单来说,Phaser就是一款免费开源的HTML5游戏框架

    它有什么特点?

    高性能:快速、免费、易于维护。一方面,开发者可以直接通过Koding平台上的VM开发系统进行代码编写及预览。另一方面,也可以在支持Canvas的浏览器中直接安装Phaser来进行游戏开发。

    多种支持:JavaScript、TypeScript双重支持、内置游戏对象的物理属性、WebGL、Canvas渲染自由切换、完全支持Web音频、输入:多点触控、键盘、鼠标、MSPointer事件。

    兼容性强:除了IE 9+、Firefox、Chrome、Safari及Opera等桌面浏览器之外,Phaser还支持Mobile Chrome(Android 2.2+)及Mobile Safari(iOS 5+)等移动浏览器。使用Phaser进行游戏开发没有任何语言设定。

    为什么选择它?

    在根据统计到的《2016年最火的15款html5游戏引擎》(原文地址:https://www.diycode.cc/topics/16)文章中可以看到,phaser.js排在第二位,在pixi.js和egret.js之前,而排在第一位的three.js学习难度和周期比较高,如果从受欢迎程度来讲的话,当然优先考虑phaser.js,如果专注于html5游戏开发或者有这方面的发展意向,那这几个都可以深入学习下。另外值得一提的是,egret.js是国内开发的一款H5框架,也就是俗称的白鹭,来自北京白鹭时代信息技术有限公司,毫无疑问,国人开发的框架,中文API读起来是最方便的,有兴趣的同学也可以优先考虑这个框架。

    一起学习

    引入

    <scripttype="text/javascript"src="_site/phaser/phaser.2.7.0.min.js"></script>

    创建一个简单得游戏场景

    <div id="phaser-example"></div>
    <scripttype="text/javascript"src="_site/phaser/phaser.2.7.0.min.js"></script>
    <script>
        var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload,create: create });
    function preload() { console.log(
    "preload"); //加载资源   }
      function create() { console.log(
    "create"); //创建场景   } </script>

    new Phaser.Game参数为:游戏的宽,游戏的高,游戏的引擎,游戏的容器id,游戏的各种状态,背景是否透明,是否消除锯齿,物理引擎设置。这样就会在id为phaser-example创建一个canvas场景,返回这个游戏对象。

    物理引擎

     物理引擎,听起来很高大上,其实说白了,就是解决物理现象的一些算法:比如速度、加速度、重力等等。

     Phaserjs中的物理引擎有三个,Arcade、Ninja和P2,三个物理引擎都提供了关于碰撞、重叠、移动等的处理方法,也都包含了重力、加速度、移动等方面的属性,不过也有不同,Arcade属于Phaserjs的内置引擎,Ninja引擎不是Phaserjs默认捆绑的物理引擎,使用的话需要先注册,P2物理引擎则是一个单独的物理引擎,很强大,不仅支持Phaserjs,也支持其他的一些框架

    //使用了ARCADE引擎,并设置这个场景的所有对象有拥有了这个重力
    function create() {
        game.physics.startSystem(Phaser.Physics.ARCADE);
     
        //设置游戏标准重力为100
        game.physics.arcade.gravity.y = 100;
    }

    碰撞检测

    function preload() {
        game.load.image('wizball', 'assets/sprites/wizball.png');
    }
    
    function create() {
        game.physics.startSystem(Phaser.Physics.ARCADE);
     
        ball1 = game.add.sprite(100, 240, 'wizball');
        ball2 = game.add.sprite(700, 240, 'wizball');
        game.physics.arcade.enable([ball1, ball2]);
    }
    
    function update () {
        //每次刷新都进行检测
        game.physics.arcade.collide(ball1, ball2, function(){ coll(ball1, ball2); });
    }
    
    //碰撞检测回调函数
    function coll(obj1, obj2){
        //obj1和obj2为碰撞的2个对象
    }

    游戏的状态

    游戏的状态中包括初始化游戏参数,加载资源,创建场景,监测更新,实时渲染等,使用什么的游戏状态,根据自己的需求来

    所有状态:init,preload,loadUpdate,loadRender,create,update,preRender,render,resize,paused,resumed,pauseUpdate,shutdown

    加载图片,文字,动画

    //加载图片
    function preload() {
        game.load.image('imageKey','assets/sprites/phaser2.png');
    }
    //渲染 function create() { //渲染一张图片   game.add.sprite(0, 0, 'imageKey');   //渲染文字   var text =game.add.text(game.world.centerX, game.world.centerY, "你好,欢迎来到Phaser的世界", textStyle);   //设置锚点 text.anchor.set(0.5, 0.5); }

     

    为了减少请求可以使用这种纹理图片,根据位置找到不同的图片

    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');
    }
    function create() {   
    //根据位置找到对象的图片   bmpText = game.add.bitmapText(0, 100,'myFont', 'A Bitmap Font from a Texture Atlas', 64); }

     

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

    加载动画其实就是每隔多长时间变化一下渲染的图片位置

    常用的基础属性

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

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

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

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

    鼠标,触屏,按键事件

    //鼠标事件
    function create() {
        //阻止事件冒泡
        game.input.mouse.capture = true;
        game.input.mouse.onMouseDown = function(){
            console.log("down"); //点击
        }
        game.input.mouse.onMouseWheel = function(){
            console.log("wheel"); //松开
        }
        game.input.mouse.onMouseMove = function(){
            console.log("move"); //点击中
        }
    }

    有很多是都发现down打印不出来,我们都会使用mousePointer或者activePointer对象来操作鼠标

    //触屏点击
    function create() {
        game.input.onDown.add(function() {
          console.log('DOWN');
          console.log(Date.now());
        });
        game.input.onHold.add(function() { //按下去2s后触发
          console.log('Hold');
          console.log(Date.now());
        });
        game.input.onUp.add(function() {
          console.log('UP');
        });
        game.input.onTap.add(function() {
          console.log('TAP');
        });
    }
    // 键盘四个方向键
    function create() { 
        upKey = game.input.keyboard.addKey(Phaser.Keyboard.UP);
        downKey = game.input.keyboard.addKey(Phaser.Keyboard.DOWN);
        leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
        rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
    }
    function update() {
        //判断按键是否被按下
        if (upKey.isDown)
        {
            sprite.y--;
        }
        else if (downKey.isDown)
        {
            sprite.y++;
        }
        
        if (leftKey.isDown)
        {
            sprite.x--;
        }
        else if (rightKey.isDown)
        {
            sprite.x++;
        }
    }

    不同的键对用不同的属性 http://phaser.io/docs/2.6.2/Phaser.KeyCode.html

    音频视频

    //音频
    function preload() {
    //这里要加载的元素支持数组格式 //官方的demo里说Firefox不支持mp3格式,所以要添加使用ogg格式的备选文件,不过我试了,mp3和ogg火狐都是支持的    game.load.audio('wizball', 'assets/audio/oedipus_wizball_highscore.ogg'); } function create() { //添加音乐到游戏场景并播放 music = game.add.audio('wizball'); music.play(); //设置音量 music.volume = 0.1; }
    //音频截取,其实很简单,类似于CSS Sprite,把许多小文件整合在一起,通过标记单独使用其中的某一部分
    function preload() {
        game.load.audio('sfx', 'assets/audio/SoundEffects/fx_mixdown.ogg');
    }
    
    function create() {
        game.add.image(0, 0, 'title');
        //注册音频文件
        fx = game.add.audio('sfx');
        //是否允许同时播放多段音乐
        fx.allowMultiple = false;
        //定义标记:关键字、开始时间、持续时间(单位:秒)
        fx.addMarker('alien death', 1, 1.0);
        fx.addMarker('boss hit', 3, 0.5);
        fx.addMarker('escape', 4, 3.2);//定义按钮关键字和位置
        makeButton('alien death', 600, 100);
        makeButton('boss hit', 600, 140);
        makeButton('escape', 600, 180);
    }
    //加载视频
    function preload() {
        game.load.video('countryroad', 'assets/video/z0011j50w5k.p302.1.mp4');
    }
    
    function create() {
        //注册视频并播放
        video = game.add.video('countryroad');
        video.play(true);
        //将视频添加到游戏窗口中:x,y,anchorX,anchorY,scaleX,scaleY
        video.addToWorld(400, 250, 0.5, 0.5);
        video.volume = 0.1;
    }

    音频和视频要注意的点就是兼容性,据我测试一些低端的手机是不支持的。剩下的就是播放、暂停、继续、停止、加大音量、减小音量这类操作,找到对应的api即可

    位移,拖拽和补间动画

    游戏j对象的位移都是通过改变游戏对象x,y坐标来实现的

    //位移
    function preload() {
        game.load.atlasJSONHash('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
    }
    var s; function create() { s = game.add.sprite(game.world.centerX, game.world.centerY, 'bot'); s.anchor.setTo(0.5, 0.5); s.animations.add('run'); s.animations.play('run', 10, true); } function update() { if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { s.x -= 4; } else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { s.x += 4; } }
    //拖拽
    function preload() {
        game.load.image('grid', 'assets/tests/debug-grid-1920x1920.png');
        game.load.image('atari', 'assets/sprites/atari800xl.png');
        game.load.image('sonic', 'assets/sprites/sonic_havok_sanity.png');
    }
    function create() {
    var atari = group.create(32, 100, 'atari'); // 使atari对象可以操作 atari.inputEnabled = true; atari.input.enableDrag(); // atari.input.enableDrag(true, true, true); atari.events.onDragStart.add(onDragStart, this); atari.events.onDragStop.add(onDragStop, this); }
    //可以得到拖拽对象和触摸对象 function onDragStart(sprite, pointer) { }
    function onDragStop(sprite, pointer) { }

    enableDrag的参数

    enableDrag(lockCenter,bringToTop, pixelPerfect, alphaThreshold, boundsRect, boundsSprite)

    lockCenter:是否锁定中心,无论你按下的位置是在sprite的哪里,下一个画面sprite中心就会出现在你按下的地方;

    bringToTop:是否置顶,就是拖动结束后是否位于最顶层;

    pixelPerfect:是否启用像素识别,这样翻译有利于理解,一张png图片只可能是矩形,但是上面的图像不一定占满整个矩形,如果启用像素识别,代码会判断你点击的位置是否在图像上,如果点击的位置在空白区域,则拖动无效;

    alphaThreshold:像素识别的精度,取值范围0~255,数值越大精度越高;

    boundsRect:定义矩形边界;

    boundsSprite:定义一个sprite为边界,你可以试着添加一个和游戏窗口一样大的sprite图片,然后参数设置为它试下。

    //补间动画
    function preload() {
        game.load.spritesheet('monster', 'assets/sprites/pixi_monsters.png', 154, 170);
    }
    function create() {
    //添加一个图像 var monster = game.add.sprite(400, 300, 'monster', 0); monster.anchor.setTo(0.5); game.add.tween(monster)   .to({ x: game.world.width - 10, y: game.world.height - 80 }, 100, "Linear", false) .to({ x: game.world.width - 10, y: 0 }, 400, "Linear", false) .to({ x: game.world.width / 2, y: 0 }, 100, "Linear", true); }

    补间动画最重要的两个方法是from和to

     time(时间对象)和timer(定时器对象)

    //时间对象
    var timer;
    function create() { //延时执行 timer = game.time.events.add(Phaser.Timer.SECOND * 4, fadePicture, this); //重复运行(重复十次) game.time.events.repeat(Phaser.Timer.SECOND * 2, 10, createBall, this); //循环执行 game.time.events.loop(Phaser.Timer.SECOND, updateCounter, this); }
    function fadePicture() { }
    function createBall() { }
    function updateCounter() { }

    time调用得到时间对象timer,也有对应的api去启动,暂停,重启,销毁

    function preload() {
        game.load.image('baddie', 'assets/sprites/space-baddie.png');
    }
    function create() {
    //创建一个组 enemies = game.add.group(); for (var i = 0; i < 16; i++) { //在组里面创建元素 enemies.create(360 + Math.random() * 200, 120 + Math.random() * 200, 'baddie'); } }

    组有点类似数组,将子项添加到组内,设置组的属性会给每个子项都设置,不用每个都操作一遍,这样很方便。

    总结:使用phaserjs创建小游戏要先了解自己得需求适合什么引擎,像p2引擎支持多边形碰撞,使用对了引擎才能走向成功。创建对象并给他设置他自己得属性,搞懂事件知道自己什么时候做出什么动作,使用纹理图和补间动画让对象动起来,时间对象就跟普通js得差不多,多个子项一定要使用组,做好碰撞检测。多去看看例子。

    phaser官网上有大量的例子,基本涵盖了常用的东西。phaser小站上也有一些大牛写的例子,仿照着写写,就会有提高的。

    官网:http://phaser.io/

    找了点博客帮助理解: https://blog.csdn.net/qq_36843675/article/details/79096043#load

    https://blog.csdn.net/daveleecn/article/details/79017410

    https://segmentfault.com/a/1190000009212221

    中文网:http://www.phaserengine.com/

    phaser小站:https://www.phaser-china.com/example-detail-422.html

    制作多边形图片:https://www.codeandweb.com/physicseditor

    社区:http://club.phaser-china.com/

    QQ群:519413640,384427721



  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/lichunjing/p/9570318.html
Copyright © 2011-2022 走看看