# チュートリアル[ボール投げゲームを作ってみましょう] ## 目次 > #### Step0 ゲームを作る準備をしよう > #### Step1 クマが左右に動くようにしよう > #### Step2 クマを10体階段状に出そう > #### Step3 画面にタッチしたときボールが縦方向に飛んでいくようにしよう > #### Step4 画面にタッチしたときボールが斜め方向に飛んでいくようにしよう > #### Step5 ボールに当たり判定をつけよう > #### Step6 ボールが落ちたときにゲームを終了するようにしよう > #### Step7 クマの種類をランダムにしてみよう > #### Step8 クマのスコアを変えてみよう > #### Step9 画面を引っ張ってボールの速度を決定しよう > #### Step10 クマを20体に増やして位置をランダムにしてみよう > #### Step11 クマの動きを複雑にしてみよう 今回はこのようなゲームを作成します。 クマにボールを当てるゲームです。 ![](https://i.imgur.com/N5QCwf6.gif) ごちゃごちゃに動いているクマに目が行くと思いますが、注目してほしいのは野球ボールの動きです。放物線をきれいに描いています。前回の授業では曲線の方程式を使ってなめらかな動きを付けましたが、今回は物理の式を使ってつけてみましょう。またパソコンでやるゲームのようにマウスのドラッグでボールを好きな方向に飛ばしてみましょう。 ## Step0 ゲームを作る準備をしよう それではまずは準備されたコードを確認してみてください。以下のようなコードになっていると思います。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを1体作成する bear[0] = new Bear(320,160); // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` 試しに今の時の画面を見てみましょう。今回のゲームは画面の横幅をいつもより大きくしています。 ![](https://i.imgur.com/EWB8GPK.png) いまのままではクマが動いたりボールを投げることができません。それではここから、少しずつ完成を目指して進めていきましょう。 ## Step1 クマが左右に動くようにしよう まずはクマに動きを付けていきましょう。クマが同じ速度で右に移動するようにして、画面端に行ったら、今度は速度は変わらずに左に移動、左の画面端に行ったら右に移動するようにします。 ![](https://i.imgur.com/gpzDRv9.gif) クラスBearに3点コードを追加しましょう。 まずは29行目に以下のコードを追加しましょう。 ```javascript= //クマの動きの速度 this.vx = 5; ``` これはクマの動く速度です この変数の値を毎フレーム、クマのx方向に足し続けるようにします。34行目のonenterframeの中に追加してみましょう。 +=は「this.x = this.x+this.vx」と同じ意味です。 ```javascript= //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; } ``` これでクマがゲームが始まったあと右に移動し続けるようになりました。 次に画面両端にいったら左右逆に移動するようにします。this.vxの処理を-の値にしてあげましょう。下のコードを35行目(this.x += this.vx; の下)に書いていきましょう。 ```javascript= if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } ``` if文の「||」は「または」という意味です、条件を2つ書いてどちらかが起きたときにif分の中の処理をしたいときに使います。 例えばこんな感じです ```javascript= if(条件A || 条件B){ 行いたい処理 } ``` この時は条件A,Bのどちらかが満たされていればif文の{}の中の処理が行われます。 右に画面端に行ったときに速度の値vxに-1をかけると値は―5になります。逆に左に移動したときに―1をかけると5に戻ります。これで左右を移動するクマができました。 クマの動きは常に一定の速度であることがわかります。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5;//ここを追加 game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; //ここを追加 if(this.x >= GameWidth||this.x <=0){//ここを追加 this.vx *= -1;//ここを追加 }//ここを追加 } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを1体作成する bear[0] = new Bear(320,160); // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step2 クマを10体階段状に出そう クマの数を10体にして下の画像のように階段みたいにしてみましょう。 ![](https://i.imgur.com/HKptEY3.png) 1、2日目のクマさんのフルーツ狩りの時のようにfor文を使っていきましょう。 階段状に表示する方法は確認クイズでた問題と一緒です。 73行目のクマを表示する命令を書き換えましょう。 変更前 ```javascript= //クマを1体作成する bear[0] = new Bear(320,160); ``` 変更後 ```javascript= //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } ``` この時クマの位置はそれぞれ(0,0)(16,16)(32,32)…(272,272)(288,288),(304,304)になっています。 これで10体画面に出るようになりました。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){//ここを追加 bear[i] = new Bear(i*16,i*16);//ここを追加 }//ここを追加 // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step3 画面にタッチしたときボールが縦方向に飛んでいくようにしよう 次はボールが上に向かって飛んでいくようにしましょう。 ![](https://i.imgur.com/i6jle6W.gif) ここでボールを上に向かって投げ上げたときの運動の式を使います。 <details> <summary>ボールの投げ上げの公式について詳しく知りたい人はここをクリック</summary> ## ボールの運動の式 ## 垂直投げ上げの場合 鉛直投げ上げでは一般的に、上向きを正の値とします。ここで、重力加速度gは常に下向きの力でした。 鉛直投げ上げでは、上向きが正なので、下向きの力である重力加速度gは-gと表現されます。(下図参照) ※物体が上昇している間であろうと、重力加速度gは常に下向きの力です。なので、鉛直投げ上げにおける加速度は常に-gです。 このことから物体は等加速度直線運動をしていることが分かります よって式は以下のようになります [鉛直投げ上げ公式] ・速度 v = v0-gt ・変位 y = v0t-1/2gt² ・時間を含まない式 v²-v0² = -2gy これらの式をもとにボールの投げ上げの動きを作っていきましょう </details> まずはontouchendの中にy方向の速度の変数を用意します。touch_flagもtrueにするようにします。 変更前 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; }); ``` 変更後 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); ``` power_zoomは今回のために用意した画面の調整用の関数です。 次にクラスBallの中にtouch_flagがtrueの時にボールを動かす処理を追加します。62行目からのonenterframeの部分を変更しましょう。 変更前 ```javascript= //enterframeイベントのリスナーを定義する onenterframe: function() { }, ``` 変更後 ```javascript= //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vy = this.EOM_vy(this.vy0,t); } }, ``` tは秒数を測っています。 zoom_yはボールのy方向の位置をenchant.js用の位置に変えてくれる関数です。 次に上のコードに書いてある関数EOM_y,EOM_vyを作成します。これはボールの運動方程式となります。中身を見てみましょう。 これを71行目の下に書いていきます。 ```javascript= EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, ``` ボールには重力加速度がかかるので上のような方程式になります。 これでボールを上に投げることができるようになりました。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){//ここに追加 t = game.frame/game.fps; //時間を測る//ここに追加 //y方向の動き//ここに追加 this.y = this.EOM_y(this.vy0,t);//ここに追加 this.y = zoom_y(this.y);//ここに追加 //ボールの速さを計測する this.vy = this.EOM_vy(this.vy0,t);//ここに追加 }//ここに追加 }, EOM_y: function(v0,t) {//ここに追加 var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt²//ここに追加 return y;//ここに追加 },//ここに追加 EOM_vy: function(v0,t) {//ここに追加 var v =v0-g*t;//v=v0-gt //ここに追加 return v;//ここに追加 },//ここに追加 }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0;//ここに追加 touch_flag = true;//ここに追加 ball.vy0 = 2;//y軸方向の速さ(初速度)//ここに追加 ball.vy0 = power_zoom(ball.vy0);//ここに追加 }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step4 画面にタッチしたときボールが斜め方向に飛んでいくようにしよう 次にx方向の動きも加えてボールが斜めに移動するようにします。 ![](https://i.imgur.com/ODZM0vX.gif) ボールを斜めに投げたときボールは放物線を描いて運動します。この動きを方程式にしてみましょう。 <details> <summary>斜めに投げたボールの公式について詳しく知りたい人はここをクリック</summary> ### 斜方投射の場合 斜め方向に初速を与えて、あとは重力の力にまかせて落下させるような運動を斜方投射といいます。 運動を水平方向と鉛直方向に分解して考えていきましょう 横軸の x軸に着目すると、速度が初速度のまま一定の等速直線運動(等速度運動)。 ![](https://i.imgur.com/EOAfMoI.gif) 縦軸の y軸に着目すると、速度はだんだん遅くなり、やがて静止し、向きを変えて下向きに落ちていきます。 ![](https://i.imgur.com/lulNkP4.gif) 鉛直投げ上げでは、上向きが正なので、下向きの力である重力加速度gは-gと表現されます。 ※物体が上昇している間であろうと、重力加速度gは常に下向きの力です。なので、鉛直投げ上げにおける加速度は常に-gです。 これらから等速直線運動の式をもとにx軸方向の式を作ります [投射x軸公式] 速度 vx = vx0   (一定) 位置 x = vx0  t y軸方向には、投げ上げの運動をするのでy軸の初速度を求めて式に入れます この式を使っていきます [投射y軸公式] 速度 vy = vy0 - g t 位置 y = vy0 t - 1/2 gt² </details> やり方はStep3と同じようにやっていきましょう。 まずはontouchedの中にx方向のボールの速度を追加します。 129行目から変えてみましょう。 変更前 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); ``` 変更後 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); ``` クラスBallの中にボールのx方向の移動を加えていきます。 61行目から変えてみましょう 変更前 ```javascript= //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vy = this.EOM_vy(this.vy0,t); } }, ``` 変更後 ```javascript= //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } }, ``` Step3の時のように76行目から関数を2つ追加しましょう。 変更前 ```javascript= EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, ``` 変更後 ```javascript= //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, ``` これでx方向へのボールの動きもできました。公式見るとx方向の公式には重力は関わっていないことが分かります。他の関数の式も確認してみましょう。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t);//ここに追加 this.x = zoom_x(this.x);//ここに追加 //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t);//ここに追加 this.vy = this.EOM_vy(this.vy0,t); } }, //速度の公式を出す EOM_x: function(v0,t) {//ここに追加 var x = v0*t;//x=v0t//ここに追加 return x;//ここに追加 },//ここに追加 EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) {//ここに追加 var v =v0;//v=v0; //ここに追加 return v;//ここに追加 },//ここに追加 EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度)//ここに追加 ball.vx0 = power_zoom(ball.vx0);//ここに追加 ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step5 ボールに当たり判定をつけよう それではボールとクマに当たり判定を付けて点数がつくようにしましょう。 ![](https://i.imgur.com/UeNnHci.gif) やり方は2日目の授業のStep11と一緒です。当たり判定の命令はBearのクラスに追加します。 以下のコードを39行目に追加しましょう。 ```javascript= if(this.within(ball)){ game.rootScene.removeChild(this); score = score + 100; scoreLabel.score = score; } ``` これでスコアをつけることができました。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){//ここに追加 game.rootScene.removeChild(this);//ここに追加 score = score + 100;//ここに追加 scoreLabel.score = score;//ここに追加 }//ここに追加 } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step6 ボールが落ちたときにゲームを終了するようにしよう それでは、ボールがゲーム画面より下に落ちたときに点数を表示してゲームを終わらせるようにしましょう。 ![](https://i.imgur.com/E1jsWWw.png) 今回はボールの高さがGameHeightより大きくなったときになります。 82行目に以下のコードを追加しましょう。 ```javascript= //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } ``` これでゲームの終了条件ができました。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){ game.rootScene.removeChild(this); score = score + 100; scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){//ここに追加 /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene();//ここに追加 game.endScene.image = game.assets['images/clear.png'];//ここに追加 alert("スコアは"+score+"点でした");//ここに追加 game.end();//ここに追加 game.stop();//ここに追加 }//ここに追加 }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step7 クマの種類をランダムにしてみよう 的役のクマにバリエーションを持たせたいのでクマを「茶ぐま」、「白くま」、「女の子ぐま」の3種類がランダムででるようにします。 ![](https://i.imgur.com/C0OSHwI.png) クラスBearの中でframeをランダムに決めるようにしましょう。 下の1行のコードを30行目に追加してください。 ```javascript= this.frame = (Math.floor(Math.random()*3))*5;//0,5,10のいずれかの数値をだす ``` このように書けば0,5,10のどれかの値がでます。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; this.frame = (Math.floor(Math.random()*3))*5;//ここに追加 game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){ game.rootScene.removeChild(this); score = score + 100; scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step8 クマのスコアを変えてみよう つぎにクマのフレームごとにあてたときにもらえる点数を変えてみましょう。 ![](https://i.imgur.com/wdh8CuC.gif) 茶ぐまを100点、白熊を200点、女の子ぐまを-100点にします。 41行目のクマの当たり判定の部分にif文をつけて変更してみましょう。 変更前 ```javascript= if(this.within(ball)){ game.rootScene.removeChild(this); score = score + 100; scoreLabel.score = score; } ``` if文を使っていきましょう。 変更後 ```javascript= if(this.within(ball)){ game.rootScene.removeChild(this); if(this.frame==0){//茶ぐまのとき score = score + 100; } if(this.frame==5){//白くまのとき score = score + 200; } if(this.frame==10){//女の子ぐまのとき score = score - 100; } scoreLabel.score = score; } ``` ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; this.frame = (Math.floor(Math.random()*3))*5;//0,5,10のいずれかの数値をだす game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){ game.rootScene.removeChild(this); if(this.frame==0){//ここに追加 score = score + 100;//ここに追加 }//ここに追加 if(this.frame==5){//ここに追加 score = score + 200;//ここに追加 }//ここに追加 if(this.frame==10){//ここに追加 score = score - 100;//ここに追加 }//ここに追加 scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step9 画面を引っ張ってボールの速度を決定しよう クマの種類を増やすとボールの狙いをつけたくなります。そこで画面をクリックして引っ張ってボールをとばしてみましょう。 ![](https://i.imgur.com/6y2AUxf.gif) 今まで使っていなかった。touchstartを使います。 画面をクリックしたときの位置を保存しましょう。162行目にコードを追加します。 変更前 ```javascript= //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる }); ``` 変更後 ```javascript= //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる start_x = event.x; start_x = fromGetToShahoux(start_x); start_y = event.y; start_y = fromGetToShahouy(start_y); }); ``` touchendの処理も追加します。 クリックが終わったときの位置をとって、クリックを始めたときの位置とクリックが終わったときの位置の2点の距離を測ります。 変更前 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる game.frame = 0; touch_flag = true; ball.vx0 = 2;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = 2;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); ``` 変更後 ```javascript= //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる end_x = event.x; end_x = fromGetToShahoux(end_x); end_y = event.y; end_y = fromGetToShahouy(end_y); game.frame = 0; touch_flag = true; //ボールの速さ(初速度) ball.v0 = get_distance(start_x,start_y,end_x,end_y); ball.vx0 = end_x-start_x;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = end_y-start_y;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); ``` fromGetToShahoux,fromGetToShahouy タッチした場所の位置を計算用に合わせる関数です。 get_distaceは二つの点を使って2点をつなげたときの線の距離を計算する関数です。 計算は難しいですが、これでクリックし始めた位置とクリックし終わった位置でボールを飛ばすことができるようになりました。 実際に試してみましょう。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; this.frame = (Math.floor(Math.random()*3))*5;//0,5,10のいずれかの数値をだす game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){ game.rootScene.removeChild(this); if(this.frame==0){ score = score + 100; } if(this.frame==5){ score = score + 200; } if(this.frame==10){ score = score - 100; } scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる start_x = event.x;//ここに追加 start_x = fromGetToShahoux(start_x);//ここに追加 start_y = event.y;//ここに追加 start_y = fromGetToShahouy(start_y);//ここに追加 }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる end_x = event.x;//ここに追加 end_x = fromGetToShahoux(end_x);//ここに追加 end_y = event.y;//ここに追加 end_y = fromGetToShahouy(end_y);//ここに追加 game.frame = 0; touch_flag = true; //ボールの速さ(初速度) ball.v0 = get_distance(start_x,start_y,end_x,end_y);//ここに追加 ball.vx0 = end_x-start_x;//x軸方向の速さ(初速度)//ここに追加 ball.vx0 = power_zoom(ball.vx0);//ここに追加 ball.vy0 = end_y-start_y;//y軸方向の速さ(初速度)//ここに追加 ball.vy0 = power_zoom(ball.vy0);//ここに追加 }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` これでゲームの大まかな部分は完成です。 ## Step10 クマを20体に増やして位置をランダムにしてみよう 次に的のクマをたくさん出してみましょう。 ![](https://i.imgur.com/iw6LUWd.png) クマを10体出していた部分(125行目)を変更してみましょう 変更前 ```javascript= //クマを10体作成する for(var i=0; i<10; i++){ bear[i] = new Bear(i*16,i*16); } ``` 変更後 ```javascript= //クマを20体作成する for(var i=0; i<20; i++){ bear[i] = new Bear(Math.floor(Math.random()*GameWidth),Math.floor(Math.random()*GameHeight)); } ``` ランダムのやり方はリンゴの時と一緒です。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; this.frame = (Math.floor(Math.random()*3))*5;//0,5,10のいずれかの数値をだす game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.within(ball)){ game.rootScene.removeChild(this); if(this.frame==0){ score = score + 100; } if(this.frame==5){ score = score + 200; } if(this.frame==10){ score = score - 100; } scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを20体作成する for(var i=0; i<20; i++){//ここに追加 bear[i] = new Bear(Math.floor(Math.random()*GameWidth),Math.floor(Math.random()*GameHeight));//ここに追加 }//ここに追加 // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる start_x = event.x; start_x = fromGetToShahoux(start_x); start_y = event.y; start_y = fromGetToShahouy(start_y); }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる end_x = event.x; end_x = fromGetToShahoux(end_x); end_y = event.y; end_y = fromGetToShahouy(end_y); game.frame = 0; touch_flag = true; //ボールの速さ(初速度) ball.v0 = get_distance(start_x,start_y,end_x,end_y); ball.vx0 = end_x-start_x;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = end_y-start_y;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ``` ## Step11 クマの動きを複雑にしてみよう 最後にクマにy方向の動きを追加しましょう。 ![](https://i.imgur.com/w3WLGOU.gif) vxを追加したときに同様に動きを追加してみましょう まずは30行目に以下のコードを追加します。 ```javascript= this.vy = 5; ``` 次に39行目からのコードを変更しましょう。 変更前 ```javascript= this.x += this.vx; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } ``` 変更後 ```javascript= this.x += this.vx; this.y += this.vy; if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.y >= GameHeight||this.y <=0){ this.vy *= -1; } ``` これで今回のゲームは完成です。どのようにボールを打てば点数が高くなるか考えてみましょう。 ```javascript= enchant(); var GameWidth = 640; var GameHeight = 320; var ball; var bear = Array(); var score = 0; //重量加速度 var g = 9.8; //ボールが動くかどうか var touch_flag; //時間を測る var t =0; //タッチしたときの座標を取る var start_x = 0; var start_y = 0; var end_x = 0; var end_y = 0; // ここで自作クラスBearをつくる Bear = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 32, 32); //Spriteオブジェクトを初期化 this.image = game.assets['images/chara1.gif']; this.x = x; this.y = y; //クマの動きの速度 this.vx = 5; this.vy = 5;//ここに追加 this.frame = (Math.floor(Math.random()*3))*5;//0,5,10のいずれかの数値をだす game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { this.x += this.vx; this.y += this.vy;//ここに追加 if(this.x >= GameWidth||this.x <=0){ this.vx *= -1; } if(this.y >= GameHeight||this.y <=0){//ここに追加 this.vy *= -1;//ここに追加 }//ここに追加 if(this.within(ball)){ game.rootScene.removeChild(this); if(this.frame==0){ score = score + 100; } if(this.frame==5){ score = score + 200; } if(this.frame==10){ score = score - 100; } scoreLabel.score = score; } } }); // ここで自作クラスBearをつくる Ball = Class.create(Sprite, // Spriteクラスを継承 { initialize: function(x, y) { //初期化する Sprite.call(this, 16, 16); //Spriteオブジェクトを初期化 this.image = game.assets['images/icon1.png']; this.x = x; this.y = y; //ボールの速さ(初速度) this.v0 = 0; this.vx0 = 0;//x軸方向の速さ(初速度) this.vy0 = 0;//y軸方向の速さ(初速度) //ボールの速さ(途中) this.vx = 0;//x軸方向の速さ(途中) this.vy = 0;//y軸方向の速さ(途中) this.frame = 1; game.rootScene.addChild(this); }, //enterframeイベントのリスナーを定義する onenterframe: function() { if(touch_flag){ t = game.frame/game.fps; //時間を測る //x方向の動き this.x = this.EOM_x(this.vx0,t); this.x = zoom_x(this.x); //y方向の動き this.y = this.EOM_y(this.vy0,t); this.y = zoom_y(this.y); //ボールの速さを計測する this.vx = this.EOM_vx(this.vx0,t); this.vy = this.EOM_vy(this.vy0,t); } //ボールが落ちたときにゲームを終了する if(this.y>GameHeight){ /* クリア画面を出したいときは以下の記述 */ game.endScene = new SplashScene(); game.endScene.image = game.assets['images/clear.png']; alert("スコアは"+score+"点でした"); game.end(); game.stop(); } }, //速度の公式を出す EOM_x: function(v0,t) { var x = v0*t;//x=v0t return x; }, EOM_y: function(v0,t) { var y = v0*t-1/2*g*t*t;//y=v0t-1/2gt² return y; }, EOM_vx: function(v0,t) { var v =v0;//v=v0; return v; }, EOM_vy: function(v0,t) { var v =v0-g*t;//v=v0-gt return v; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.gif', 'images/icon1.png','images/clear.png'); game.onload = function() { //ボールを作成する ball = new Ball(0,GameHeight-32); //クマを20体作成する for(var i=0; i<20; i++){ bear[i] = new Bear(Math.floor(Math.random()*GameWidth),Math.floor(Math.random()*GameHeight)); } // スコアラベルを作成 scoreLabel = new ScoreLabel(10, 10); scoreLabel.score = score; game.rootScene.addChild(scoreLabel); // ラベルを作成 var GLabel = new Label("重量加速度:"+g+"m/s²"); GLabel.x = 20; // X座標 GLabel.y = 25; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(GLabel); // ラベルを作成 var V0Label = new Label("初速度:"+ball.v0+"m/s"); V0Label.x = 20; // X座標 V0Label.y = 45; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(V0Label); // ラベルを作成 var VXLabel = new Label("x軸速度:"+ball.vx+"m/s"); VXLabel.x = 20; // X座標 VXLabel.y = 65; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VXLabel); // ラベルを作成 var VYLabel = new Label("y軸速度:"+ball.vy+"m/s"); VYLabel.x = 20; // X座標 VYLabel.y = 85; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(VYLabel); //ゲーム画面のどこかをタッチし始めた時の処理 game.rootScene.addEventListener('touchstart', function(event) { //eventにタッチされた座標が入ってくる start_x = event.x; start_x = fromGetToShahoux(start_x); start_y = event.y; start_y = fromGetToShahouy(start_y); }); //ゲーム画面のどこかをタッチし終わった時の処理 game.rootScene.addEventListener('touchend', function(event) { //eventにタッチされた座標が入ってくる end_x = event.x; end_x = fromGetToShahoux(end_x); end_y = event.y; end_y = fromGetToShahouy(end_y); game.frame = 0; touch_flag = true; //ボールの速さ(初速度) ball.v0 = get_distance(start_x,start_y,end_x,end_y); ball.vx0 = end_x-start_x;//x軸方向の速さ(初速度) ball.vx0 = power_zoom(ball.vx0); ball.vy0 = end_y-start_y;//y軸方向の速さ(初速度) ball.vy0 = power_zoom(ball.vy0); }); game.onenterframe = function(){ //文字の更新 var v0 = ball.v0 * 100; V0Label.text = "初速度:"+Math.round(v0)/100+"m/s"; var vx = ball.vx * 100; VXLabel.text = "x軸速度:"+Math.round(vx)/100+"m/s"; var vy = ball.vy * 100; VYLabel.text = "y軸速度:"+Math.round(vy)/100+"m/s"; }; } game.start(); //game.debug(); } //タッチした始点と終点から距離を求める get_distance = function(sx,sy,ex,ey) { var distance = Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ex-sx,2)); return distance; }; //取得した座標を斜方投射座標へ返還(x) fromGetToShahoux = function(x) { return x / 32; } //取得した座標を斜方投射座標へ返還(y) fromGetToShahouy = function(y) { return (320 - 32 - y) / 32; } //計算した座標をenchantへ返還(x) zoom_x = function(x) { return x * 32; }; //計算した座標をenchantへ返還(y) zoom_y = function(y) { return 320 - 32 - 32 * y; } //投射する計算 power_zoom = function(mat) { var pzoom = mat * 5; return pzoom; } ```