# チュートリアル[ゲーム要素に数学を加えてみようその1] ### 目次 > #### Step0 まずは準備 > #### Step1 ゲームの基本を作ろう > #### Step2 クマに動きを追加しよう。(1次関数の場合) > #### Step3 クマに動きを追加しよう。(2次関数の場合) > #### Step4 クマに動きを追加しよう。(3次関数の場合) > #### Step5 システムにボタンを追加しよう ### Step0 まずは準備 ## 数学の動き ゲームを作っていくときにキャラクターに変わった動きをさせたいときがあります。 このような動きを簡単に作るためには数学のグラフの動きを再現することが必要です。 まずは数学のグラフの動きを理解して、シューティングゲームに導入してみましょう。 ## 実際に使ってみよう 今回はこちら用意したゲーム作成システムでゲームを作ってみましょう 以下の部分をクリックしてみてください。 [ゲーム作成システム](https://summ) するとログイン画面が出ます。 ![](https://i.imgur.com/uQ9xF8k.png) 皆さんの机の上にあるメモを見てユーザIDとパスワードを入力してください。 今回のチュートリアルに沿って、9つの問題があると思います。 上から順番にやっていきましょう。 ### Step1 クマに動きを追加しよう。(1次関数の場合) Step1ではこのようなクマの動きを作ります。 ![](https://i.imgur.com/jKE5Ypt.gif) <!-- ![](https://i.imgur.com/SzqLUIG.gif) --> このクマは、中学校の数学で習う1次関数の知識を使って動かしています。それでは、1次関数についてすこしおさらいをしてみましょう。 #### 1次関数とは 2つの変数xとyがあり、yの値がxの値にともなって変化し,xの値を定めるとyの値がただ一つに決まる場合yはxの関数であるといいます。 その中でも,y=x,y=3xのようにyをxの1次式で表せる関数を1次関数と呼びます。 1次関数の式は以下のように表せます。 > y=ax+b 例えば、y=2xのとき、xが-5から5の間において、以下の表のようになります。 ![](https://i.imgur.com/FZL1WuS.png) 例えば,xが-5のとき、y=2xということは、y=2×(-5)となりy=-10となります。 また、この関数をx,y座標上のグラフで表すと、以下のようになります。 ![](https://i.imgur.com/7yuArQb.png) 先ほど見せたクマの動きの動画をみてみましょう。クマはy=2xの動きをしていたことがわかります。 以上が1次関数の簡単な説明になります。Step1では、<font color="red">**1次関数(y=2x)の動きをするクマを作っていきます。**</font> ちなみに、<font color="red">**enchant.jsにもx,yの座標の概念があるため上手く活用しましょう。**</font> #### クマを表示しよう。(1次関数の場合) まずは、クマを表示するだけのコードを作成します。このような状態を目指します。 //画像表示 それでは下のコードのような骨組みを用意しましょう。 ```javascript= enchant(); var game; var GameWidth = 320; var GameHeight = 320; /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ //➀ここに動きの処理を追加する }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); /* クマをつくる */ bear = new Bear(-4, -4); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; ``` 2日目に学んだことを思い出しながらコードを確認してみましょう。 クマの画像が表示されていれば大丈夫です。 それではこのコードにクマの動きを追加していきます。 #### クマに動きを追加しよう。(1次関数の場合) それではさいごに,クマにy=2xのグラフのような動きをするようにコードを追加してみましょう。動きが追加されると,このような実行結果が得られます。 <font color="blue">画像を追加</font> 今回は関数liner_graphを作成して、そこにx座標を渡してyの値が返ってくるようにします。追加するソースコードは以下のようになります。 ➀に以下のソースコードを追加します。 ```javascript= /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = this.liner_graph(this.x); this.x += 4; }, //1次関数でグラフを作る liner_graph : function(x){ var y = 2*x; //y=2xの式 return y;//求められた値を返す }, ``` 追加した結果、全体のコードはこのようになります。 <details><summary><font color="blue">現状のコード(ここをクリック)</font></summary> </details> ここで、<font color="red">**this.yとyは別の変数であることに注意してください。**</font> それでは動かしてみましょう。 動かしてみるとわかるのですが、このままだとenchant.jsの座標では背景のマス目とは動きが合いません。なので数値を調整して座標を合わせることにします。onenterfraneの部分を修正します。 ```javascript= this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 4; ``` コード全体は以下のようになっています。 <details><summary>現状のコード(ここをクリック)</summary> ```javascript= Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ //➀ここに動きの処理を追加する * enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 4; }, //1次関数でグラフを作る liner_graph : function(x){ var y = 2*x; //y=2xの式 return y;//求められた値を返す }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); /* クマをつくる */ bear = new Bear(-4, -4); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; ``` </details> これでクマが左からy=2xの動きをしながら動くようになりました。 ### クマの動きに線を追加しよう。 次にクマの動きに合わせて、グラフ上に線を引くようにしましょう。 まずはゲーム開始時に線を引くようのオブジェクトの設定をします。 ```javascript= game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); bg.x +=1; /* クマをつくる */ bear = new Bear(0, 0); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); }; ``` そのあとクマの移動に合わせてクマに追従して線がでるようにしましょう。 ```javascript= this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 4; //線を描画する //Spriteを作ります //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; ``` クマの左上の位置から線が出ていることが確認できます。 ![](https://i.imgur.com/jKE5Ypt.gif) コードは以下のようになります。 <details><summary>現状のコード</summary> ```javascript= Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ //➀ここに動きの処理を追加する * enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 4; //線を描画する //Spriteを作ります //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; }, //1次関数でグラフを作る liner_graph : function(x){ var y = 2*x; //y=2xの式 return y;//求められた値を返す }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); /* クマをつくる */ bear = new Bear(-4, -4); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; ``` </details> 次にグラフの値の変化を分かりやすくするためにクラスBearの初期設定にグラフの要素の変数を追加します。変数名はa,bとします。 変数の値は変数名 = グラフの値 * 調整用の値のようにしています。+ ```javascript= /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a = 1; //グラフの頂点 this.b = 2*GameHeight/16;//GameHeight/16は調整用 game.rootScene.addChild(this); }, ``` これをもとに関数を編集します ```javascript= //1次関数でグラフを作る liner_graph : function(x){ var y =this.a*x+this.b; return y; }, ``` この時,グラフの動きはy=2xになります。 変数の値をy=4x+3にしてみます ```javascript= this.a = 4; this.b = 3*GameHeight/16;//GameHeight/16は調整用 ``` 実際に動作を確認してみましょう。できたら変数の値を変化させてグラフの動きを変化させてみましょう。 ## 挑戦してみよう それではthis.a,this.bの値を変更して以下のグラフを作ってみましょう。 (1)y=1/4x+1の式の動きを作ってみよう (2)y=-3x+1の式の動きを作ってみよう <details><summary>コードは以下のようになります。</summary> ```javascript= enchant(); var game; var GameWidth = 320; var GameHeight = 320; /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a = 4; //グラフの切片 this.b = 3*GameHeight/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2;//関数の値をゲーム座標に移す this.x += 4; //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; }, //1次関数でグラフを作る liner_graph : function(x){ var y =this.a*x+this.b; return y; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); bg.x +=1; /* クマをつくる */ bear = new Bear(-4, -4); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; ``` </details> ## STEP2 クマに動きを追加しよう。(2次関数の場合) それではSTEP1のコードに2次関数の動きを追加しましょう ### 2次関数とは では次に二次関数の式の動きを作ってみましょう ### 二次関数とは 二次関数とはy=x²,y=3x²+2のようにyをxの2次式で表せる関数である.式は以下のように表せる. y=ax²+bx+c y=x²のxとyの関係表は以下のようになる ![](https://i.imgur.com/LzPRmOi.png) ソースコードはStep1と同様のモノを使っていきましょう。 新しい関数quadratic_graphを作ります y=a(x-c)²+bの式になるように式を考えましょう。 ```javascript= //2次関数でグラフを作る quadratic_graph : function(x){ var y =this.a2*(x-this.c2)*(x-this.c2)+this.b2; return y; }, ``` クマのクラスにも使う変数を追加しておきます。今回はa2,b2,c2の3つです。値もグラフが通るように調整します。 this.aの1/16は傾き1を表現するために16で割っています。なので傾きを2にしたい場合はthis.a2=2/16になります。 ```javascript= /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a = 4; //グラフの切片 this.b = 3*GameHeight/16; //2次関数用の設定 //グラフの傾き this.a1 = 1/16; //グラフの頂点 this.b2 = 2*GameHeight/16; this.c3 = 0*GameWidth/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.quadratic_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 1; ``` <details> <summary>コード全体はこのようになっています</summary> enchant(); var game; var GameWidth = 320; var GameHeight = 320; /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a = 4; //グラフの切片 this.b = 3*GameHeight/16; //グラフの傾き this.a2 = 1/16; //グラフの頂点 this.b2 = 2*GameHeight/16; this.c2 = 0*GameWidth/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.quadratic_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 1; //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; }, //1次関数でグラフを作る liner_graph : function(x){ var y = this.a*x+this.b; return y; }, //2次関数でグラフを作る quadratic_graph : function(x){ var y = this.a2*(x-this.c2)*(x-this.c2)+this.b2; return y; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); bg.x +=1; /* クマをつくる */ bear = new Bear(-4, -4); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; </details> この変数の場合、a2=1,b2=2,c2=0なので式はy=x²+2になります ![](https://i.imgur.com/AtBQfWn.gif) 頂点を(0,2)とした放物線を描いていることが確認できます。 ## 挑戦してみよう それではthis.a,this.bの値を変更して以下のグラフを作ってみましょう。 (1)y=4(x-1)²-4の式の動きを作ってみよう (2)y=y =-2(x-3)²-4の式の動きを作ってみよう (3)y=-x²+6x-5の式の動きを作ってみよう ヒント:式はy=-(x-3)²+4に変換できます ## STEP3 クマに動きを追加しよう。(3次関数の場合) ### 三次関数とは 三次関数とはy=x³,y=3x³+6x²+2x+1のようにyをxの3次式で表せる関数である.式は以下のように表せる. y=ax³+bx²+cx+d y=x³のxとyの対応表を以下に示す. ![](https://i.imgur.com/148joIQ.png) ## 三次関数の動きをする関数を作成しよう 今までの関数と同様に三次関数の動きをする関数を作成しましょう. 関数は以下のようになります. ```javascript= //3次関数でグラフを作る cubic_graph : function(x){ var y = this.a3*x*x*x+this.b3*x*x+this.c3*x+this.d3; return y; }, ``` クラスBearに変数の値を4つ追加しましょう。 ```javascript= /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a3 = 1/GameWidth; //グラフの頂点 this.b3 = -3/(16+1.2); this.c3 = 0/GameWidth; this.d3 = 4*GameHeight/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.cubic_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 1; //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; }, //3次関数でグラフを作る cubic_graph : function(x){ var y = this.a*x*x*x+this.b*x*x+this.c*x+this.d; return y; }, }); ``` <details> <summary>コード全体はこのようになっています</summary> enchant(); var game; var GameWidth = 320; var GameHeight = 320; /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //グラフの傾き this.a = 4; //グラフの切片 this.b = 3*GameHeight/16; //グラフの傾き this.a2 = 1/16; //グラフの頂点 this.b2 = 2*GameHeight/16; this.c2 = 0*GameWidth/16; //グラフの傾き this.a3 = 1/GameWidth; //グラフの頂点 this.b3 = -3/(16+1.2); this.c3 = 0/GameWidth; this.d3 = 4*GameHeight/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { this.y = -1*this.cubic_graph(this.x-GameWidth/2)+GameHeight/2; this.x += 1; //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; }, //1次関数でグラフを作る liner_graph : function(x){ var y = this.a*x+this.b; return y; }, //2次関数でグラフを作る quadratic_graph : function(x){ var y = this.a2*(x-this.c2)*(x-this.c2)+this.b2; return y; }, //3次関数でグラフを作る cubic_graph : function(x){ var y = this.a3*x*x*x+this.b3*x*x+this.c3*x+this.d3; return y; }, }); window.onload = function() { game = new Game(GameWidth, GameHeight); game.preload('images/chara1.png','images/masu_関数.png','images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); bg.x +=1; /* クマをつくる */ bear = new Bear(-4, -4); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); }; /* game.debug()で動かすと,画像の枠がわかりやすくなるため,当り判定が確認しやすい */ game.start(); //game.debug(); }; </details> 実際に動作を確認してみましょう ![](https://i.imgur.com/G6RY9XR.gif) ## 挑戦してみよう それではthis.a3,this.b3,this.c3,thisd3の値を変更して以下のグラフを作ってみましょう。 (1)y=-x³の式の動きを作ってみよう (2)y=の式の動きを作ってみよう ## Step5 システムにボタンを追加しよう ゲームにxの値を入力してその位置でクマが止まるようにします。 そのために入力エリアと開始ボタンを作成します。 ```javascript= // ラベルを作成 var myLabel = new Label("x:"); myLabel.x = 330; // X座標 myLabel.y = 20; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(myLabel); //開始ボタンの作成 input_button = new Sprite(124, 30); input_button.x = 340; input_button.y = 40; input_button.image = game.assets['next.png']; //開始ボタンを画面に表示 game.rootScene.addChild(input_button); //開始ボタンをタッチしたとき入力値を計算してクマの停止座標を決める input_button.addEventListener('touchstart', function() { bear.input_x = input._element.value; var input_up = Number(bear.input_x);//分子の値を取得する var input_down = 1; //分母の値を取得する //入力値に’/’が含まれているときに’/’を境に分子と分母を取得する if ( bear.input_x.indexOf('/') != -1){ input_up = Number(before_cut(bear.input_x));//分子の値を取得する input_down = Number(after_cut(bear.input_x));//分母の値を取得する } input_num = input_up/input_down;//分子÷分母を行う bear.stop_x = Math.round(160+input_num*20);//クマの停止座標をゲーム座標に合わせる bear.flag = true;//クマの動作を開始する }); ``` ボタンには分数が入力されたときにもちゃんと取得できるような処理が追加されています。 関数として文字をうまく取得できるようなプログラムを作成します。 ```javascript= //決められた値より前を取り出す before_cut = function(value) { // 1.切り出す元となるテキスト取得 var str = value; // 2.切り出す基準となるテキスト取得 var cut_str = "/"; // 3.基準となる文字列の位置を取得 var index = str.indexOf(cut_str); // 4.基準文字列から後の文字列を切り出して表示 str = str.substring(0, index); return str; } //決められた値より後を取り出す after_cut = function(value) { // 1.切り出す元となるテキスト取得 var str = value; // 2.切り出す基準となるテキスト取得 var cut_str = "/"; // 3.基準となる文字列の位置を取得 var index = str.indexOf(cut_str); // 4.基準文字列から後の文字列を切り出して表示 str = str.slice(index + 1); return str; } ``` これに合わせてクラスBearも変えていきましょう。 ```javascript= /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //クマの動作開始フラグ this.flag = false; //入力x座標 this.input_x =0; //停止する位置 this.stop_x = 0; //グラフの傾き this.a = 2; //グラフの切片 this.b = 0*GameHeight/16; this.c = 0*GameWidth/16; //グラフの値(2次関数用) this.a2 = 1/32; this.b2 = 0; this.c2 = 0; //グラフの値(3次関数用) this.a3 = 1/GameWidth; this.b3 = 0/(16+1.2); this.c3 = 0/GameWidth; this.d3 = 0*GameHeight/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { if(this.flag){ //クマの動作を行う this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2;//関数の値をゲーム座標に移す this.x += 1; //クマがstop_xのx位置に来たとき if(this.x == Math.floor(this.stop_x)){ //sin表から入力されたxの値からyの値を出す alert("座標はx:"+this.input_x+"y:"+((this.liner_graph(this.x)-GameHeight*2)/20)); this.flag = false; } //線を描画する //Spriteを作ります //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; } }, //1次関数でグラフを作る liner_graph : function(x){ var y =this.a*(x-this.c)+this.b; return y; }, //2次関数でグラフを作る quadratic_graph : function(x){ var y =this.a2*(x-this.c2)*(x-this.c2)+this.b2; return y; }, //3次関数でグラフを作る cubic_graph : function(x){ var y = this.a3*x*x*x+this.b3*x*x+this.c3*x+this.d3; return y; }, }); ``` これで好きなグラフに対して好きな位置で停止させることができるようになりました。気になる式のxの時のyの値を確認してみましょう。 ## 挑戦してみよう それでは式を組み立ててx座標を入力してその時のy座標の値を確認してみましょう。 (1)y=3x+2 x座標 2 (2)y=(x-1)²+3 x座標 1 (2)y=(x-1)²+3 x座標 1 (4)y=x³ x座標 -2 実際に自分で計算してみてy座標の位置があっているかどうか確認してみましょう。 <details> <summary>コード全体はこのようになっています</summary> ```javascript= enchant(); var game; //ゲーム画面設定 var GameWidth = 320; var GameHeight = 320; /* 独自クラスBearの定義 */ Bear = Class.create(Sprite, { initialize: function(x, y) { Sprite.call(this, 32, 32); this.image = game.assets['images/chara1.png']; this.x = x; this.y = y; //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; this.frame = 0; //クマの動作開始フラグ this.flag = false; //入力x座標 this.input_x =0; //停止する位置 this.stop_x = 0; //グラフの傾き this.a = 4; //グラフの切片 this.b = 2*GameHeight/16; //グラフの値(2次関数用) this.a2 = 1/32; this.b2 = 0; this.c2 = 0; //グラフの値(3次関数用) this.a3 = 1/GameWidth; this.b3 = 0/(16+1.2); this.c3 = 0/GameWidth; this.d3 = 0*GameHeight/16; game.rootScene.addChild(this); }, /* enterframeイベントのリスナーを設定 */ onenterframe: function() { if(this.flag){ //クマの動作を行う this.y = -1*this.liner_graph(this.x-GameWidth/2)+GameHeight/2;//関数の値をゲーム座標に移す this.x += 1; //クマがstop_xのx位置に来たとき if(this.x == Math.floor(this.stop_x)){ //入力されたxの値からyの値を出す alert("座標はx:"+this.input_x+"y:"+((this.liner_graph(this.x)-GameHeight*2)/20)); this.flag = false; } //線を描画する //Spriteを作ります //線の描画を始める context.beginPath(); //パスを開始 context.moveTo(this.ox-1, this.oy-1); context.lineTo(this.x-1, this.y-1); context.closePath(); //パスを終了 context.stroke(); //パスを描画する //1つ前の座標を保存する this.ox = this.x; this.oy = this.y; } }, //1次関数でグラフを作る liner_graph : function(x){ var y =this.a*x+this.b; return y; }, //2次関数でグラフを作る quadratic_graph : function(x){ var y =this.a2*(x-this.c2)*(x-this.c2)+this.b2; return y; }, //3次関数でグラフを作る cubic_graph : function(x){ var y = this.a3*x*x*x+this.b3*x*x+this.c3*x+this.d3; return y; }, }); window.onload = function() { game = new Game(GameWidth+200, GameHeight); game.preload('images/chara1.png','images/masu_関数.png' ,'images/next.png'); game.onload = function() { //背景画像を設定 var bg= new Sprite(320, 320); bg.image = game.assets["images/masu_関数.png"]; game.rootScene.addChild(bg); /* クマをつくる */ bear = new Bear(-4, -4); //線を作る sprite = new Sprite(320, 320); //Surfaceを作ります surface = new Surface(320, 320); //spriteのimageにsurfaceを代入します sprite.image = surface; //コンテキストを取得します context = surface.context; //シーンにサーフェスを追加する ' game.rootScene.addChild(sprite); var input = new Entity(); var input_down = new Entity(); //入力テキスト作成 input._element = document.createElement('input'); input._element.setAttribute('type','text'); input._element.setAttribute('maxlength','5'); input._element.setAttribute('value','0'); input.width = 30; input.height = 20; input.x = 340; input.y = 20; //rootSceneに追加 game.rootScene.addChild(input); // ラベルを作成 var myLabel = new Label("x:"); myLabel.x = 330; // X座標 myLabel.y = 20; // Y座標 // ラベルを画面に表示 game.rootScene.addChild(myLabel); //開始ボタンの作成 input_button = new Sprite(124, 30); input_button.x = 340; input_button.y = 40; input_button.image = game.assets['images/next.png']; //開始ボタンを画面に表示 game.rootScene.addChild(input_button); //開始ボタンをタッチしたとき入力値を計算してクマの停止座標を決める input_button.addEventListener('touchstart', function() { bear.input_x = input._element.value; var input_up = Number(bear.input_x);//分子の値を取得する var input_down = 1; //分母の値を取得する //入力値に’/’が含まれているときに’/’を境に分子と分母を取得する if ( bear.input_x.indexOf('/') != -1){ input_up = Number(before_cut(bear.input_x));//分子の値を取得する input_down = Number(after_cut(bear.input_x));//分母の値を取得する } input_num = input_up/input_down;//分子÷分母を行う bear.stop_x = Math.round(160+input_num*20);//クマの停止座標をゲーム座標に合わせる bear.flag = true;//クマの動作を開始する }); }; game.start(); }; //決められた値より前を取り出す before_cut = function(value) { // 1.切り出す元となるテキスト取得 var str = value; // 2.切り出す基準となるテキスト取得 var cut_str = "/"; // 3.基準となる文字列の位置を取得 var index = str.indexOf(cut_str); // 4.基準文字列から後の文字列を切り出して表示 str = str.substring(0, index); return str; } //決められた値より後を取り出す after_cut = function(value) { // 1.切り出す元となるテキスト取得 var str = value; // 2.切り出す基準となるテキスト取得 var cut_str = "/"; // 3.基準となる文字列の位置を取得 var index = str.indexOf(cut_str); // 4.基準文字列から後の文字列を切り出して表示 str = str.slice(index + 1); return str; } ``` </details>