広告
↓発売日:2018年09月22日↓
新品価格 |
今回は敵の動きを増やしてみましょう。
簡単な数学の関数が登場します!
数学嫌いな方もこれから習う方もSTG作りを通して数学好きになってしまうハズです。たぶん。
数学関数の動きが確認できる簡単なプログラムになります。
関数に当てはめて計算する部分
void my_move_point(){ x = x + 8; y = 1 * x; }
こちらを変えればいろいろな関数が試せますのでよかったらお使いください。
マイナス方向に変化させたい場合などはそれに合わせて「x」の初期値を変更してください。
void my_init_point(){ x = -220; y = 0; draw_x = 0; draw_y = 0; }
こちらが初期化の部分になります。
使い方が難しそう!という方はこの章を最後まで読めばきっと使えるようになると思われます。
注意点としては終了処理などは書いてないので無駄に計算され続けます!ウィンドウを閉じて強制終了してください。
ではいってみましょう!
右上がりの直線ですね。
「何の事かわからないよ!」
という方の為にまずはこの「a」という部分を忘れて
y = x;
としてみましょう。
「y」は「x」と同じって事ですね!
「x」が「10」なら「y」も「10」
「x」が「20」なら「y」も「20」
って感じです。
それでこの「x」と「y」をそのまま座標に置き換えてひたすら
「x」が「0」なら「y」も「0」
「x」が「1」なら「y」も「1」
「x」が「2」なら「y」も「2」
「x」が「3」なら「y」も「3」
「x」が「4」なら「y」も「4」
「x」が「5」なら「y」も「5」
と座標ごとに点を打つと・・・。
こんな感じになりますよね。
それでさきほどの「y = ax」をプログラム式で書くと
y = a * x;
このようになります。
「y」は「a」かける「x」って事ですね。
それでこの「a」の部分をいろんな数字に変えてみると「y」もそれに合わせていろんな結果になりますよね。
たとえば「a」が「2」だとしたら
y = 2 * x;
になるので
「x」が「0」→「y」は「0」
「x」が「1」→「y」は「2」
「x」が「2」→「y」は「4」
「x」が「3」→「y」は「6」
「x」が「4」→「y」は「8」
「x」が「5」→「y」は「10」
「y」の方が勢いよく増えていくのでこんな感じになりますよね。
これが関数のキホンです。
「y」の値は式の右側の「x」と「a」によって決まるというやつです。
さらには
y = a * x + b;
とかちょっと余計な「b」とかが増えたりする事で「y」がさらにいろんな変化をしてその結果、いろいろな座標の動き方を実現できるというワケです。
説明がわからなかった方はすいません。
そんなワケでこの関数を敵の動きに取り入れる事によってたくさんの種類の動きができるようになります。
では話を戻してまずは
y = a * x;
こちらを利用した「動き」のプログラムを見てみましょう。
「my_move_enemy()」の「case 1」「上から現れてななめに戻る」ような動きになります。
初期化部分です。
if (enemy[i].init_flag == 0){ enemy[i].x = 0; enemy[i].y = 260; enemy[i].gamecount_point = gamecount; enemy[i].init_flag = 1; } else{ /*移動部分*/ }
決まった動きになるので「x = 0」「y = 260」と初期座標はこの時点で決めてしまいます。
移動部分です。
if (gamecount < enemy[i].gamecount_point + 260){ enemy[i].y--; }
最初は上からy座標が「0」になるまで「260」カウント直線に下降します。
if (gamecount > enemy[i].gamecount_point + 300){ enemy[i].x++; enemy[i].y = 1 * enemy[i].x; }
ここがななめに戻る部分です。
「関数のキホンは「y」は「x」によって決まる」でしたね。なので先に「x」座標を動かしてあげます。
enemy[i].x++;
この関数の場合ななめに戻るって事は右にあがるって事なのでxをプラス方向「x++」に動かしてあげれば大丈夫です。
当たり前ですが逆の「x--」だと左に下がります。
あとは「y = a * x」に当てはめるだけですね。
enemy[i].y = 1 * enemy[i].x;
「ななめに戻る」ことができました。
さきほども言いましたが「a」に当たる部分「1」のトコロを変えればななめの角度が変わります。
ここで注意です。
「ステキな動きだね!」
と思って好き勝手に色んな場所に敵を配置したはいいけど思い通りに動いてくれないかと思います。
これは「y = x」というラインから外れてしまうとこのような結果になってしまいます。
ラインに合わせて調整しましょう!
「これじゃ使い物になんねえよ!」
と思った方は焦らないでください。
これは数学関数のほんの入り口になります。
先ほどの問題も解決できるばかりかまるで魔法のような動きをする関数もありますので少しづつ学んでいきましょう!
次は「y = ax + b」を紹介します。
さきほどの「y = ax」に仲間「b」が増えました。
何が「b」かといいますと
先ほどの原点を通る「y = ax」の直線を
上とか
下とか
ずらした時のたて軸に当たる部分が「b」になります。
たとえば
「y = 2x + 100」
っていう直線は
こうなります。
つまりこの「b」の場所を加えれば好きな場所でななめに折り返せるワケです。
ではどうするか?といいますと
1・折り返しの角度を決める
2・敵の登場場所を決める
3・折り返したい場所を決める
4・「b = y - ax」に当てはめる
みたいな手順で好きな場所で折り返せるようになります。
数学嫌いにはたまらない感じですよね。
後ほど例の魔法のような関数をご紹介しますので
ここはあせらず順番に初歩的な関数も試していきましょう!
では気を取り直して
角度といっても「何度」で決めるワケではないです。
「y = ax」の「a」の部分をいじってできる「傾き」になります。
とりあえず「y = 2x」でいきましょう。ちょっとだけ角度がきつい感じですね!
座標(100,260)ぐらいから登場としましょう。
折り返しポイントを(100,0)とします。
これで必要な情報はそろいました!
当てはめます!
「x」と「y」は折り返しポイントの座標
「a」は最初に決めた折り返し角度になります。
b = 0 - 2 * 100
こうなりますね!計算すると・・・。
b = -200
つまりは「y = 2x - 200」というラインに乗せればさきほどの例では上手く折り返してくれるワケです!
ここまでの一連の動きのプログラムがこちらです。
「my_move_enemy()」の「case 2」になります。
if (enemy[i].init_flag == 0){ enemy[i].x = 100; enemy[i].y = 260; enemy[i].gamecount_point = gamecount; enemy[i].init_flag = 1; } else{ /*移動部分*/ }
初期座標はさきほど決めた(100,260)からになりますね。
if (gamecount < enemy[i].gamecount_point + 260){ enemy[i].y--; }
y座標が「0」になるまで「260」カウント下降します。
if (gamecount > enemy[i].gamecount_point + 280){ enemy[i].x++; enemy[i].y = (2 * enemy[i].x) - 200; }
あとは先ほど計算して導き出した式「y = 2x - 200」のラインに乗せてあげるだけですね!
これで好きな場所で折り返せるようになりました!
続きまして「y = a / x」双曲線のご紹介です。
2つの曲線が描かれるので双曲線です。
特徴的な動きをするのでまずは動き方の確認をしてみましょう!
最初の位置を「x = -220」から始めて「x++」とインクリメントしていった場合です。
こんな感じになります。
「x」を減らしていけば逆の動きをしますし、「a」にマイナスをかけてあげれば
y = (-1 * a) / x;
今度は左上と右下のスペースに曲線が現れます。
今回は右上の曲線の動き
こちらの部分を使いたいと思います。
プログラムを見てみましょう!
「my_move_enemy()」の「case 5」になります。
if (enemy[i].init_flag == 0){ enemy[i].x = 0; enemy[i].y = 260; enemy[i].gamecount_point = gamecount; enemy[i].init_flag = 1; } else{ /*移動部分*/ }
中央上部らへんから出現するのでとりあえず初期位置は(0,260)としました。
あとで計算で補正されるのでだいたいの位置で大丈夫だと思います。
if (gamecount < enemy[i].gamecount_point + 50){ enemy[i].x = enemy[i].x + 2; enemy[i].y = 6000 / enemy[i].x; } if (gamecount > enemy[i].gamecount_point + 110){ enemy[i].x = enemy[i].x + 2; enemy[i].y = 6000 / enemy[i].x; }
あとは先ほどの計算に当てはめるだけですね。
今回曲線を描く「a」の値は「6000」としました。
この「a」の部分を変えれば曲線が大回りになったり小回りになったりします。
「enemy[i].y = 3000 / enemy[i].x;」の場合
「enemy[i].y = 30000 / enemy[i].x;」の場合
これ以上でもこれ以下でもちょっと動きとしては使えなさそうなので「3000~30000」の間ぐらいが良さそうです。
あと「y = a / x」みたいなダイレクトな除算を行う計算では「0」で除算して思わぬエラーを引き起こす事があるので、そうなりそうな場合は避けるようなエラー対策が必要です。
最後は2次関数というものです。
ちょっと上の書き方では誤解しそうなのでプログラム的に書くと
y = a * (x * x);
このようになります。
「x」を2回かけるトコロがポイントですね。
動きを見てみましょう。
放物線というものですね。物を遠くに投げた時のような動きです。
ではプログラムを見てみましょう!
「my_move_enemy()」の「case 7」になります。
if (enemy[i].init_flag == 0){ enemy[i].x = -155; enemy[i].y = 260; enemy[i].gamecount_point = gamecount; enemy[i].init_flag = 1; } else{ /*移動部分*/ }
初期座標は(-155,260)としました。
こちらもだいたいでいいと思います。
if (gamecount < enemy[i].gamecount_point + 90){ enemy[i].x++; enemy[i].y = 0.01 * (enemy[i].x * enemy[i].x); } if (gamecount > enemy[i].gamecount_point + 200){ enemy[i].x++; enemy[i].y = 0.01 * (enemy[i].x * enemy[i].x); }
あとは先ほどの計算に当てはめるだけですね。
今回「a」の値は「0.01」としました。
他の「a」の値はと言いますと
「enemy[i].y = 0.002 * (enemy[i].x * enemy[i].x);」の場合
「enemy[i].y = 0.2 * (enemy[i].x * enemy[i].x);」の場合
「0.002~0.2」ぐらいの間が調度良さそうです!
今回はこのぐらいにして後半さらにいろいろな動きを追加していきたいと思います。
色々な動きをします!
ここまでの中間ソースになります。
次回は敵ショットの種類を追加したいと思います。
広告
↓発売日:2016年02月29日↓
12歳からはじめる ゼロからのC言語 ゲームプログラミング教室 新品価格 |
↓発売日:2018年06月22日↓
新品価格 |
↓発売日:2018年03月09日↓
新品価格 |
↓発売日:2017年06月14日↓
新品価格 |
↓発売日:2018年05月21日↓
新品価格 |
↓発売日:2017年12月07日↓
新品価格 |
↓発売日:2017年02月08日↓
新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ) 新品価格 |
↓発売日:2017年09月26日↓
新品価格 |