游戏开发 | Phaser基本操作

1,412 阅读6分钟

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

前言

开发网页游戏,很久之前用AS3做合金弹头,现在Flash慢慢没落之后,新一代的H5游戏引擎崛起,比较知名的有coco2d.js、Unity-2D、laya,以及老东家的 Egret2D、Egret3D,这些主流引擎都非常强,如果你对TS比较熟练的话,这里推荐你用egret,如果是你是原生JS的爱好者(其实本文的主角也支持TS,不过既然你都用TS了,何不尝试egret呢),今天我将带你一起领略一款轻量高效又免费的H5引擎:Phaser。

回顾

前面说道Phaser是H5 2D游戏开发的开源免费框架,支持JS和TS,基于Pixi.js引擎,内置游戏对象的物理属性,渲染模式同时支持Canvas和WebGL,基于浏览器支持可自由切换。

鉴于Phaser轻量便捷、免费的特点,使用Phaser来开发小型也有的优势显而易见,可以直接在支持Canvas的浏览器中直接引用或安装Phaser来进行游戏开发。

上一篇说到Phaser的生命周期,以及Phaser资源引用、不同主函数的模块,

音视频的导入

function preload(){
  game.load.audio("bgmap3","./assets/audio/bg.ogg");
}
function create(){
  var bgmusic = game.add.audio("bgmap3");
  bgmusic.play();
}

创建了一个音频对象bgmusic,可以对其播放,暂停,调节音量。备注:因为跨域,音频文件的加载需要搭建本地服务器。

// 音频常用的api有播放、暂停、恢复、停止、分段标注、淡入淡出
  this.preload = function(){
    game.load.audio('music', 'asset/sound/1.mp3');
    game.load.image('btn_play', 'asset/sound/btn_play.png');
    game.load.image('btn_pause', 'asset/sound/btn_pause.png'); 
    game.load.image('btn_resume', 'asset/sound/btn_resume.png');
    game.load.image('btn_stop', 'asset/sound/btn_stop.png');
  }

  this.create = function(){
    var sound = game.add.audio('music', 0.1);

    var btn_play = game.add.button(260, 20, 'btn_play', function(){
      sound.play(); //播放
    });

    var btn_pause = game.add.button(260,145, 'btn_pause', function(){
      sound.pause(); //暂停
    });

    var btn_resume = game.add.button(260, 280, 'btn_resume', function(){
      sound.resume(); //恢复
    });

    var btn_stop = game.add.button(260, 415, 'btn_stop', function(){
      sound.stop(); //停止
    });

    //  标注声音 sound.addMarker(name, start, duration, volume?, loop?); 
    //  移除标注 sound.removeMarker(name);
    sound.addMarker('marker1', 5, 1);

    // 标注       
    var btn_play = game.add.button(260, 20, 'btn_play', function(){  
      sound.play('marker1'); //播放
    });
    var sound = game.add.audio('music');


    var btn_play = game.add.button(260, 20, 'btn_play', function(){      
      sound.fadeIn(3000); //淡入   
    });

    var btn_pause = game.add.button(260,145, 'btn_pause', function(){           
      sound.fadeOut(3000); //淡出          
    });

phaser基本事件

  • game.onblur 失去焦点

  • game.onFocus 获取焦点

  • game.onPause 暂停焦点

  • game.onResume 恢复事件

  • game.scale.onFullScreenChange 进入、退出全屏

  • game.scale.onOrientationChange 设备横竖屏切换

  • game.scale.onSizeChange 游戏尺寸改变

  • game.load.onFileComplete 单个资源加载完成

  • game.load.onFileError 当文件加载失败

  • game.load.onFileStart 当文件开始加载

  • game.load.onLoadComplete 当所有资源加载完成

Phaser常用动画

var tween = game.add.tween();

tween.onStart                 // 动画开始

tween.onComplete         // 动画完成

tween.onLoop                // 动画循环

tween.onRepeat            // 动画重复

var animation = new Phaser.Animation()

animation.onStart          //动画开始

animation.onComplete  // 动画完成

animation.onLoop         // 动画循环

animation.onUpdate     // 动画的帧变化时

Phaser.Input对象

它包括鼠标事件、键盘事件以及触摸事件等等。

function create(){
  game.input.onDown.addOnce(function(){
    // 按下后的回调事件
  })

  game.input.onUp.addOnce(function(){
    // 按下离开后的回调事件
  })

  game.input.onTap.addOnce(function(){
    // 轻击后的回调事件
  })

  game.input.onHold.addOnce(function(){
    // 长按后的回调事件
  })

  game.input.addMoveCallback(move,this);
    // 鼠标/手指移动监听

  game.input.deleteMoveCallback(move,this);
    // 移除鼠标/手指移动监听
}

function move(){
  document.title = game.rnd.between(0,100)
}

Phaser.Pointer对象

Pointer对象即指针对象,可以是鼠标、手指或其他的输入设备。

function create(){
  this.pointer = game.input.activePointer;
  // 获取Pointer对象
}

function update(){
  document.title = this.pointer.clientX;
  // this.pointer.clientY
  // this.pointer.x / this.pointer.y
  // 指针事件发生时的x、y坐标
  if(this.pointer.isDown){
    // 指针按下后的回调
  }
  if(this.pointer.isUp){
    // 指针弹起后的回调
  }
}

Phaser.Keyboard对象

function create(){
  // 获取键盘对象
  this.keyboard = game.input.keyboard;

  // 添加一个键对象
  this.keyA = this.keyboard.addKey(Phaser.Keyboard.A);

  // 创建一个方向键对象
  this.cursor = this.keyboard.createCursorKeys();

  // 监听所有按键的回调,包括onDown,onUp...

  this.keyA.onDown.addOnce(function(){
    // 按下自定义键对象后的回调函数
  })

  this.keyA.onUp.addOnce(function(){
    // 释放自定义键后的回调函数
    // 如果这个自定义键还处于按下状态或其他状态,则暂不执行
  })
}

function update(){
  if(this.keyA.isDown){
    // 按下自定义键的状态
  }
  if(this.cursor.left.isDown){
    // 按下了 left 键
  }
  if(this.cursor.right.isDown){
    // 按下了 right 键
  }
}

比如一个常见的业务场景,游戏中点击某个按钮或点击游戏特定区域实现暂停,这里可以根据游戏情况给定游戏暂停的条件用事件。

function create(){
  game.onPause.add(function(){
    console.log("游戏已暂停")
  })
}

function update(){
  game.paused = true;
}

游戏对象的交互

Phaser.Events对象

事件集合体,挂靠在宿主(游戏中的显示对象)身上,也有部分是系统事件。

function create(){
  game.state.backgroundColor = "#F20";
  this.oBtext = game.add.text(0,0,"测试对象");

  // 开启对象的输入事件(可以接收回调事件)
  this.oBtext.inputEnabled = true; 

  // onInputDown、onInputUp、onInputOver、onInputOut 按下、释放、经过、离开
  this.oBtext.events.onInputDown.addOnce(testOnDown);
}

function testOnDown(){
  // 点击 舞台中的“测试对象”后的回调函数
}

Phaser.InputHandler对象

封装了一些与宿主相关的用户交互方法和用户输入属性。

function create(){
  game.state.background = "#F20";

  this.oBtext1 = game.add.text(0,0,"测试对象")
  this.oBtext2 = game.add.text(0,0,"文本对象")

  this.oBtext2.inputEnabled = true;
  // 开启对象的 输入事件(不是点击输入,是允许事件)

  this.inputHandler = this.oBtext2.input;
  // 获取文本对象的 inputHandler 对象

  this.inputHandler.disableDrag();
  // 禁止拖拽

  this.inputHandler.enableDrag();
  // 运行拖拽对象

  this.inputHandler.boundsSprite = this.oBtext1;
  // 限制 oBtext2 的拖拽范围 是 oBtext1的文本大小

  this.inputHandler.useHandCursor = true;
  // 是否使用鼠标手形图标

  inputHandler.pointerOver();
  // 判断指针是否在对象内

  inputHandler.pointerOut();
  // 判断指针是否在对象之外

  inputHandler.pointerX;
  // 当指针在对象内部时,相对于对象的 x 坐标

  inputHandler.pointerY;
  // 当指针在对象内部时,相对于对象的 y 坐标

  inputHandler.bringToTop;
  // 当点击或拖动该对象时是否把该对象 置顶显示(一般是true)
}

Phaser的交互事件远不止这些,但我不是官网API的搬运工过,这些是我觉得平常最常用的,足以开发小型页游的一些基本交互事件,也是学习Phaser最先应当掌握的东西。具体的PAI后续将以表格的形式总结出来,方便我自己还有大家一起学习。

游戏就绪之前

一般游戏舞台,一般都是由背景、精灵、舞台其他无关建筑构成。前面说过,这些资源在 boot 函数阶段或 loading 阶段分步加载,当资源加载完之后,我们一般会用指示条或其他形式来告知用户游戏目前状态,当全部加载完之后,可以直接进入游戏主函数,也可以显示一张图片or文件,由用户点击触发事件进入游戏,比如用 button 或者 text 添加事件来进入主游戏,例如

image.png

function Menu(game) {
  this.preload=function () {
    game.gameData = {
    maps:[
      {name:"map-0",entries:[[7,14,1,1]]},
      {name:"map-1",entries:[[0,8,2,1],[7,0,0,0],[15,12,3,0]]},
      {name:"map-2",entries:[[10,0,2,0],[15,7,1,0],[11,15,4,1]]},
      {name:"map-3",entries:[[0,8,1,2],[9,0,3,1],[13,15,3,2]]}, 
      {name:"map-4",entries:[[0,11,5,0],[5,0,2,2],[7,15,4,2]]},
      {name:"map-5",entries:[[15,4,4,0]]}
    ],
    currMap:0,
    currPos:[7,5],
    currFace:"DOWN",
    items:[]
    };
  };

  this.create = function() {
    var txt = game.add.text((game.width)/2, 200, "点击屏幕即开始游戏", {fontSize: "16px", fill: "#FFFFFF" });
    txt.anchor.setTo(0.5);  
    game.input.onDown.add(function(){game.state.start("main");}, this);
  };
}

总结

下一篇开始,将开始记录游戏实战环节,最终会实现一个Phaser版的指尖大冒险。