用Phaser制作iOS游戏circle path

前几天,我发布了教程“【HTML5游戏原型】用Phaser制作了TwinSpin游戏”,我一直都说要充分重用代码提高开发效率,今天就基于TwinSpin的代码,创建另外一个叫做Circle path的游戏原型,好吧,基本重现了原版的游戏。
Circle Path

我确定这个是Apple store推荐的特色游戏,适用平台是iPhone或iPad。

不管怎么样,下面就是游戏原型。把握好时机,点击或触摸屏幕,让小球停止旋转,并落到目标位置上去。
点击图片查看游戏
circlePath游戏的官方介绍里说《你的预感能力怎么样?瞬间判断能力如何?时间把握的好不好?反应能力高不高?》

这我不知道,我只知道游戏源代码和TwinSpin游戏非常相似。唯一的不同是这里使用了线性差值算法,实现了镜头跟随效果

我知道实现这个效果的方法有很多种,但我还是希望介绍线性差值法,因为我在Unity种也创建了这个算法原型,后续我会详细的介绍两个游在开发中遇到的问题。

下面是游戏源代码

var game;

var ballDistance = 120;
var rotationSpeed = 4;
var angleRange = [25, 155];
var visibleTargets = 7;
var bgColors = [0x62bd18, 0xffbb00, 0xff5300, 0xd21034, 0xff475c, 0x8f16b2];


window.onload = function() {	
	game = new Phaser.Game(640, 960, Phaser.AUTO, "");
     game.state.add("PlayGame", playGame);
     game.state.start("PlayGame");
}

var playGame = function(game){};

playGame.prototype = {
     preload: function(){
          game.load.image("ball", "ball.png");
          game.load.image("target", "target.png");
          game.load.image("arm", "arm.png");
          game.scale.pageAlignHorizontally = true;
          game.scale.pageAlignVertically = true;
          game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
     },
     create: function(){
          this.savedData = localStorage.getItem("circlepath")==null?{score:0}:JSON.parse(localStorage.getItem("circlepath"));
          var style = {
               font: "bold 64px Arial",
               fill: "#ffffff"
          };
          var text = game.add.text(0, game.height - 64, "Best score: "+this.savedData.score.toString(), style);
          this.destroy = false;
          this.saveRotationSpeed = rotationSpeed;
          this.tintColor = bgColors[game.rnd.between(0, bgColors.length - 1)];
          do{
               this.tintColor2 = bgColors[game.rnd.between(0, bgColors.length - 1)];     
          } while(this.tintColor == this.tintColor2)
          game.stage.backgroundColor = this.tintColor;
          this.targetArray = [];
          this.steps = 0;
          this.rotatingDirection = game.rnd.between(0, 1);
          this.gameGroup = game.add.group();
          this.targetGroup = game.add.group();
          this.ballGroup = game.add.group();
          this.gameGroup.add(this.targetGroup);
          this.gameGroup.add(this.ballGroup);
          this.arm = game.add.sprite(game.width / 2, game.height / 4 * 2.7, "arm");
          this.arm.anchor.set(0, 0.5);
          this.arm.tint = this.tintColor2;
          this.ballGroup.add(this.arm);
          this.balls = [
               game.add.sprite(game.width / 2, game.height / 4 * 2.7, "ball"),
               game.add.sprite(game.width / 2, game.height / 2, "ball")                   
          ]
          this.balls[0].anchor.set(0.5);
          this.balls[0].tint = this.tintColor2;
          this.balls[1].anchor.set(0.5);
          this.balls[1].tint = this.tintColor2;
          this.ballGroup.add(this.balls[0]);
          this.ballGroup.add(this.balls[1]);
          this.rotationAngle = 0;
          this.rotatingBall = 1;
          var target = game.add.sprite(0, 0, "target");
          target.anchor.set(0.5);
          target.x = this.balls[0].x;
          target.y = this.balls[0].y;
          this.targetGroup.add(target);   
          this.targetArray.push(target);      
          game.input.onDown.add(this.changeBall, this);
          for(var i = 0; i < visibleTargets; i++){
               this.addTarget(); 
          }
          
     },
     update: function(){
          var distanceFromTarget = this.balls[this.rotatingBall].position.distance(this.targetArray[1].position);
          if(distanceFromTarget > 90 && this.destroy && this.steps > visibleTargets){
               this.gameOver();
          }
          if(distanceFromTarget < 40 && !this.destroy){
               this.destroy = true;
          }
          this.rotationAngle = (this.rotationAngle + this.saveRotationSpeed * (this.rotatingDirection * 2 - 1)) % 360;
          this.arm.angle = this.rotationAngle + 90;
          this.balls[this.rotatingBall].x = this.balls[1 - this.rotatingBall].x - ballDistance * Math.sin(Phaser.Math.degToRad(this.rotationAngle));
          this.balls[this.rotatingBall].y = this.balls[1 - this.rotatingBall].y + ballDistance * Math.cos(Phaser.Math.degToRad(this.rotationAngle));
          var distanceX = this.balls[1 - this.rotatingBall].worldPosition.x - game.width / 2;
          var distanceY = this.balls[1 - this.rotatingBall].worldPosition.y - game.height / 4 * 2.7;
          this.gameGroup.x = Phaser.Math.linearInterpolation([this.gameGroup.x, this.gameGroup.x - distanceX], 0.05);
          this.gameGroup.y = Phaser.Math.linearInterpolation([this.gameGroup.y, this.gameGroup.y - distanceY], 0.05);                   
     },
     changeBall:function(){
          this.destroy = false;
          var distanceFromTarget = this.balls[this.rotatingBall].position.distance(this.targetArray[1].position);
          if(distanceFromTarget < 20){
               this.rotatingDirection = game.rnd.between(0, 1);
               var detroyTween = game.add.tween(this.targetArray[0]).to({
                    alpha: 0
               }, 500, Phaser.Easing.Cubic.In, true);
               detroyTween.onComplete.add(function(e){
                    e.destroy();
               })
               this.targetArray.shift();
               this.arm.position = this.balls[this.rotatingBall].position;
               this.rotatingBall = 1 - this.rotatingBall;
               this.rotationAngle = this.balls[1 - this.rotatingBall].position.angle(this.balls[this.rotatingBall].position, true) - 90;
               this.arm.angle = this.rotationAngle + 90; 
               for(var i = 0; i < this.targetArray.length; i++){
                    this.targetArray[i].alpha += 1 / 7;  
               }      
               this.addTarget();
          }
          else{
               this.gameOver();
          }   
     },
     addTarget: function(){
          this.steps++;
          startX = this.targetArray[this.targetArray.length - 1].x;
          startY = this.targetArray[this.targetArray.length - 1].y;          
          var target = game.add.sprite(0, 0, "target");
          var randomAngle = game.rnd.between(angleRange[0] + 90, angleRange[1] + 90);
          target.anchor.set(0.5);
          target.x = startX + ballDistance * Math.sin(Phaser.Math.degToRad(randomAngle));
          target.y = startY + ballDistance * Math.cos(Phaser.Math.degToRad(randomAngle));
          target.alpha = 1 - this.targetArray.length * (1 / 7);
          var style = {
               font: "bold 32px Arial",
               fill: "#" + this.tintColor.toString(16),
               align: "center"
          };
          var text = game.add.text(0, 0, this.steps.toString(), style);
          text.anchor.set(0.5);
          target.addChild(text);
          this.targetGroup.add(target);   
          this.targetArray.push(target);      
     },
     gameOver: function(){
          localStorage.setItem("circlepath",JSON.stringify({
               score: Math.max(this.savedData.score, this.steps - visibleTargets)
	     }));
          game.input.onDown.remove(this.changeBall, this);
          this.saveRotationSpeed = 0;
          this.arm.destroy();
          var gameOverTween = game.add.tween(this.balls[1 - this.rotatingBall]).to({
               alpha: 0
          }, 1000, Phaser.Easing.Cubic.Out, true);
          gameOverTween.onComplete.add(function(){
               game.state.start("PlayGame");
          },this)
     }
}

点击下载源代码。你的最好成绩是多少?

  • 原文名称:HTML5 prototype of iOS game “Circle Path” made with Phaser
  • 原文链接: 点击阅读原文
  • 原文作者:Emanuele feronato

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

One Reply to “用Phaser制作iOS游戏circle path”

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注