トップ


最高得点を表示する

$frameCount

オープニングは完成しました。最高得点も表示させたいものです。

最高得点を表示する前に、敵を倒したときの得点を教えてあげると遊ぶ人にとって親切です。敵の得点を表示した後に、最高得点を表示させましょう。また、操作方法を記すとさらにユーザーフレンドリーです。最後には操作方法も表示してあげましょう。

では、どのようにタイトル→敵紹介→最高得点→操作方法と順に移動していきましょうか。新しいプロジェクトを作っても時間の概念は解決できません。
以前に、フレームカウントを使って時間を拘束したと思います。また、timeのようなフレームカウントを作成しても良いのですが、今回はグローバル変数の$frameCountというTonyuに最初から入っている変数を使用してみようと思います。

$frameCountはゲームが始まった直後からカウントを増やしてゆきます。また、割り算の余り($frameCount%number)を使用して、自分の好みにあった時間で次々と画面が変わるようにしてみましょう。また、新しいプロジェクトを作成しないで全てをこのMainクラスで行わせて見ましょう。

Main.tonyu
extends SecretChar;

$bgcolor=$clBlack;
i=0;
j=0;
k=0;
l=0;
waitTime=600;
enemyId=new Array(); //EnemyのIDの配列 enemyId.add(2); //skyBlue enemyId.add(8); //Yellow enemyId.add(11); //Red enemyId.add(19); //Green enemyId.add(22); //Blue enemyId.add(3); //UFO enemyId.add(26); //middleBoss enemyId.add(29); //Boss enemyName=new Array(); //Enemyの名前の配列 enemyName.add("Sky Blue"); //skyBlue enemyName.add("Yellow"); //Yellow enemyName.add("Red"); //Red enemyName.add("Green"); //Green enemyName.add("Blue"); //Blue enemyName.add("UFO"); //UFO enemyName.add("Middle Boss"); //middleBoss enemyName.add("Boss"); //Boss enemyMark=new Array(); //Enemyの点数の配列 enemyMark.add(10); //skyBlue enemyMark.add(10); //Yellow enemyMark.add(30); //Red enemyMark.add(100); //Green enemyMark.add(100); //Blue enemyMark.add(" ?"); //UFO enemyMark.add(200); //middleBoss enemyMark.add(1000); //Boss if($highScore==null) $highScore=0;
while(1){ //オープニング while($frameCount%waitTime!=0){ //アニメーション後にタイトル drawSprite(i+j/10,100+j*0.5+k,$pat_Sample+3); drawSprite($screenWidth-i-j/10,100+j*0.5+k,$pat_Sample+22); drawSprite(i+j/5-40,140+j*0.25+k,$pat_Sample+19); drawSprite($screenWidth-i-j/5+40,140+j*0.25+k,$pat_Sample+11); drawSprite(i+j/2-80,180+k,$pat_Sample+8); drawSprite($screenWidth-i-j/2+80,180+k,$pat_Sample+2); drawSprite($screenWidth/2,0-40+j*1.5+k,$pat_Sample+29); if(i<200) i++; else if(j<60) j++; else if(k<110) k++; else { drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22); drawText(210,330,"Press Space Key",$clWhite,16); } if (getkey(32)>0) $projectManager.loadPage($page_index); update(); } while($frameCount%waitTime!=0){ //敵紹介 drawText(50,0,"Shooting Game Sample - Extended -",$clWhite,22); drawText(400,35,"Point",$clWhite,18); if(l<6){ drawSprite(160,40+30*(l+1),$pat_Sample+enemyId.get(l)); drawText(250,30+30*(l+1),enemyName.get(l),$clWhite,18); drawText(400,30+30*(l+1),enemyMark.get(l),$clWhite,18); } else { drawSprite(160,10+70*(l-2.3),$pat_Sample+enemyId.get(l)); drawText(250,70*(l-2.3),enemyName.get(l),$clWhite,18); drawText(400,70*(l-2.3),enemyMark.get(l),$clWhite,18); } if(l<7) l++; else { l=0; if (getkey(32)>0) $projectManager.loadPage($page_index); update(); } } while($frameCount%waitTime!=0){ //最高得点表示 drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22); drawText(100,150,"HIGH SCORE = "+$highScore,$clWhite,25); drawText(210,330,"Press Space Key",$clWhite,16); if (getkey(32)>0) $projectManager.loadPage($page_index); update(); } while($frameCount%waitTime!=0){ //操作方法表示 drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22); drawText(200,100,"How to Play",$clAqua,25); drawText(120,150,"Right Arrow",$clWhite,20); drawText(120,200,"Left Arrow",$clWhite,20); drawText(120,250,"Space Bar",$clWhite,20); drawText(300,150,"Right Move",$clWhite,20); drawText(300,200,"Left Move",$clWhite,20); drawText(300,250,"Shoot Missiles",$clWhite,20); drawText(210,330,"Press Space Key",$clWhite,16); if (getkey(32)>0) $projectManager.loadPage($page_index); update(); } updateEx(5); }

全部で100行もあります。プログラムは長いのですが、内容もその分濃くなっています。
$frameCountが600、1200、1800、2400の時に画面が変わって行き、次は、3000、3600、4200、4800・・・のように次々と変わってゆきます。1200も600の公倍数ですが、$frameCountの600が終わった後でupdate()によって$frameCountは1増えるので次は1200となります。ローカル変数waitTimeを用意しましたが、600から700などに増やしたり減らしたりすることもできるので利便性は高いと思います。

使用しているプログラミングの技術は全てこのチュートリアルで学んだ内容ばかりです。
敵紹介の部分では配列を3つ使用して、見やすくて、作業効率も良くしています。全ての敵のパラメタを書いてしまったのでは後で変更するときが大変です。配列と変数lを使用すれば、全体を右に移動させたりするときに非常に便利です。全部を書き並べた場合には24行で済むのですが、配列を使用した場合には36行必要でした。12行多くなったのですが、利便性は格段に上がりました。プログラム自体が見やすくなったことは言うまでもありません。
ハイスコア表示の部分では$highScoreに何も入っていない場合も考えられますので、null値を受け取った場合には$highScoreを0とするようにしました。また、全てのページでスペースキーを押すとゲームがすぐに始められるようにしてあります。

ゲームオーバーになったときにはハイスコアかどうかを調べておきましょう。また、nキーでstart.cmmlに戻って来られるようにもしておきましょう。

Text.tonyu
extends TextChar;

$bgcolor=11816980;
$mplayer.play($se_shootingsample1,0,80);
i=255;
while(1) {
  text="Score:"+$score;
  if($myChar.isDead()) {
    if($score>$highScore) $highScore=$score;
    if(i>0) i--;
    if(i==250) for(t in $chars) if(t is Enemy) t.die();
    if(i==200) appear(new Blue($screenWidth/2,$UFO.y,$pat_Sample+22));
    if(i==1) $UFO.die();
    $bgcolor=color(  0,  0,  i);
    drawText($screenWidth/2-130,$screenHeight/2-30,"Game Over",color(255-i,255-i,255-i),50);
    drawText(210,330,"Press N Key",$clWhite,16);
    if (getkey(78)>0) $projectManager.loadPage($page_start);
    update();
  }
  else update();
}

これで、ハイスコアも表示されるようになりました。

ファイルの保存

このままでは、Tonyuを一度終了させてから再びゲームを始めると$highScoreは0に戻されてしまいます。$highScoreをファイルに保存して置きましょう。

Text.tonyu
extends TextChar;

$bgcolor=11816980;
$mplayer.play($se_shootingsample1,0,80);
i=255;
while(1) {
  text="Score:"+$score;
  if($myChar.isDead()) {
    if($score>$highScore) {
      $highScore=$score;
      fileOut=new FileWriter("highScore.txt");
      fileOut.writeLn($highScore);
      fileOut.close();
    }
    if(i>0) i--;
    if(i==250) for(t in $chars) if(t is Enemy) t.die();
    if(i==200) appear(new Blue($screenWidth/2,$UFO.y,$pat_Sample+22));
    if(i==1) $UFO.die();
    $bgcolor=color(  0,  0,  i);
    drawText($screenWidth/2-130,$screenHeight/2-30,"Game Over",color(255-i,255-i,255-i),50);
    drawText(210,330,"Press N Key",$clWhite,16);
    if (getkey(78)>0) $projectManager.loadPage($page_start);
    update();
  }
  else update();
}

これでハイスコアは保存できましたが、まだ読み込むことはしていませんMainクラスに戻ってFileから読み込ませましょう。

Main.tonyu
extends SecretChar;

$bgcolor=$clBlack;
i=0;
j=0;
k=0;
l=0;
waitTime=600;
enemyId=new Array();  //EnemyのIDの配列
enemyId.add(2);       //skyBlue
enemyId.add(8);       //Yellow
enemyId.add(11);      //Red
enemyId.add(19);      //Green
enemyId.add(22);      //Blue
enemyId.add(3);       //UFO
enemyId.add(26);      //middleBoss
enemyId.add(29);      //Boss
enemyName=new Array();        //Enemyの名前の配列
enemyName.add("Sky Blue");    //skyBlue
enemyName.add("Yellow");      //Yellow
enemyName.add("Red");         //Red
enemyName.add("Green");       //Green
enemyName.add("Blue");        //Blue
enemyName.add("UFO");         //UFO
enemyName.add("Middle Boss"); //middleBoss
enemyName.add("Boss");        //Boss
enemyMark=new Array();  //Enemyの点数の配列
enemyMark.add(10);      //skyBlue
enemyMark.add(10);      //Yellow
enemyMark.add(30);      //Red
enemyMark.add(100);     //Green
enemyMark.add(100);     //Blue
enemyMark.add(" ?");    //UFO
enemyMark.add(200);     //middleBoss
enemyMark.add(1000);    //Boss
if(fileExists("highScore.txt")){
  fileIn=new FileReader("highScore.txt");
  $highScore=fileIn.readLn();
  fileIn.close();
}
if($highScore==null) $highScore=0;
while(1){                                //オープニング
  while($frameCount%waitTime!=0){             //アニメーション後にタイトル
    drawSprite(i+j/10,100+j*0.5+k,$pat_Sample+3);
    drawSprite($screenWidth-i-j/10,100+j*0.5+k,$pat_Sample+22);
    drawSprite(i+j/5-40,140+j*0.25+k,$pat_Sample+19);
    drawSprite($screenWidth-i-j/5+40,140+j*0.25+k,$pat_Sample+11);
    drawSprite(i+j/2-80,180+k,$pat_Sample+8);
    drawSprite($screenWidth-i-j/2+80,180+k,$pat_Sample+2);
    drawSprite($screenWidth/2,0-40+j*1.5+k,$pat_Sample+29);
    if(i<200) i++;
    else if(j<60) j++;
    else if(k<110) k++;
    else {
      drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22);
      drawText(210,330,"Press Space Key",$clWhite,16);
    }
    if (getkey(32)>0) $projectManager.loadPage($page_index);
    update();
  }
  update();
  while($frameCount%waitTime!=0){            //敵紹介
    drawText(50,0,"Shooting Game Sample - Extended -",$clWhite,22);
    drawText(400,35,"Point",$clWhite,18);
    if(l<6){
      drawSprite(160,40+30*(l+1),$pat_Sample+enemyId.get(l));
      drawText(250,30+30*(l+1),enemyName.get(l),$clWhite,18);
      drawText(400,30+30*(l+1),enemyMark.get(l),$clWhite,18);
    } else {
      drawSprite(160,10+70*(l-2.3),$pat_Sample+enemyId.get(l));
      drawText(250,70*(l-2.3),enemyName.get(l),$clWhite,18);
      drawText(400,70*(l-2.3),enemyMark.get(l),$clWhite,18);
    }      
    drawSprite(160,10+70*(6-2.3),$pat_Sample+enemyId.get(0));  //middleBossの中のskyBlue
    if(l<7) l++;
    else {
      l=0;
      if (getkey(32)>0) $projectManager.loadPage($page_index);
      update();
    }
  }
  update();
  while($frameCount%waitTime!=0){            //最高得点表示
    drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22);
    drawText(100,150,"HIGH SCORE = "+$highScore,$clWhite,25);
    drawText(210,330,"Press Space Key",$clWhite,16);
    if (getkey(32)>0) $projectManager.loadPage($page_index);
    update();
  }
  update();
  while($frameCount%waitTime!=0){            //操作方法表示
    drawText(50,50,"Shooting Game Sample - Extended -",$clWhite,22);
    drawText(200,100,"How to Play",$clAqua,25);
    drawText(120,150,"Right Arrow",$clWhite,20);
    drawText(120,200,"Left Arrow",$clWhite,20);
    drawText(120,250,"Space Bar",$clWhite,20);
    drawText(300,150,"Right Move",$clWhite,20);
    drawText(300,200,"Left Move",$clWhite,20);
    drawText(300,250,"Shoot Missiles",$clWhite,20);
    drawText(210,330,"Press Space Key",$clWhite,16);
    if (getkey(32)>0) $projectManager.loadPage($page_index);
    update();
  }
  update();
}

まず、fileExists関数でFileが存在するかしないかを調べています。Fileが存在した場合には、その中から数値を取って$highScoreに代入します。ユーザーがFileを消してしまう、もしくはFileの中身を空にしてしまう事も考えられますので、$highScoreはnull値を取るかもしれません。null値の時にはやはり0を代入します。

実際には、fileExists()関数は使用しなくても$highScoreにはnullが入り正常に動作します。

次はいよいよ最後です。エンディングを作ってみましょう。

  トップ