グラフィカルなルーレットを作る

グラフィカルなルーレットです。

今回やること

ボタンを押してブラウザ内のルーレットを回転させます。 もう一度押すとゆっくり止まって音がなります。

用意するもの

組み立て方

以下の表や図のように配線します。ボタンは左右どちらの向きで繋いでも問題ありません。

obniz 部品
0 スピーカー signal
1 スピーカー GND
6 ボタン signal
7 ボタン GND

プログラム

ボタンとスピーカーを繋いだピンの番号に応じて、プログラム内にてwiredの番号を変えます。

button = obniz.wired("Button", {signal:6 , gnd:7 });
speaker = obniz.wired("Speaker", {signal:0 , gnd: 1});

画像を回転させる

ルーレット画像を回転させます。

HTMLで画像を回転させる場合、cssのtransformを使います。 たとえば、90度回転させる場合、下記のように書きます。

document.getElementById("roulette").style = "transform:rotate(90deg);";

ゆっくり回転を開始したり止めたりしたいので、speedという変数を作って1フレームあたりの回転角度を決めています。

let speed = 0;
  let deg = 0;
  function rotate(){
    deg += speed;
      document.getElementById("roulette").style = "transform:rotate("+deg+"deg);";

  }
  setInterval(rotate,10);

音を鳴らす

やはりルーレットの番号が変わったときに音を鳴らしたいですよね。 以下ように書くと、440Hz(ドの音)で10ms間音を鳴らすことができます。

      speaker.play(440);
      await obniz.wait(10);
      speaker.stop();

ルーレットの番号が変わった時を知るには、先程のrotate関数内にてdegの値を確認する必要があります。

if( Math.floor((deg + speed) / (360/7.0)) -  Math.floor(deg / (360/7.0)) >= 1){
      onRouletteChange();
}

これらを合わせると以下のようになります。

  let speed = 0;
  let deg = 0;
  function rotate(){
    //on change value
    if( Math.floor((deg + speed) / (360/7.0)) -  Math.floor(deg / (360/7.0)) >= 1){
      onRouletteChange();
    }
    deg += speed;
      document.getElementById("roulette").style = "transform:rotate("+deg+"deg);";

  }
  setInterval(rotate,10);

  async function onRouletteChange(){
    if(!speaker){return;}
      speaker.play(440);
      await obniz.wait(10);
      speaker.stop(); 
  }

ボタンを押したらスタートする

ボタンを押されたことを検知するために、buttonStateという変数を作り、そこに現在のボタンの値を入れておきます。

button.onchange = function(pressed){
    buttonState = pressed;
  };

また、このプログラムでは、今どの状態かの把握のためにphase変数を作っています。 このphaseが次のどれかになることで現在の状態を把握しています。

const PHASE_WAIT_FOR_START = 0; 
const PHASE_ROTATE = 1;
const PHASE_STOPPING = 2;
const PHASE_STOPPED = 3;

たとえば、phasePHASE_WAIT_FOR_STARTのときにボタンが押されたら、次のPHASE_ROTATEフェーズに行くようにします。

if(phase == PHASE_WAIT_FOR_START){
    speed = 0;
    if(buttonState){
       phase = PHASE_ROTATE;
    }
}

ボタンが押されたら速度を上げるようにするにはこう書きます。

if(phase == PHASE_ROTATE){
    speed = speed+0.5;
}

逆に速度を落とすときはこうなります。ゆっくり止まって欲しいので、速度を上げるときより変化値を小さくしています。

if(phase == PHASE_STOPPING){    
    speed = speed-0.2;
}

これらを組み合わせて実行してみましょう。

obnizに電源を繋いでブラウザやobnizのコンソールでプログラムを実行すると、画面にルーレットが表示されます。ボタンを押すとルーレットが回り始め、もう一度ボタンを押すとゆっくりルーレットが止まります。

完成したプログラム