クリックすると、猿がりんご、バナナ、さくらんぼのどれかをランダムに落とします。
落とした分だけ得点にカウントされますが、地面に落ちた分はマイナスされるので、かごに積んだ分が得点になります。
時間は50秒で、スコアと、りんご、バナナ、さくらんぼの数の分の絵が表示されます。
作り込みの授業のときに困ったところをいくつか先生に助言をいただいたおかげでそのときにすごく進めることができたみたいで喜んでいました。やっぱり一人で作るより助けを借りて作ったほうがいいですね。
最後に、結果画面のところに、「積んだ果物をそれぞれの個数分で画像で並べて出したい」と言い出して、(ノ∀`)アチャーまた難しそうなことを(ヤメテー)・・と思いましたが、偶然にも私の助言のおかげで(エッヘン)実現することができました。
その結果画面について、難しかったので覚えで書いておきます。息子に説明してもらいました。
何が難しいかというと、
①りんご、バナナ、さくらんぼの数はそれぞれその都度異なる。
②それぞれその都度異なる数のものを、等間隔に並べて表示する。(x座標の問題)
③端まできたら、次の行に移して並べていく。(x,y座標の問題)
どういうアルゴリズムでやればいいのでしょうか?
①りんご、バナナ、さくらんぼの数を配列にしてセーブします
var howmanyF = [0,0,0];//フルーツの数を入れておく配列をつくる(howmanyF[0]がりんごの数、 howmanyF[1]がバナナの数、howmany[2]がさくらんぼの数) function dropBlock(){ var fruits1 = new PhyBoxSprite(32,32, enchant.box2d.DYNAMIC_SPRITE,1,0.5,0); var rdm = getRandom(0,2); //ifと同じだが2つ以上だとこっちが楽 switch(rdm){ case 0: fruits1.image= core.assets["images/cf307/monkeyapple.png"]; howmanyF[0] +=1;//りんごを落としたらりんごの数が+1される break; case 1: fruits1.image= core.assets["images/cf307/banana.png"]; howmanyF[1] +=1;//バナナを落としたらバナナの数が+1される break; case 2: fruits1.image = core.assets["images/cf307/sakuranbo.png"]; howmanyF[2] +=1;//さくらんぼを落としたらさくらんぼの数が+1される break; } (略) // (2)当たり判定(ground x group)//フルーツが地面に当たったら ground.addCollision(group); ground.on(Event.COLLISION, function(e){ //console.log(e); var target = e.collision.target; target.remove(); switch(target.image){ case core.assets["images/cf307/monkeyapple.png"]: console.log("aplle"); howmanyF[0] -=1;//りんごだったらりんごの数を-1する break; case core.assets["images/cf307/banana.png"]: console.log("banana"); howmanyF[1] -=1;//(以下同様) break; case core.assets["images/cf307/sakuranbo.png"]: console.log("さくらんぼ"); howmanyF[2] -=1;//(以下同様) break; } if(score != 0){ score--; } }); rope.tl.delay(16); rope.tl.then(function(){ timer--; console.log("あと"+ timer + "秒"); timelabel.text = "TIME: " + timer; if(timer <= 10){ timelabel.color = "red"; } if(timer == 0){//0秒になったら BGM.stop();//音を止める console.log("おしまい"); console.log(howmanyF); localStorage.setItem("howmanyF", howmanyF);//howmanyFをセーブする localStorage.setItem("monkey_score", score); endStart(); } }); rope.tl.loop();
②りんご、バナナ、さくらんぼをセーブした個数分画像で並べる
例えば、りんごを15個並べたいとき、10個目までは32ピクセルずつずらしてならべ、11個目からはまたx座標は0に戻さないといけないのです。
x座標で言うと、0のときは0、1のときは32×1、2のときは32×2、・・・9のときは32×9、そして10のときはまた0に戻る、これはどう書けばいいのか・・
息子は悩みはじめました。こんな数学の問題は学校ではでてきません。どんな数式でしょうか。
要は0〜9まではそれぞれ対応して0〜9で、10〜19までまた戻って0〜9、20から29までまた戻って0〜9(この繰り返し)になればいいのです。だから、「10で割ってその余りの数の・・」というところまで息子は考えたのですがわかりませんでした。
そこで私が思い出したのは、ブロック崩しもどきのゲームを作ったときに、先生のサンプルから真似して見よう見まねで書いたものの中に、ブロックをきっちりすきまなく順番に並べて置いていくというものを作ったことをうっすら思い出しました。意味もわからず見よう見まねで書いたものがあったよね、それがもしかしたら参考になるのでは?と息子に言って見せると
block.x = 0 + ((i % 40) * 8);//(iを40で割った数の余り)×8 block.y = 0 + (Math.floor(i / 40) * 8);//(iを40で割った商の小数点を切り捨てた数)×8
↑これだ!これがやりたかったの!これのことだったんだ!と感激していました。
これって・・言われればそのとおりだけど、思いついた人はすごいと思う。
%というのは、「割った余りの数値」です。Math.floorとは「小数点を切り捨て」です。
上の例だと、8ピクセルのブロックを40個ずつ並べたいので、iを40で割った余りの8倍をx座標にすれば40までは i (×8)ずつ増えて40で0に戻り、iを40で割った商の小数点を切り捨てた数の8倍をy座標にすれば、iが40増えるごとに 1(×8)ずつ増えるので40個ずつで行が下に行くことになります。
ということで、母のかすかな記憶のおかげで偶然にも解決できました。見よう見まねで作ってみたものがこんなところで役に立つとは。おかげで私も、初めてこれの意味を理解することができました。
さらに、ブロックは一種類でしたが今回はりんご、バナナ、さくらんぼを三種類を画像を変えて並べないといけないので、iの数を前の果物の数だけ加えてずらすという工夫が必要でした。
以下コメント部分はゆうじの解説です。
function endStart(){// 結果画面 scene = new Scene(); core.replaceScene(scene); core.resume(); //========== // ここから //========== var sound = core.assets["sounds/cf307/trumpet1.mp3"].clone(); sound.play(); Fruits = Class.create(Sprite, { // フルーツというクラスを、Spriteを継承させてつくる initialize: function(image){ // クラスのものをつくるときに行う imageが引数 Sprite.call(this,32,32); // 継承したものを呼び出す(これ、32,32) this.image = core.assets[image]; //そのクラスのプロパティを設定 } }); var howmany = localStorage.getItem("howmanyF"); // howmanyFで名付けた配列を取り出して howmanyと名付ける var howmanyA = howmany.split(","); // howmanyを区切って取りしたものをhowmanyAとする var howmanyN =[];// 空っぽの配列を作る for (var n in howmanyA) { // howmanyAの中身を順番に数字にする(長さ分だけ繰り返す例えば、 2,3,5とかなら3) var N = Number(howmanyA[n]); // howmanyAのn番目を文字列から数値にする(文字列として保存 されているから) howmanyN.push(N); // 数値にしたものを作っておいた空っぽの配列howmanyNに入れる console.log(howmanyN); // howmanyNというのは(りんごの数、バナナの数、さくらんぼの数) という配列なので、howmanyN[0]はりんごの数、 howmany[1]はバナナの数、howmany[2]はさくらんぼの数になる } //林檎をさっき皿の上にのったかずだけ出す for(var Fx = 0; Fx < howmanyN[0]; Fx++){ // りんごの数分だけ繰り返す(howmanyN[0]という のが今りんごの個数になっているのでその分繰り返す) var apple = new Fruits("images/cf307/monkeyapple.png"); apple.x = 0 + ((Fx % 10) * 32); // 10個まで32ずつずらして並べ、かつ10個ずつで折り返し たいので、「りんごの個数を10で割った余り×32」をx座標と する console.log(apple.x); apple.y = (Math.floor(Fx / 10) * 32); // 10個ならべたら次の行にするには「りんごの数を 10で割った数の小数点を切り捨てた数×32」をりんご のy座標とする scene.addChild(apple); } //バナナをその続きからだす for(var Fx2 = 0; Fx2 < howmanyN[1]; Fx2++){ var banana = new Fruits("images/cf307/banana.png"); banana.x = 0 + (((Fx2 + Fx) % 10) * 32);// バナナもりんごと同様だが、りんごの後に並べるので りんごの分をずらさないといけないので個数はりんごの 分も加えた(Fx2 + Fx)とする console.log(Fx); banana.y = (Math.floor((Fx2 + Fx) / 10) * 32); scene.addChild(banana); } //さくらんぼをバナナの続きからだす for(var Fx3 = 0; Fx3 < howmanyN[2]; Fx3++){ var cherry = new Fruits("images/cf307/sakuranbo.png"); cherry.x = 0 + (((Fx3 + Fx2 + Fx) % 10) * 32);// りんごとバナナの分ずらさないといけないの でその分の個数を加えた(Fx3 + Fx2 + Fx)と する console.log(Fx3); cherry.y = (Math.floor((Fx3 + Fx2 + Fx) / 10) * 32); scene.addChild(cherry); } scene.backgroundColor = "green"; var score = localStorage.getItem("monkey_score"); var scorelabel = new Label("結果: " + score); scorelabel.x = 320 / 2 -100; scorelabel.y = 340; scorelabel.color = 'yellow'; scorelabel.font = "48px 'PixelMplus10'"; scene.addChild(scorelabel); //console.log(scorelabel); //========== // ここまで //========== }
【感想】
今回の発表は、発表用の原稿の紙がなかったこともあって、アドリブの効かない息子は、デモプレイを一回やったっきり、だんまりで間が持たず、(デモプレイを繰り返ししていればよかったのにそれもなぜかせず ^♢^; )、苦労したんだからそのあたりもうちょっと説明したらいいのになと可笑しかったのですが、それも一つの個性なので、まあいいかと思います。(みんな違ってみんないい)
奇をてらわずシンプルで、息子の真面目さが出たようなゲームだと思いました。ゲームとして突き抜けたようなアイデアはないけれど、こういうふうに動かしたい、こういうものを出したいという構想を思い描いたとおりに実現させました(プログラミングの醍醐味だね)。そういうところを見ると、もしかすると息子はゲームよりも、実用的なアプリとかシステムをつくるプログラミングのほうが向いているかも知れないなと思いました。
ゲーム投稿サイト9leapに投稿してみました。こちらは得点の登録ができるプラグインがあるので、得点ランキングがでるところがいいです!