距離センサを使って衝突回避ゲーム

このエントリーをはてなブックマークに追加

糸通しや,Flappy Birdのような迫りくる壁を回避するゲームです.
距離センサを使って入力しますので,より直感的な操作で遊べます

材料

作り方(ハードウェア)

obnizに距離センサをつなぐだけです.どこに挿してもいいですが,下記のようにつなぎました.

  • io0 : VCC(赤)
  • io1 : GND(黒)
  • io2 : 信号線(黄色)

作り方(ソフトウェア)

HTML5のcanvasをゴリゴリ使っていきます

<canvas id="field" width="300" height="300"/>
  let canvas = document.getElementById('field');
  let ctx = canvas.getContext('2d');

距離センサからの入力はinputHeight変数に自動で入るように設定しておき,使いたいタイミングで使うようにします.


  let inputHeight = 0;
  let obniz = new Obniz("OBNIZ_ID_HERE");
  obniz.onconnect = async function () {
    let sensor = obniz.wired("GP2Y0A21YK0F", {vcc:0, gnd:1, signal:2});
    sensor.start(function (height) {
      inputHeight = height;
    })

  };

コードの中の{vcc:0, gnd:1, signal:2}は距離センサを接続した場所によって変えます.「作り方(ハードウェア)」にて同じように接続していれば,そのままで大丈夫です.

ここでとった値は,毎フレーム内の処理の際に入力値として使っています

   let input = (300 - inputHeight);
   input = Math.min(Math.max(0, input), canvas.height);
   dot.push(input);

Program

<!-- HTML Example -->
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/obniz@1.9.1/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>

<canvas id="field" width="300" height="300"/>

<script>
  let canvas = document.getElementById('field');
  let ctx = canvas.getContext('2d');
  let dot = [];
  let bars = [];
  let inputHeight = 0;
  let frameCount = 0;
  let obniz = new Obniz("OBNIZ_ID_HERE");
  obniz.onconnect = async function () {
    let sensor = obniz.wired("GP2Y0A21YK0F",  {vcc:0, gnd:1, signal:2});
    sensor.start(function (height) {
      inputHeight = height;
    })


  };

  function initialize() {
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.fillStyle = "white";
    ctx.font = "25pt Arial";
    ctx.fillText("Click to START", 40, 150);


    canvas.addEventListener('click', startGame, false);
  }

  initialize();

  function startGame() {

    frameCount = 0;
    for (let i = 0; i < canvas.width / 4; i++) {
      dot[i] = undefined;
    }
    dot[dot.length] = canvas.height / 2;

    bars = [];

    frame();

  }

  function frame() {

    frameCount++;
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    let input = (400 - inputHeight);
    input = Math.min(Math.max(0, input), canvas.height);
    dot.push(input);
    dot.shift();

    for (let i = bars.length - 1; i >= 0; i--) {
      bars[i].x--;
      if (bars[i].x + bars[i].width < 0) {
        bars.splice(i, 1);
      }
    }
    if (frameCount === 100) {
      frameCount = 0;
      if (Math.random() > 0.3) {

        bars.push({x: canvas.width, y: Math.random() * 380 - 80, width: 16, height: 160});
      } else {
        let hole = Math.random() * 300;
        bars.push({x: canvas.width, y: 0, width: 16, height: hole - 40});
        bars.push({x: canvas.width, y: hole + 40, width: 16, height: canvas.height});
      }

    }


    drawDots();
    drawBars();
    if (isHit()) {
      gameOver();
    } else {
      setTimeout(frame, 10);
    }

  }

  function drawDots() {
    ctx.strokeStyle = "white";
    ctx.lineWidth = 1;
    ctx.beginPath();

    for (let i = 0; i < dot.length - 1; i++) {

      if (dot[i] !== undefined && dot[i + 1] !== undefined) {

        ctx.moveTo(i, dot[i]);
        ctx.lineTo(i + 1, dot[i + 1]);
      }
    }
    ctx.closePath();
    ctx.stroke();


  }

  function drawBars() {
    ctx.fillStyle = "red";
    ctx.beginPath();

    for (let i = 0; i < bars.length; i++) {

      ctx.fillRect(bars[i].x, bars[i].y, bars[i].width, bars[i].height);
    }

  }

  function isHit() {
    let x = dot.length;
    let y = dot[dot.length - 1];

    for (let i = 0; i < bars.length; i++) {
      if (bars[i].x <= x && x <= bars[i].x + bars[i].width
          && bars[i].y <= y && y <= bars[i].y + bars[i].height) {
        return true;
      }
    }
    return false;

  }

  function gameOver() {

    ctx.fillStyle = "white";
    ctx.font = "25pt Arial";
    ctx.fillText("GAME OVER", 50, 100);
    ctx.fillText("Click to START", 40, 200);

  }

</script>
</body>
</html>

今すぐ実行

HTMLがブラウザで開かれて実行されます。