3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

現役学生がphina.jsでゲーム作ってみた

Last updated at Posted at 2016-12-31

こんなんで簡単なブロック崩しゲームが作れます。
一度皆さんもやってみてはいかがでしょうか

index.html
 
<html>
  <head>
    <meta charset="utf-8" />
    
    <title>test  </title>
    
<style>
html {
  font-size: 62.5%;
}
body {
  color: #444;
  background-color: hsl(0, 0%, 96%);
}
h1 {
  font-size: 1.8rem;
}

</style>
  </head>
  <body>
    <script src="http://cdn.rawgit.com/phi-jp/phina.js/v0.2.0/build/phina.js"></script>
<script>
phina.globalize();//phina.game.GameAppのように階層的に定義されているクラスをGameAppだけで呼び出せるようにする処理などをしています。

var BLOCK_WIDTH = 40 * 2;
var BLOCK_HEIGHT = 60 / 2;
var PADDLE_WIDTH = BLOCK_WIDTH * 1.5;
var PADDLE_HEIGHT = BLOCK_HEIGHT;
var BALL_RADIUS = BLOCK_WIDTH / 8;
/*
 * メインシーン
 */
phina.define("MainScene", {//phina.defineは、クラスを定義する関数です。
  // 継承
  superClass: 'DisplayScene',//phina.defineは、クラスを定義する関数です。
  // コンストラクタ
  init: function() {//init関数は、いわゆるコンストラクタです。
    // 親クラス初期化
    this.superInit();//this.superInitで親クラスのコンストラクタを呼び出しています。この後に、実際のゲーム処理コードを書いていくことになります。
  
    this.backgroundColor = 'black';    // 背景色
    
    this.blockGroup = DisplayElement().addChildTo(this);// ブロックグループ
    
    this.dummyGroup = DisplayElement().addChildTo(this); // ダミーブロックグループ
  
    var screenRect = Rect(0, 0, 640, 960); // 位置判定用のRect

    var self = this;
    // Gridを利用してブロック設置
    Array.range(2, 16, 2).each(function(spanX) {
      Array.range(1, 4, 0.5).each(function(spanY) {
        Block().addChildTo(self.blockGroup)
               .setPosition(self.gridX.span(spanX), self.gridY.span(spanY));
      });
    });
    // パドル移動ライン
    var paddleY = this.gridY.span(14.5);
    // パドル設置
    var paddle = Paddle().addChildTo(this)
                         .setPosition(this.gridX.center(), paddleY);
    // 画面上でのタッチ移動時
    this.onpointmove = function(e) {
      // タッチ位置に移動
      paddle.setPosition(e.pointer.x | 0, paddleY);
      // 画面はみ出し防止
      if (paddle.left < screenRect.left) { paddle.left = screenRect.left; }
      if (paddle.right > screenRect.right) { paddle.right = screenRect.right; }
    };
    // 画面上でタッチが離れた時
    this.onpointend = function() {
      if (self.status === 'ready') {
        // ボール発射
        self.ball.vy = -self.ball.speed;
        self.status = 'move';
      }
    };
    // スコア
    this.score = 0;
    var scoreLabel = Label({
      text: this.score + '',
      fill: 'lime',
      fontSize: 64,
    }).addChildTo(this);
    scoreLabel.setPosition(this.gridX.center(), this.gridY.center());
    scoreLabel.alpha = 0.6;
    // 連続ヒット数
    this.hitNumber = 0;
    // ボール作成
    this.ball = Ball().addChildTo(this);
    // シーン全体から参照可能にする
    this.paddle = paddle;
    this.screenRect = screenRect;
    this.scoreLabel = scoreLabel;
    // ゲーム状態
    this.status = 'ready';
  },
    // 毎フレーム更新
  update: function() {
    var ball = this.ball;
    var paddle = this.paddle;
    var screenRect = this.screenRect;
    // ボール待機中
    if (this.status === 'ready') {
      // ボールはパドルの真上
      ball.vx = ball.vy = 0;
      ball.x = paddle.x;
      ball.bottom = paddle.top;
    }
    // ボール移動中
    if (this.status === 'move') {
      // ボール移動
      ball.moveBy(ball.vx, ball.vy);
      // 画面端反射
      // 上
      if (ball.top < screenRect.top) {
        ball.top = screenRect.top;
        ball.vy = -ball.vy;
      }
      // 左
      if (ball.left < screenRect.left) {
        ball.left = screenRect.left;
        ball.vx = -ball.vx;
      }
      // 右
      if (ball.right > screenRect.right) {
        ball.right = screenRect.right;
        ball.vx = -ball.vx;
      }
      // 落下
      var self = this;

      if (ball.top > screenRect.bottom) {
        // ゲームオーバー表示
        var label = Label({
          text: 'GAME OVER',
          fill: 'yellow',
          fontSize: 64,
        }).addChildTo(this);
        label.setPosition(this.gridX.center(), this.gridY.center());
        // 少し待ってからタイトル画面へ
        label.tweener.clear()
                     .wait(2000)
                     .call(function() {
                       self.nextLabel = 'title';
                       self.exit();
                     });
      }
      // パドルとの反射
      if (ball.hitTestElement(paddle) && ball.vy > 0) {
        ball.bottom = paddle.top;
        ball.vy = -ball.vy;
        // 当たった位置で角度を変化させる
        var dx = paddle.x - ball.x;
        ball.vx = -dx / 5;
      }
      // ブロックとの反射
      this.blockGroup.children.some(function(block) {
        // ヒットなら
        if (ball.hitTestElement(block)) {
          // 左上かど
          if (ball.top < block.top && ball.left < block.left) {
            // 位置補正
            ball.right = block.left;
            ball.bottom = block.top;
            // 移動方向設定
            ball.vx = -ball.speed;
            ball.vy = -ball.speed;
            // ブロック消去
            self.disableBlock(block);
            return true;
          }
          // 右上かど
          if (block.top < ball.top && block.right < ball.right) {
            ball.left = block.right;
            ball.bottom = block.top;
            ball.vx = ball.speed;
            ball.vy = -ball.speed;
            self.disableBlock(block);
            return true;
          }
          // 左下かど
          if (block.bottom < ball.bottom && ball.left < block.left) {
            ball.right = block.left;
            ball.top = block.bottom;
            ball.vx = -ball.speed;
            ball.vy = ball.speed;
            self.disableBlock(block);
            return true;
          }
          // 右下かど
          if (block.bottom < ball.bottom && block.right < ball.right) {
            ball.left = block.right;
            ball.top = block.bottom;
            ball.vx = ball.speed;
            ball.vy = ball.speed;
            self.disableBlock(block);
            return true;
          }
          // 左側
          if (ball.left < block.left) {
            ball.right = block.left;
            ball.vx = -ball.vx;
            self.disableBlock(block);
            return true;
          }
          // 右側
          if (block.right < ball.right) {
            ball.left = block.right;
            ball.vx = -ball.vx;
            self.disableBlock(block);
            return true;
          }
          // 上側
          if (ball.top < block.top) {
            ball.bottom = block.top;
            ball.vy = -ball.vy;
            self.disableBlock(block);
            return true;
          }
          // 下側
          if (block.bottom < ball.bottom) {
            ball.top = block.bottom;
            ball.vy = -ball.vy;
            self.disableBlock(block);
            return true;
          }
        }
      });
    }
    // クリアチェック
    if (this.blockGroup.children.length === 0) {
      // スコアをリザルトシーンに渡す
      this.exit({
        score: this.score,  
      });
    }
  },
  // ブロックの消去処理
  disableBlock: function(block) {
    // 消去アニメーション用のダミーブロック
    var dummy = Block().addChildTo(this.dummyGroup);
    // 属性コピー
    dummy.x = block.x;
    dummy.y = block.y;
    // ブロック削除
    block.remove();
    // 縮小して消えるアニメーション
    dummy.tweener.clear()
                 .to({scaleX: 0.1, scaleY: 0.1}, 200)
                 .call(function() {
                   dummy.remove();
                 });
    // スコア加算
    this.addScore();
  },
  // スコア加算処理
  addScore: function() {
    this.hitNumber++;
    this.score += this.hitNumber * 10;
    this.scoreLabel.text = this.score;
  },
});
/*
 * ブロッククラス
 */
phina.define('Block', {
  // 親クラス指定
  superClass: 'RectangleShape',
  // コンストラクタ
  init: function() {
    // 親クラス初期化
    this.superInit({
      width: BLOCK_WIDTH,
      height: BLOCK_HEIGHT,
    });
  },
});
/*
 * パドルクラス
 */
phina.define('Paddle', {
  // 親クラス指定
  superClass: 'RectangleShape',
  // コンストラクタ
  init: function() {
    // 親クラス初期化
    this.superInit({
      width: PADDLE_WIDTH,
      height: PADDLE_HEIGHT,
      fill: 'silver',
    });
  },
});
/*
 * ボールクラス
 */
phina.define('Ball', {
  // 親クラス指定
  superClass: 'CircleShape',
  // コンストラクタ
  init: function() {
    // 親クラス初期化
    this.superInit({
      radius: BALL_RADIUS,
      fill: 'silver',
    });
    // スピード
    this.speed = 6;
  },
});
/*
 * メイン処理
 */
phina.main(function() {
  // アプリケーションを生成
  var app = GameApp({
    title: 'GAMES',
  });
  // fps変更
  app.fps = 60;
  // 実行
  app.run();
});
</script>
  </body>
</html>
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?