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



  • 相关阅读:
    大规模扩展casbin的一种方案
    casbin 性能优化的几点建议
    使用casbin进行应用访问控制
    使用xid 生成 唯一id
    jcsabin FilteredAdapter 逻辑处理问题
    jcasbin redis watcher 一些修改
    cube.js 0.27.31 一些新特性
    sdkman Stop! maven is not a valid candidate 类似问题解决
    lakefs 类似git 的文件对象存储
    readme.so docker 镜像
  • 原文地址:https://www.cnblogs.com/lichunjing/p/9570318.html
Copyright © 2011-2022 走看看