スマートデバイスプログラミング 第7回
ネットワーク機能を使ってみよう

k07_web.zip(サーバに置くファイル群)

GameCanvasについて

・GameCanvasの機能:今週使う変数、メソッド
    gc.DrawOnlineImage(url,x,y);
   ・urlにアクセスして取得した画像をxyに表示します。
   ・内部では、urlをキーにしてた保存領域に画像情報をDLしていき、
    DLが終わり次第表示します(終わるまでは何も表示せず処理が終わります)

   gc.GetOnlineTextAsync(url,out str);
   ・urlにアクセスして、通信結果をテキストとして返します。

課題

(1)通信により、画像を取得して表示してみましょう。 (2)パラメータを送信してみましょう。 (3)簡単な避けゲームを作って、スコアを送信できるようにしてみましょう。 (4)その他、プログラムを改良したり、学んだ技術を駆使して、何か面白いことをやってみましょう。
作ったC#のプログラムを添付してください。
(プロジェクトを保存したフォルダのasset以下にあると思います。
コメント欄には、どこまでやったかと、(3)のハイスコアを書いてください。

課題の進め方

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

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

  1. プログラムを編集

    (クラスに入った直後)に変数の宣言を足す

    
    

    (InitGame()の中)に初期化処理を足す

    
        gc.SetResolution(640, 480);
    

    (UpdateGame()の中)に下記の行を足す

    
    

    Draw()の中(ClearScreenの後)に下記の行を記載

    
        gc.ClearScreen();
        gc.SetColor(0, 0, 0);
        gc.SetFontSize(36);
        gc.DrawOnlineImage("https://web.sfc.keio.ac.jp/~wadari/sdp/k07_web/Player.png",320,240);
    
  2. セーブして実行してみましょう。
  3. 暫く待つとPlayerが表示されます。
  4. (web上からダウンロードして表示しています)
  5. 問題なく動きそうなら、unityRemoteで実行したり、apkを作ったり、 xcodeでビルドしてiOS端末で動かしたもしてみましょう。
  6. 自分で好きな画像をupして、urlを変えてDLしたりもしてみましょう。

課題2のヒント

//変数宣言の所に追加
int score=0;
string pname = "t93520mw";
string url = "";
string str = "";

//initGameに追加
score = gc.Random(0,100);

//updateGameに追加
if(gc.GetPointerFrameCount(0) ==1 ){
   url = "https://web.sfc.keio.ac.jp/~wadari/sdp/k07_web/score.cgi?score="
     + score + "&name=" + pname;
     gc.GetOnlineTextAsync(url,out str);
}

//drawGameに追加
gc.DrawString(str,0,300);

などを適宜配置しましょう。

  • タップすると、通信結果が表示されます。
  • (ハイスコア、名前、スコア、名前、カウンター)です。
  • カウンターはcgiが起動された回数です。(ゲーム的には意味は無い値ですが、応用する際、参考にしてください)
  • k07_webを解凍して設置して、cgiファイルとdatファイルのパーミッションを755にすると、自分のHP上でも動くようになります。試してみましょう。
  • ※zip内のscore.cgiは今UPされているものとは若干異なります。UPしているものは改行等を減らしています
  • ブラウザでscore_web.cgiにアクセスすると、ブラウザからも確認できます。
  • score=-1で送信すると、ハイスコアが初期化されます(0になります)
  • 課題3のヒント

    第4回の課題を改造して、降ってくる箱を避けるゲームを作ってみましょう。
    
    何もしないと右に動いていく
    タップする度に移動方向が左右に切り替わる
    (常にどちらかに動く)
    
    箱は、ゲームが進むとだんだん大きくなっていく。
    箱に触れたらゲームオーバー。
    経過秒数がスコアになる。
    
    変数gameStateを使って、タイトル画面、ゲーム中、ゲームオーバー画面で、
    それぞれ処理内容や表示するものを切り替えてみましょう。
    
    //変数宣言の所に↓を追加
    int gameState = 0;
    
    //updateGameとdrawGameにgameStateによる切り替え処理を追加
    //それぞれに追加します
    
    if(gameState == 0){
      //タイトル画面の処理
    }
    else if(gameState == 1){
      //ゲーム中の処理
    }
    else if(gameState == 2){
      //ゲームオーバー時の処理
    }
    
    
    //更に追加で用意する変数、初期化
    //(課題2で使ったscore,url,strも引き続き使用します)
    
    const int BOX_NUM = 10;
    int[] box_x = new int [BOX_NUM];
    int[] box_y = new int [BOX_NUM];
    int[] box_speed = new int [BOX_NUM];
    int box_w = 24;
    int box_h = 24;
    
    int player_x = 304;
    int player_y = 400;
    int player_dir = 1;
    int player_speed = 5;
    
    int count =0;
    
    //初期化の処理
    //void resetValue()という初期化用メソッドを用意しても良いでしょう
    
    for(int i =0 ; i < BOX_NUM ; i ++ )
    {
      box_x[i] = gc.Random(0,616);
      box_y[i] = -gc.Random(100,480);
      box_speed[i] = gc.Random(3,6);
    }
    
    // 動き
    //gameStateが0の時:タップしたらgameStateを1にします。
    if(gc.GetPointerFrameCount(0) ==1 ){
      gameState = 1;
    }
    
    //gameStateが2の時:タップしたらスコアを送信(課題2を参考に)
    
    //gameStateが1の時:下記の処理を加えます
    
    count++;
    score = count/60;
    box_w = 24+count/300;
    box_h = 24+count/300;
    
    if(gc.GetPointerFrameCount(0) ==1 ){
      player_dir = -player_dir;
    }
    
    player_x += player_dir * player_speed;
    
    for(int i =0 ; i < BOX_NUM ; i ++ )
    {
      //箱を動かす処理
      box_y[i] = box_y[i] + box_speed[i];
    
      if(box_y[i]> 480){
        box_x[i] = gc.Random(0,616);
        box_y[i] = -gc.Random(100,480);
        box_speed[i] = gc.Random(3,6);
      }
    
      //playerと箱の当り判定
      if (gc.CheckHitRect (
        player_x,player_y,32,32,
        box_x[i],box_y[i],box_w,box_h)) {
        //当たった時の処理
        gameStateを2にする
      }
    }
    
      //playerが画面左右に着いてもgameOverになるように
      if(player_x < 0 || player_x > 608){
        gameStateを2にする
      }
    
    // 描画
    
    //gameStateが0の時は"Title"と表示
    //(具体例)
    gc.DrawString("TITLE",320,240);
    
    //gameStateが2の時は"Game Over"と表示、スコアと通信結果も表示
    //(具体例)(通信結果は課題2の物をそのまま使用)
    gc.DrawString("GAME OVER",320,240);
    gc.DrawString("SCORE:"+score,0,0);
    
    //gameStateが1の時はゲーム画面を表示
    
    playerの描画(課題1を参考に、playerx,playeryを用いて座標指定)
    
    //箱の描画
    for(int i =0 ; i < BOX_NUM ; i ++ ){
      gc.FillRect(box_x[i],box_y[i],box_w,box_h);  
    }
    
    などを適宜加えて行きましょう。
    
    

    課題4のヒント

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

    補足

    通信メソッド

     gameCanvasではwebsocketを使用した通信もできるようになっています。
     ネットワークの知識がある方は、こちらも試してみると良いかもしれません。


    よくある質問

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

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

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

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