使用Phaser进行JavaScript游戏编程

Phaser是适用于台式机和移动设备的HTML5游戏框架。 它是快速,免费和开源的。 Phaser当前版本为2.0.7 。 它同时支持WebGL和Canvas。 它具有许多功能,可帮助您进行游戏开发。 就像ActionScript 3的Flixel游戏框架一样。在本文中,我们将使用Phaser.State使用Phaser构建游戏框架。 为简单起见,我们将不使用任何Phaser游戏对象,例如精灵或组。 我还将提到一些关于补间的内容。

安装相位器

使用以下命令,可以通过Bower使用Phaser:

bower install phaser-official --save

或者,您可以直接从GitHub抓取文件。 Phaser的完整版本在build目录中。 在build/custom目录中还有一些自定义的构建,例如不带物理引擎的Phaser。

有许多社区教程和入门指南。 我建议您检查其中的一些以便熟悉Phaser。 我的最爱之一是《 飞鸟》四部分系列 。 在Phaser官方网站上可以找到大量的教程, 示例文档

脚手架移相器

用于相位器的基于Grunt的Yeoman发电机可用于脚手架项目。 您可以使用以下命令进行安装:

npm install -g generator-phaser-official
yo phaser-official

该生成器非常适合快速启动和运行,但是,出于本教程的目的,我们将从头开始。

移相器目录结构

我们的Phaser项目将使用以下所示的目录结构。 main.js开始游戏,而app.js定义我们的Phaser应用程序。 prefabs目录用于游戏对象,而states目录用于游戏状态。

|-- app.js
|-- main.js
|-- prefabs
`-- states
    |-- boot.js
    |-- level_intro.js
    |-- level_master.js
    |-- level_round.js
    |-- main_intro.js
    |-- main_menu.js
    `-- preload.js

如果要在这些文件中添加纯script标记,则必须注意它们的包含顺序。 我更喜欢使用RequireJS,另一种替代方法是Browserify。

Phaser.State

本节将重点介绍Phaser.State的使用。 移相器状态封装了游戏的不同状态。 游戏状态的示例包括预加载,主菜单,级别1,级别2,帮助,暂停等。状态开始时,您将创建与该状态相关的游戏对象。 稍后,您可以切换到其他状态,Phaser会清理您的旧游戏对象,以便您可以创建新游戏对象并显示它们。

您可以通过使用某些hook方法定义对象来定义状态。 重要的是:

  • init –状态开始时调用的方法。 传递了一个参数以启用状态之间的数据共享。
  • preload –状态开始时调用的方法。 它用于先加载资产。
  • create –在preload之后调用的方法,用于创建游戏对象。
  • update –为每个帧调用的方法,用于用户轮询和冲突检测。
  • shutdown –一种shutdown状态时调用的方法,用于清理游戏对象。

组织状态流

这是我们相位器状态的状态图。 BootPreload状态是用于设置配置和加载游戏资产的实际状态。 MainMenu状态用于显示主菜单。 其他关卡状态则用于实际游戏并在不同关卡和回合之间切换。 这些级别分为几轮。 每个关卡都有一些回合,一旦播放,您就可以进入下一个关卡。

移相器游戏状态

游戏状态

引导状态通过preload hook方法加载预加载器资产,并通过create方法设置Phaser游戏设置,例如缩放比例和输入指针。

File: states/boot.js

function Boot() {};

Boot.prototype = {
  preload: function() {
    // load preloader assets
  },
  create: function() {
    // setup game environment
    // scale, input etc..

    this.game.state.start('preload');
  }
};

Preload状态将加载所有游戏资产,然后切换到main-intro状态。

File: states/preload.js

Preload.prototype = {
  preload: function() {
    // load all game assets
    // images, spritesheets, atlases, audio etc..
  },
  create: function() {
    this.game.state.start('main-intro');
  }
};

MainIntro状态显示游戏的简介,徽标,信用等。它不需要preload方法,因为它会在对象之间补间两秒钟,然后切换到main-menu状态。 我在此处添加了一个补间,只是为了让您了解,您可以使用淡入淡出,缩小和滑动等效果来过渡对象,以实现状态转换效果。

File: states/main_intro.js

function MainIntroState() {};

MainIntroState.prototype = {
  create: function() {
    // add main intro assets into the world
    this.tweenFadeState();
  },

  tweenFadeState: function() {
    this.game.add.tween({})
      .to({alpha: 1}, 2000)
      .onComplete.add(function() {
        this.game.state.start('main-menu');
      }, this);
  }
};

MainMenu状态显示主菜单。 然后,用户可以与菜单中的项目进行交互。 为简单起见,我添加了一个键盘事件,该事件将触发一系列补间,最后切换到level-master状态。 补间链接对于合并动画(如缩小菜单然后使显示淡入淡出)很有用。

File: states/main_menu.js

MainMenuState.prototype = {
  create: function() {
    this.enterKey = this.game.input.keyboard
        .addKey(Phaser.Keyboard.ENTER);

    this.enterKey.onDown.add(this.tweenPlayState, this);
  },
  tweenPlayState: function() {
    var tweenMenuShrink = this.game.add.tween({})
          .to({x: 0, y: 0}, 200);

    var tweenFadeIn = this.game.add.tween({})
          .to({alpha: 1}, 2000);

    tweenFadeIn.onComplete.add(function() {
      this.game.state.start('level-master');
    }, this);

    tweenMenuShrink.chain(tweenFadeIn);
    tweenMenuShrink.start();
  }
};

注意,在示例中,我没有补间任何有用的东西。 为简单起见,您应该在此处插入游戏对象。 另外,我不创建任何游戏对象,但是您可以在create方法中进行操作。 有关更多信息,请查看Phaser示例和文档。

LevelMaster状态是无头状态,它决定要切换到哪个状态。 它不会在游戏世界上显示任何内容。 唯一的目的是决定是否应该切换到level-round状态或level-intro状态,最重要的是,它会在状态之间更新并传递游戏数据( this.levelData )。

File: states/level_master.js

LevelMasterState.prototype = {
  init: function(levelData) {
    if (!levelData) {
      levelData = {
        level: 0,
        round: 1,
        players: [
          { score: 0, skill: 1 },
          { score: 0, skill: 1 }
        ]
      };
    }

    this.levelData = levelData;
    this.winScore = 2;
  },

  create: function() {
    this.decideLevelState();
  }
};

当新级别开始时, level-intro状态开始。 level-intro状态显示新级别的介绍,例如显示您所在的级别。 在level-intro ,它会切换到level-round ,这是实际玩游戏的地方。

一轮结束后,它是一个新的level-round或一个新的水平。 这种逻辑发生在我们的decideLevelState函数中。 如果是第一个级别,或者我们有一个级别的获胜者,我们将切换到下一个级别,否则我们将切换到下一个回合。

this.levelData保存游戏数据,例如游戏级别,游戏回合和玩家得分。 我们按照逻辑更新它并传递状态。

File: states/level_master.js

LevelMasterState.prototype = {
  decideLevelState: function() {
    if (this.isFirstLevel() || this.getWinningPlayer() !== -1) {
      this.nextLevel();
    } else {
      this.nextRound();
    }
  },
  nextLevel: function() {
    this.levelData.level++;

    this.levelData.players.forEach(function(p) {
      p.score = 0;
    }, this);

    this.levelData.round = 1;

    this.game.state.start('level-intro', true, false, this.levelData);
  },
  nextRound: function() {
      this.levelData.round++;
      this.game.state.start('level-round', true, false, this.levelData);
  }
};

LevelIntro状态显示关卡介绍信息,例如您所在的关卡以及一些介绍动画。 我们传递用于保存游戏数据的levelData参数。 在create方法中,如果是游戏的第一关,我们通过显示技能菜单来使用levelData技能菜单是指玩家选择想要玩的技能的菜单,但这取决于您。 最后,它切换到level-round状态。

File: states/level_intro.js

LevelIntroState.prototype = {
  init: function(levelData) {
    this.levelData = levelData;
  },
  create: function() {
    var tweenIntro = this.tweenIntro();

    if (this.levelData.level === 1) {
      var tweenSkillMenuPop = this.tweenSkillMenuPop();

      tweenIntro.chain(tweenSkillMenuPop);
      tweenSkillMenuPop.onComplete.add(this.levelStart, this);
    } else {
      tweenIntro.onComplete.add(this.levelStart, this);
    }
  },
  levelStart: function() {
    this.game.state.start('level-round', true, false, this.levelData);
  },
  tweenIntro: function() {
    var tween = this.game.add.tween({})
      .to({alpha: 0}, 1000, Phaser.Easing.Linear.None, true);

    return tween;
  },
  tweenSkillMenuPop: function() {
    var tween = this.game.add.tween({})
      .to({x: 1, y: 1}, 500, Phaser.Easing.Linear.None, true);

    return tween;
  }
};

最后, LevelRound状态是实际玩游戏的地方。 如果需要,可以使用其update方法。 为简单起见,我添加了一个简单的按键交互操作,该交互操作在按Enter键时结束状态。 这里重要的一点是,它会切换回level-master ,首先传递它从level-master获得的levelData

File: states/level_round.js

LevelRoundState.prototype = {
  init: function(levelData) {
    this.levelData = levelData;
  },
  create: function() {
    this.enterKey = this.game.input.keyboard
      .addKey(Phaser.Keyboard.ENTER);

    this.enterKey.onDown.add(this.roundEnd, this);
  },
  roundEnd: function() {
    this.nextRound();
  },
  nextRound: function() {
    this.game.state.start('level-master', true, false, this.levelData);
  }
};

这样就完成了状态流。 所有这些为我们提供了一个水平状态循环,看起来像这样:

Boot -> Preload ->
main-intro -> main-menu ->
level-master -> Level1 ->
level-master -> L1 Round1 ->
level-master -> L1 Round2 ->
level-master -> Level2 ->
level-master -> L2 Round1 ->

您可以通过切换到main-menu状态的操作在level-round状态中退出此循环。

启动相位器

现在,我们将开始“移相器”游戏。 将此div放在您的页面内。 移相器会将画布放在那里。

File index.html

<div id="game-area"></div>

我们必须创建一个Phaser.Game ,将所有状态添加到StateManager ,然后启动启动状态。

File: app.js

function Game() {}

Game.prototype = {
  start: function() {
    var game = new Phaser.Game(640, 480, Phaser.AUTO, 'game-area');

    game.state.add('boot', BootState);
    game.state.add('preload', PreloadState);
    game.state.add('main-intro', MainIntroState);
    game.state.add('main-menu', MainMenuState);
    game.state.add('level-master', LevelMasterState);
    game.state.add('level-intro', MainIntroState);
    game.state.add('level-round', LevelRoundState);
    game.state.start('boot');
  }
};

最后,使用以下代码启动游戏。

File: main.js

var game = new Game();
game.start();

结论

Phaser.State我们的Phaser.State文章结束了。 这只是Phaser游戏的骨架。 Phaser为您提供了许多其他功能,例如精灵,动画,声音,物理效果,缩放等。 您可以在GitHub上找到我们示例的存储库。

From: https://www.sitepoint.com/javascript-game-programming-using-phaser/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值