obniz Blog
This blog is an archive of past articles. For the latest updates, visit iot.obniz.com.

Collision Avoidance Game with Distance Sensor

(Updated2020.04.22)Game and Fun

日本語で読む →

It is collision avoidance game like Flappy Bird. You use your hands in this game, so you can control the bar intuitively (using distance sensor).

Materials

  • obniz x1
  • power supply for obniz x1
  • GP2Y0A21YK0F(IR distance sensor) x1
  • PC or Smartphone x1

Steps

Hardware

Connect IR distance sensor to an obniz like the table and the image below.

obniz GP2Y0A21YK0F (IR distance sensor)
0 Vcc
1 GND
2 signal

software

Use HTML5 canvas.

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

Set value of distance sensor to variable “inputHeight“, and make it usable anytime.

  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} will be changed if you make different wiring from “Hardware“.

This values are used as input values each frames.

   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.com/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/[email protected]/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

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

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

<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});      
      let dataValues = [];
    sensor.start(function (height) {
      dataValues.push(height);
      if(dataValues.length > 5){
        dataValues.shift();
      }
      inputHeight = dataValues.reduce(function(x, y) { return x + y; })/dataValues.length;
    })


  };

  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", 90, 200);


    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 = (500 - 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 + 90, width: 16, height: canvas.height});
      }

    }


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

  }

  function drawDots() {
    ctx.strokeStyle = "white";
    ctx.lineWidth = 3;
    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", 100, 150);
    ctx.fillText("Click to START", 90, 250);

  }

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