【１３日目】加速度センサを使ったゲーム [monaca]

## はじめに
今回は加速度センサを使用してゲームを作ります。開発環境にはmonacaを使用します。
簡単に概要を説明すると、スマホを傾けると移動するボールを動かしポイントを稼ぐゲームです。

)![加速度play.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2584729/a56e9d6c-9fe2-139a-acaf-69e8abc9c86a.png)



```
(後ほど動画を貼り付けます)
```


## 加速度センサ

まずはゲームのもとになるプログラムを作ります。`navigator.accelerometer.watchAcceleration();`を使ってスマホを傾ける度にxとyの変数が変わるようにし、そのx,yの値をellipseで指定します。するとスマホを傾ける操作でボールを操作できるようになります。

```
(後ほど動画を貼り付けます)
```


当たり判定はdist関数を使用して、一定間近づくと円が再生成されるようになっています。



```javascript
document.addEventListener("deviceready", () => {
    navigator.accelerometer.watchAcceleration(onSuccess, onError, { frequency: 30 });
}, false);

let accX = 0, accY = 0, accZ = 0;
let x, y;
let disU;

function setup() {
    createCanvas(windowWidth, windowHeight);
    x = width / 2;
    y = height / 2;

    xUp = random(0, width);
    yUp = random(0, height);

}
function draw() {
    // background(255, 255, 255);
    fill(255, 255, 255, 160);
    rect(0, 0, width, height);

    fill(255, 0, 0);
    textSize(40);

    x = constrain(x - accX * 5, 50, width - 50);
    y = constrain(y + accY * 5, 50, height - 50);

    ellipse(x, y, 80, 80);

    fill(255, 255, 0);
    ellipse(xUp, yUp, 120, 120);

    disU = dist(x, y, xUp, yUp);
    if (disU < 100) {
        text("up!!!!!!", xUp, yUp);
        xUp = random(0, width);
        yUp = random(0, height);
        console.log("up");

    }

}

function onSuccess(acceleration) {
    accX = acceleration.x;
    accY = acceleration.y;
    accZ = acceleration.z;
}

function onError() {
    console.log("Error!");
}

```





## 完成

上記のプログラムに加えて、クラスで円の数を増やし、スタート、リザルト画面、制限時間、ポイントを表示させるようにしました。
標的のボールはクラスで複製させていますが、スタートの段階でそのボールと自分のボールが重なっているとエラーが起きるため、多少強引ですが標的の的が生成される個所に制限を設けました。

backgroundを使わずrectとfillで背景を作り、透明度を設けることで残像が見えるような工夫もしました。





```javascript
document.addEventListener("deviceready", () => {
    navigator.accelerometer.watchAcceleration(onSuccess, onError, { frequency: 30 });
}, false);

let c = [];

let timeLimit = 11;
let time;

let timeBegin;

class Circle {
    constructor(x, y, s) {
        this.xDw = x;
        this.yDw = y;
        this.s = s;
        this.disD;
    }
    ptDown() {
        fill(0, 255, 0);
        ellipse(this.xDw, this.yDw, this.s, this.s);
    }

    del() {
        this.disD = dist(this.xDw, this.yDw, x, y);
        if (this.disD < 50 + xS / 2) {
            fill(0);
            text("down....", this.xDw, this.yDw);
            return 1;
        } else {
            return 0;
        }
    }
}

let accX = 0, accY = 0, accZ = 0;
let x, y;
let disU;

function setup() {
    createCanvas(windowWidth, windowHeight);
    x = width / 2;
    y = height - 50 ;

    scoreResult = 0;
    scene = "start";

    xUp = random(0, width);
    yUp = random(0, height);

    xS = 0;
    upS = 0;

}
function draw() {
    if (scene == "start")
        startScene();

    if (scene == "play") {
        // background(255, 255, 255);
        fill(255, 255, 255, 230);
        rect(0, 0, width, height);

        fill(255, 0, 0);
        textSize(40);

        if (time < 11) {
            ellipse(x, y, xS, xS);
            x = constrain(x - accX * 5, 50, width - 50);
            y = constrain(y + accY * 5, 50, height - 50);
        }

        fill(255, 255, 0);
        ellipse(xUp, yUp, upS, upS);
        disU = dist(x, y, xUp, yUp);

        if (disU < xS / 2 + upS / 2) {
            fill(0);
            text("up!!!!!!", xUp, yUp);
            xUp = random(0, width);
            yUp = random(0, height);
            scoreCal(10);
            console.log("up");
        }


        for (i = 0; i < 5; i++) {
            c.push(new Circle(random(0, width), random(0, height-160), 100)); //pushは関数
            c[i].ptDown();
            if (c[i].del() == 1) {
                c.splice(i, 1);
                scoreCal(-10);
            }
        }


        scoreText();

        time = timeLimit - (millis() - timeBegin) / 1000;
        text("制限時間→ " + int(time), 10, 80);

        if (time < 0)
            scene = "result";
    }

    if (scene == "result")
        endScene();

}

function startScene() {
    background(160, 255, 255);
    fill(0);
    textSize(48);
    text("イライラボール", 20, 300);
    textSize(30);
    text("選択してスタート", 30, 620);
    textSize(25);
    text("黄色に当たるとポイントup!", 10, 30);
    text("緑に当たるとポイントdown...", 10, 60);

    fill(160, 255, 160);
    ellipse(65, 400, 70, 70);

    fill(255, 0, 0);
    ellipse(65, 503, 70, 70);
    textSize(30);

    fill(0);

    text("Ｅ   ←イージーモード", 50, 410);
    text("Ｈ   ←ハードモード", 50, 515);

    if (mouseIsPressed) {
        if (dist(65, 400, mouseX, mouseY) <= 70) {
            xS = 80;
            upS = 120;
            timeBegin = millis();
            scene = "play";
        }
        if (dist(65, 503, mouseX, mouseY) <= 70) {
            xS = 120;
            upS = 50;
            timeBegin = millis();
            scene = "play";
        }
    }

}

function scoreCal(score) {
    scoreResult += score;
}

function scoreText() {
    fill(0);
    textSize(24);
    text("score→" + scoreResult, 10, 30);
}

function endScene() {
    background(0);

    //スタート、コンティニューボタン
    fill(0, 190, 0);
    ellipse(65, 590, 70, 70);

    fill(0, 0, 255);
    ellipse(65, 693, 70, 70);

    fill(255);
    text("結果", 50, 450);
    text("ｓ   ←スタート画面", 50, 600);
    text("ｃ   ←コンティニュー", 50, 700);
    textSize(30);
    text(scoreResult + "pt", 50, 500);
    if (mouseIsPressed) {
        if (dist(65, 693, mouseX, mouseY) <= 70) {
            scoreResult = 0;
            timeBegin = millis();
            scene = "play";
        }
        if (dist(65, 590, mouseX, mouseY) <= 70) {
            scoreResult = 0;
            scene = "start";
        }
    }
}

function onSuccess(acceleration) {
    accX = acceleration.x;
    accY = acceleration.y;
    accZ = acceleration.z;
}

function onError() {
    console.log("Error!");
}

```

結果的に見づらい記事になってすみません。至らない箇所もあると思いますのでコメントお待ちしています。
<br>

[スタート画面]
![加速度start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2584729/265ad3ce-4f12-b2ee-346d-ed5824d8d459.png)