スマートデバイスプログラミング 第6回
色々なセンサーを使ってみよう

GameCanvasについて

・GameCanvasの機能:今週使う変数、メソッド

 ・(float)gc.AccelerationLastX;
 ・(float)gc.AccelerationLastY;
 ・(float)gc.AccelerationLastZ;
   加速度センサーで測定されたXYZ軸の加速度

課題

(1)加速度センサーの値を取得して表示してみましょう。
(2)加速度センサーの値を使って、画面内をボールが転がるようにしてみよう。
(3)ボールで番号を順番に取っていくゲームを作ってみよう。
・ランダムの場所に、1から10の番号が書いた40x40の箱を配置
・順番にしか取れない、全部取るのに何秒かかるかを競う
(4)ゲームを改造してみよう。

作ったC#のプログラムを添付してください。
(プロジェクトを保存したフォルダのasset以下にあると思います。
コメント欄には、どこまでやったかと、
(3)までできた人はベストタイムを書いてください。

課題の進め方

前回、apkが作れなかった人、xcodeを用いてうまく実機で動かせなかったmax&iOSユーザーは、前回の課題の問題解決から始めましょう。
「課題の進め方」
※今回は第6回なので、フォルダはk06に改名してください。
サンプルの起動を確認し、スクリプトが編集できる状態になったら、
続きを読み進めてください。

課題1をやってみましょう

  1. プログラムを編集

    (クラスに入った直後)に下記の行を記載

    
    

    (InitGame()の中)に下記の行を記載

    
    gc.SetResolution(720,1280);
    gc.IsAccelerometerEnabled = true;
    

    (UpdateGame()の中)に下記の行を記載

    
    

    (DrawGame()の中に下記の行を記載)

    
    gc.ClearScreen();
    gc.SetColor(0, 0, 0);
    gc.SetFontSize(36);
    gc.DrawString("AcceX:"+gc.AccelerationLastX,0,0);
    gc.DrawString("AcceY:"+gc.AccelerationLastY,0,40);
    gc.DrawString("AcceZ:"+gc.AccelerationLastZ,0,80);
    
  2. セーブして実行してみましょう。
  3. 問題なく動きそうなら、unityRemoteで実行したり、apkを作ったり、 xcodeでビルドしてiOS端末で動かしたもしてみましょう。
  4. 端末を上下左右に動かすと、値が変わります。
  5. センサーのxyz軸にかかっている加速度が表示されます。
  6. zがマイナス1になっているのは、重力がかかっているからです。
  7. xの値は左右に傾けると変わります。
  8. yの値は上下に傾けると変わります。
  9. 端末を上下左右にすばやく動かすと、加速が発生するので、値が変化します。
  10. たまにノイズが入るので、何フレームか計測して平均値を取って使うようにすると、より動きが安定します。

課題2のヒント

xy座標をfloatで用意しましょう
早さの調整用にplayer_speedもfloatで用意ししましょう。
毎フレームのacceの値をボールに反映させましょう。

(変数の宣言(Class入ってすぐのところに足す))
float player_x = 360;
float player_y = 640;
float player_speed = 20.0f;

(動きの処理(UpdateGameに足す))
player_x += gc.AccelerationLastX * player_speed;
player_y += gc.AccelerationLastY * player_speed;

(描画の処理(DrawGameに足す))
gc.DrawImage(GcImage.BallYellow,(int)player_x,(int)player_y);

などを適宜追加します。
ちなみにボール画像は縦横24ドットです。
余力がある人はボールが画面外に出た時に画面内に戻す処理も足してみましょう。

課題3のヒント

<用意する変数>
  配列で10個分、的の為の変数を用意
    xy座標、的がある状態かない状態か。
  次に取るべき玉の番号
  タイム
  クリアした状態か、など。

(具体例)
const int BLOCK_NUM = 10;
int[] block_x = new int[BLOCK_NUM];
int[] block_y = new int [BLOCK_NUM];
bool[] block_alive_flag = new bool[BLOCK_NUM];
int time;
int next_block_num;
bool isComplete;

<準備>
 各変数の初期化をします。

(具体例)
player_x = 360.0f;
player_y = 640.0f;
player_speed = 20.0f;

time = 0;
next_block_num = 0;
isComplete = false;

for(int i =0 ; i < BLOCK_NUM ; i ++ )
{
   block_x[i] = gc.Random(0,720-40);
   block_y[i] = gc.Random(0,1280-40);
   block_alive_flag [i] = true;
}

<毎フレームやること>

 クリアした状態でなければ
   タイムを足す
  (具体例)
  if(isComplete == false) time++;

 玉を動かす(課題2をそのまま使う)

 forでブロックの数だけ繰り返し
  箱が存在していたら、かつ、次に取るべき箱だったら

   玉と箱が接触していたら(checkHitRectで玉と箱の当り判定)

       箱を消す
       次に取るべき箱の番号を増やす

       全部取ったら(次の番号==ボールの数だったら)
         クリアした状態にする

  (具体例)
for(int i=0;i< BLOCK_NUM;i++){
  if(block_alive_flag [i] && i== next_block_num){
    if(gc.CheckHitRect((int)player_x,(int)player_y,24,24,block_x[i],block_y[i],40,40)){
      block_alive_flag[i] = false;
      next_block_num++;
        if(next_block_num == BLOCK_NUM){
        isComplete=true;  
      }
    }
  }
}

<表示>

 timeを表示
 クリア状態だったら「クリア!」と表示
(具体例)
gc.DrawString("time:"+time,0,160);
if (isComplete) {
  gc.DrawString("CLEAR!!",0,200);
}

 玉を表示(課題2をそのまま使う)

 forで10回繰り返し
    箱が存在していたら、
      30x30の塗り潰し四角形を表示
      色を変えて、箱の番号を表示

    ※重なった時の対策として、大きい番号から描画命令を送った方がベターです。
     (次に取る物が分かる為)
    ※内部では0〜9で扱って、表示の時だけ+1しましょう。

(具体例)
for(int i=0;i< BLOCK_NUM;i++){
  if(block_alive_flag[i]){
    gc.SetColor(255, 0, 0);
    gc.FillRect(block_x [i], block_y [i],40,40);
    gc.SetColor(0, 0, 0);
    gc.DrawString ("" + (i + 1),block_x [i], block_y [i]);
  }
}

課題4のヒント

画面長押しで再度遊べるようにする、
アニメーションをつけてみる、ルールを変えてみる、
取ってはいけないものを作る、入れない場所(壁)を作ってみる、など、
より良くする案を考えてみましょう。

補足

描画メソッド

エディタについて

 標準でついてくるエディタMonoDevelopは日本語入力に不備が多々あります。
 入力せずに済ませるのが現実的ですが、どうしても日本語を入力したい場合は
 他のエディタで打ち込んでコピー&ペーストで持ってくるのが確実です。

 日本語対応するプログラムなども配布されているので、
 検索して試してみると良いかもしれません。
 容量は食いますがVisualStudioCommunityを導入するのもオススメです。

よくある質問

スクリプトを更新したのに、何も変わらない

プログラムが間違っていてビルドエラーが出ている可能性が高いです。

エディタ上でbuildしてみましょう。

{}の対応が間違っていないか、全角スペースが入っているかなど、確認してみましょう