HOPTER TECH SCHOOL 自分が3年間活動してきた事の振り返り
皆様こんにちは、HOPTER TECH SCHOOL 3年のりっくんです。
今回は自分がHOPTERに入ってから3年間の活動を作品を通して振り返っていきたいと思います。
1年生 | 2022年
なったーホン
なったーホンは自分が1年生で最初に作った作品で「たのしいmicro:bitコンテスト2022」に応募するための制作物である。
概要としては以下の通り
アイデアは最初中々出てこなくて苦戦したけど、もうそろそろ授業の時間が終わる頃に、「そういえば自宅の2階のインターホンが押された時に音を出すやつが壊れてたよな、だから親が2階にいる時にインターホンが押されても気づかないことがあるよな」という問題を思い出してから、いい感じに進んだ記憶がある。
(悩みを出す段階とアイデアスケッチを発表する段階の記憶が混在して曖昧になっているため「いい感じに進んだ」としか言えない)
制作中は、当時2年生のO先輩にサポートしてもらいながら制作した。
サポート具合としては、自分がサポートに入った「びっくらべる」のサポートと比べて、手厚めにサポートしてもらった印象がある。
自分から質問しなくても、「〇〇はこうだよ」みたいな感じで進んで教えてくれた感じがした。
作品が完成した後は、応募するために作品の映像を制作して、 𝕏 (旧Twitter) に投稿する必要があるため、動画の撮影と編集を行った。
撮影場所は、自宅で当時研究生のS先輩が撮影を担当して、O先輩がサポート及び演者、自分も演者を担当する感じでの撮影となった。
流れとしては、自分が撮影前に書いた絵コンテ通りに進めた。絵コンテには1コマずつに絵とそれを説明した文章があり、その絵コンテ通り撮影できる場所を探すために家の中を行ったり来たりしていた。場所が決まると絵コンテ通りに移動したり喋ったりする、同じシーンを繰り返し4~5回程度撮る、終わったら次の撮影できる場所を探す(移動する)感じだった。
応募の結果は自身のgmailにて伝えられた。hopterから帰って家に帰宅して、gmailを開くと1次審査通過のお知らせとの文字が件名に入っているメールがとどいていた、当時の心境としては「えっ!?、通過できちゃった!?」みたいな感じだったと思う。
1次審査通過を通過すると「Maker Faire Tokyo 2022」会場内の展示スペースに作品を展示することができる権利と、決勝大会への出場権が得られる。その決勝大会では3つの賞があり、特別表、優秀賞、グランプリ、その中でグランプリを目指すために作品のプレゼンテーションを行う。
プレゼンテーションを行うためには資料が必要なため、その作成をニチビのOBであるA先輩のサポートを受けながら制作した。
制作している中で同じルールで文字などを配置させる「反復」が大事な事や、人の視線はZのように動くことなどを教わった記憶があり、それが今後2年生で制作したポートフォリオや、hopterで行うインフォグラフィックスの授業などにいかされていくのであった。
コードは以下の通り
送信側は作品の映像において、自宅のインターホンに引っ掛けていた部分であり、中に入っているmicro:bitがインターホンのディスプレイの光を検知する。検知した光の明るさが、変数「明るさを判断する」の値である10より多い場合に送信側に無線で通信を行う。
変数「もう送らなくていいか判断する」は無線で通信した後にずっとブロックの中で実行しているため送り続けてしまうのを防止するためであり、送った後に別の値をその代入することにより防止している。
受信側は作品の映像において、自宅の寝室に置かれていた物であり、無線で受信すると、LEDが緑色に光ってピンポーンと音が鳴る。
パームレストレッチ
パームレストレッチは1年生の後期期末課題に作った作品であり、テーマは「友達の課題解決」であった。
概要は以下の通り
アイデアは石郷先生と同学年のKくんと自分で話あっていた時に同学年のKくんが「パソコンで作業していると手首が痛くなる」と言っていた事から制作が始まった。
制作中、一番記憶に残っているのは、動画のシークバーを作っている時だと思う、理由は動画を再生している時にシークバーを動かすと動画がラグくなるというか再生されるまでにしばらく時間がかかる現象が起きていた。色々試していく中で、それを解決できるアイデアが浮かんできた、それはシークバーを触った時に動画の再生を止める処理を入れてから動かすようにするというもの、どういう事かと言うと、ラグい方では動画が再生している状態でシークバーを触る事によって、現在何秒地点を再生しているかを表す変数に値を入れる事によって値を変えていたが、再生中に値を変えている事が原因の可能性があるので、動画を止める処理を入れてから値を変えれば解決するのではないかということである。結果は成功、ジークバーを移動させる時に動画を止める処理を入れて、離す時に動画を再生させることにより、ラグくなく動画がすぐに再生されるようになったのであった。
作品が完成した後は、「進級・卒業制作展 HOPTER 2023」で作品を説明する。
作品を説明すること自体は「Ogaki Mini Maker Faire 2022」で説明していたため初めてではないが、慣れないものである、というのも作品を何回も説明すれば、ある程度何を言えばいいかわかってくるようになるので、頭の中に台本がある状態というかテンプレートが出来上がっていく感じなので、アドリブが必要な割合が減っていくのだけど、最初に説明するときは、その頭の中に台本がない状態、テンプレートが出来上っていないので、アドリブが必要な割合が多いので、言葉に詰まったり、適切な言葉が使えなかったりする。
もちろん、最初の時にも何を言うか頭の中で考えたり、台本みたいな物を書いたりしているが、いざ説明すると考えた事が吹っ飛ぶというか引き出せなくなるので結局、言葉に詰まったり、適切な言葉が使えなかったりする。
コードの解説だが、すべて解説すると文字数が大変なことになるので、「制作中、一番記憶に残っているのは」の部分のコードを解説していく。
コードは以下の通り
public class operation_reproducing_bar : MonoBehaviour
{
public Slider Slider;
public VideoPlayer VideoPlayer;
int Videolenght_minutes;
int Videolenght_seconds;
bool on_play_pa = false;
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
void Update()
{
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Slider.SetValueWithoutNotify((float)VideoPlayer.time);
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
public void Slider_operation(bool down) //つまみを動かすとSliderの値をVideoPlayer.timeに入力
{
if (down == true)
{
VideoPlayer.Pause(); //一旦止めてからスライダーを動かすことで処理を軽くする
VideoPlayer.time = Slider.value;
VideoPlayer.Play();
VideoPlayer.Pause();
}
else if(on_play_pa == false)
{
VideoPlayer.Play();
}
}
public void video_complete_up_to_time_get() //再生の準備が完了すると動画の長さをsliderのmasValueに設定
{
Slider.maxValue = (float)VideoPlayer.length;
Videolenght_minutes = (int)VideoPlayer.length / 60;
Videolenght_seconds = (int)VideoPlayer.length % 60;
Play_ok = true;
}
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
やっている事としてはSliderオブジェクト(画像下)に対して、マウスのドラッグ操作及びクリックをした際に、Slider_operation関数を呼んでいる感じで、引数にtrueを渡して呼ぶと、if文を通過してViderPlayer型の変数VideoPlayerに対して、VideoPlayer.Pause()で動画の再生を止めてから、VideoPlayer.time(動画の再生時間)の中にSlider.valueの値を入れている。
引数にfalseを渡して呼ぶと、else ifを通過した場合VideoPlayer.Play()で動画が再生されるが、これはクリック状態から離された時に変数 on_play_pa(一時停止しているかどうか)が falseの(していない)時に動画を再生させるためである。
Slider.valueの値はまず、動画が読み込まれて再生できる状態になったらvideo_complete_up_to_time_get関数を呼び出してSlider.maxValueの値の中に(float)VideoPlayer.length(動画の長さ)を入れてSliderの最大値を決める。その後にSlider.SetValueWithoutNotify((float)VideoPlayer.time)を呼び出すことによってVideoPlayer.time(動画の再生時間)の値をSlider.valueの値に同期させている。
こうする事により、動画が再生されるとVideoPlayer.time(動画の再生時間)と連動してSliderオブジェクト(画像下)がyoutubeのシークバーみたいに動いてくれる。
2年生 | 2023年
ここから先は文字通り自分が2年生のときに作った作品が並ぶのだが、今の時点で大体、4900文字くらいで、このまま1年生を振り返る勢いで書くと文字数が数万字に達しそうなので、作品の名前と概要と記憶に残っている事とコード解説を書いて行こうと思う。
バサバッサイ
バサバッサイは「日本ゲーム大賞2023」に応募するために制作した作品であり、当時3年生のE先輩との共同制作である、自分はコード、E先輩はデザインを担当した。
概要は以下の通り
制作中、一番記憶に残っているのは、E先輩に迷惑をかけてしまった事だろう、自分が立て続けにしてしまったミスが発端であり、それの対応も自己中極まりないひどい有様だった。
謝罪して、対策案を出して、それを厳守することを誓う。これをするしかないのに・・・。
こんな事をしてしまった原因はおそらくhopterに入る前の話、小中高の頃、特に小の頃で助けてもらうのが当たり前の環境で育ったものだと思う。それに慣れてしまっていたので、何か苦労や困難に直面した時に、助けを乞う・・・違うな、助けを命令することしかできなくなっていたと思う。だが、この制作中の経験により、助けてもらうのは当たり前ではなく、苦労や困難を乗り越えるのは自分でありそれは助けがあろうが無かろうが変わらないものである事を学んだと思う。
話はそれるが、お店とかでたまに見る迷惑客などは「困難を乗り越えるのは自分」と言う意識がなく、「困難を乗り越えるのはサポートしているお前」みたいな意識があるのかな?と記事を書いている中考えたりしていた。
コードの解説だが、当たり判定のロジックとコードを解説して行こうと思う。
下にバサバッサイの動画を貼った↓
バサバッサイにはチェンソーを振り回すしろけつ(Slackのスタンプではしろけつと言う名称)とスギ、ヒノキ、ブタクサ、イネの4つの植物と壁の役割を持つ岩がある。
当たり判定は画像下のように四角形の形で行われるのが前提である。
まず、上記画像にある青い4つの点の座標を求めるために以下の計算をする。
ScaleのXを-0.5倍、Yを0.5倍した値をしろけつの座標に加えた結果、左上の点が求められる。
ScaleのXを0.5倍、Yを0.5倍した値をしろけつの座標に加えた結果、右上の点が求められる。
ScaleのXを-0.5倍、Yを-0.5倍した値をしろけつの座標に加えた結果、左下の点が求められる。
ScaleのXを0.5倍、Yを-0.5倍した値をしろけつの座標に加えた結果、右下の点が求められる。
次にステージ上の植物や岩に対しても同じように計算をして4つの点の座標を求める。
次にif文を行い、しろけつの4つの点それぞれが、他の植物や岩の中に入っているか調べる。
collect.Countは変数collectと言うGameObject型のListである、配列みたいなもので中にステージ上の植物や岩のGameObjectが入っている、Countは中に入っている数を返してくれるものであり、for文でCountの数、植物や岩に一つずつif文で質問している。
if文に使われている変数を解説していくと、変数player_left_top_pなどplayerが付くものは、しろけつを表しており、後ろのleft_topは左上の点の座標を表している。
変数opponent_machine_left_top_pなどopponent_machineは、植物や岩を表しており、後ろのleft_topは、左上の点の座標を表している。
画像内一番上のif文を日本語に直すと以下の通り
植物や岩の左上X座標が、しろけつの左上X座標より小さいか同じ かつ
植物や岩の左上Y座標が、しろけつの左上Y座標より大きいか同じ かつ
植物や岩の左下X座標が、しろけつの左上X座標より小さいか同じ かつ
植物や岩の左下Y座標が、しろけつの左上Y座標より小さいか同じ かつ
植物や岩の右上X座標が、しろけつの左上X座標より大きいか同じ かつ
植物や岩の右上Y座標が、しろけつの左上Y座標より大きいか同じ かつ
植物や岩の右下X座標が、しろけつの左上X座標より大きいか同じ かつ
植物や岩の右下Y座標が、しろけつの左上Y座標より小さいか同じ
これら8つの条件を満たせば、しろけつの左上の点の座標が植物や岩に入っていると言える。
残りの左下、右上、右下の点の座標も、同じような流れで調べる。
画像のコードを見てみると、変数bury_0と変数bury_num_0があるが、これは8つの条件を満たした時に、bury_0の方はtrueを代入するための変数であり、bury_num_0は、for文のiを代入するための変数である。
変数の後ろの数字は、0が左上、1が左下、2が右上、3が右下を表している。
例えば、bury_0とbury_2にtrueが代入されていた場合は、しろけつの左上の点の座標としろけつの右上の点の座標が植物や岩に入っているという状態を表せるため、if (bury[0] && bury[2]) みたいな感じでif文かいてその中に上方向に移動しないようにするコードを書けば、当たり判定の実装をすることができる。ただ、bury_0だけにtrueが代入されていた場合は、しろけつの左上の点の座標だけが植物や岩に入っているという状態を表わせるが、この場合、植物や岩の右辺からしろけつの左上の点の座標が入っていた場合と下辺から入っていた場合が考えられる、下辺の場合上方向に移動しないようにする必要があり、右辺の場合左方向に移動しないようにする必要があるので、if文で分岐する
植物や岩の右下の点のX座標 - しろけつの左上の点のX座標 の差
植物や岩の右下の点のY座標 - しろけつの左上の点のY座標 の差
これらを絶対値にしてif文で比較をする。(画像上記参照)
Xの絶対値が多い場合は上方向に移動しないようにするコードを書く。
Yの絶対値が多い場合は左方向に移動しないようにするコードを書く。
こんな感じで当たり判定を実装していた。
・・・書いてて思ったけど、自分のコードは「if (bury[0] && bury[2]) 」と上記の絶対値のコード両方書いているけど、絶対値のコードだけでもおそらく動作すると思った。当時はデバッグして動いていたので両方書いたままにしていた。
はぶらしゅーと
はぶらしゅーとは2年生の前期期末課題に作った作品であり、テーマは「〇〇に1度しか使わないアプリ / デバイス」であった。
概要は以下の通り
制作中、特に記憶に残っているのは、基盤作業と当時2年のKくんと池田温泉に行った事だと思う。
基盤作業では、当時、垂井にあったhopterで夜な夜な3〜4泊しながら作業していて、今回の作品には2桁の7セグやRTCモジュール、ステッピングモーターを使用していたため、はんだ付けする箇所が多く時間が掛かった。
筐体も2~3回程度切り直した、最初は学内展示7セグの配置を修正するために一回、次は切り終わった後にフィンガーの部分が間違っていたので、時間内に修正して切ったが、切り終わった後によく確認すると1~1.5mm程度出っ張っている感じになったので二回、それが前期期末課題の2日前くらいだったと思う。何度も行くことになったので、ちょっと金がとんでしまった。
池田温泉では、あまり覚えていないが、Kくんが風呂に入りたいので行くみたいな事を言っていて、自分は行ったことが無いので行ってみることにした。Kくんはもともとhopterに車で通っていたため、池田温泉にも車で向かった、山奥やトンネル辺りを結構飛ばして走行していた。
到着した後はロッカーに着ている服を入れて入る、今までの制作の疲れを流すようにシャワーを浴び、ゆっくりとあったかい温泉に浸かっていくのだった。
入浴後は、服を着替えた後ロビーに出る、そこで記念飲むヨーグルトを買った。美味かったと思うけど、もう覚えていない、元気はもらったと思う。
hopterに帰宅した後は、期末課題のアプリの方であるtime撮るのコードを書いて行くのであった。
コード解説は、端折りたいのでうるう年の処理に関するコードを解説していく。
はぶらしゅーとは、概要を見ると一定の時間が経過すると自動で交換するみたいな事が書かれているが、その時間は1ヶ月である。ただ、一ヶ月は、月によって30〜31日間の場合があったり、2月の時はうるう年の関係で28〜29日間の場合があるのでそれを考慮した処理を書く必要がある。
そのコードは以下の通り
const int february_leap_year_date = 29;
const int date_normal_february = 28;
int january_days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
void leap_year_decision()
{
if(now_what_month == 2 && now_year % 4 == 0) //2月だった場合、かつ、年数を4で割って割り切れるか、満たしていれば閏年の可能性が高い
{
if(now_year % 100 == 0 && now_year % 400 != 0) //西暦年が100で割り切れるが400では割り切れない年の場合、閏年ではない
{
january_days[1] = date_normal_february;
}
else //閏年の場合
{
january_days[1] = february_leap_year_date;
}
}
else //普通の年の場合
{
january_days[1] = date_normal_february;
}
}
変数の説明をする。
変数february_leap_year_dateは2月のうるう年が発生した場合の1ヶ月の日数を表す。
変数date_normal_februaryは2月のうるう年ではない場合の1ヶ月の日数を表す。
変数january_daysは各月の1ヶ月の日数が入っている。
変数january_daysの値をif文に活用することにより歯ブラシを交換しているだがそれだと、うるう年の場合など日数に変化がある場合だと、対応できないため、関数leap_year_decision()を呼んでうるう年の場合、変数january_daysの2月を表す場所に変数february_leap_year_dateの値を代入して対応している。
ちなみにうるう年が発生する周期は4年であるが、例外がある、それは、年数を100で割り切れるが400で割り切れない時である、この場合はうるう年ではない(平年)なので上記のコードで例外かどうかもif文で判断している。
time撮る
memolink
ヘキサイト
隠ストレージ
3年生 | 2024年
おうちに帰ロワイヤル
おうちに帰ロワイヤルは「TechSeeker Hackathon 2024(テックシーカー ハッカソン)」で制作した作品であり、メンバーは、A先輩、E先輩、Iさん、自分の4名で制作した。
会場は大阪のATC特設会場(ITM棟2F、10F )であった。
概要は以下の通り
制作中、記憶に残っているのは、色々大変だったことだと思う、自分はSpresenseというマイコンのコードを担当したが、ハッカソンが始まってから1週間程度、もらったSpresenseが不良で書き込みができなかったのがしんどかった、作品制作が1週間ぶっ飛ぶと後々苦しむ事になるのだが、まさにそれが当たる事となった。
特に6月後半〜7月7日(展示日)まで特にしんどく、3~4泊して自宅に帰宅する日々を繰り返していた。
本当は泊まらずに自宅に毎日帰宅するのがベストではあるが、ゾーンの収縮を表示させるデモ(スマホから自宅を設定すると、仮で設定した現在地が自宅にランダムな速度で向かっていく)の実装に特に苦戦しており、「自宅に泊まらずに帰ってしまったり、長く寝てしまったら間に間に合わない」という
考えが自分の中にあったためであった。
今回のハッカソンでは展示が終わった後にプレゼンがあり、全チームのプレゼンが終わった後にどのチームが受賞したか発表があるが結構ドキドキしていた、と言うのもSpresense賞は一番最後?辺りの発表であり、他の賞では名前が呼ばれていない状況、このまま名前が呼ばれなかったら、受賞できなかったことになってしまうので、呼ばれたときにはまず最初に安心感、次には達成感があった。受賞した後ずっとニヤけていた。
もう一つ記憶に残っているのは、7月6日〜7月7日の間で夜、飲食店に入って飲んだ時やE先輩とI先生と薬局とか買い物に着いていった時、泣きそうになっていたのを覚えている、理由はわからないけど、涙腺がうるうるして我慢する、涙腺がうるうるして我慢する、を結構繰り返してた気がする。7月7日の夜、受賞した後の打ち上げでお好み焼きを食べたと思うがその時もうるうるしていた、何なら少し出てたかもしれないので、バレていたかも。
その後家に帰宅した後、youtubeでいろんな音楽聞いてまわってたら「はいよろこんで / こっちのけんと MV」が出てきたので聞いていたが、そこで涙が溢れ出ていた。歌詞の意味はそこまで理解していなかったと思うが。疲れてたんだろうなーと思う。
コード解説は、苦戦した所の一つである、現在地を動かす関数を解説していく。
コードは以下の通り。
double currentLocationStartPointALat; //範囲収縮が始まった直後の緯度現在地点を入れる
double currentLocationStartPointALng; //範囲収縮が始まった直後の経度現在地点を入れる
double moveSpeedPeroneSeconds; //展示で使う1秒当たりの座標移動量
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
double currentLocationMove(double currentLocationALat_, double currentLocationALng_,
double registrationPointBLat_, double registrationPointBLng_, bool oncePassingCurrentLocationMoveBool_) //展示で現在地を動かす関数 日本専用 boolでゲームが終了したらまた通過できるようにする
{ //展示で現在地を動かす関数 日本専用 boolでゲームが終了したらまた通過できるようにする
//緯度 いど latitude ←短い
//経度 けいど longitude ←長い
//緯度の値は -90 ~ 90 です。0 は赤道を示します。
//経度の値は -180 ~ 180 です。0 は子午線です。
//currentLocationALat currentLocationALng 現在地
//registrationPointBLat, registrationPointBLng 登録地点
//現在地が過去で登録地点が未来
double movingDistanceLatitude; //移動距離緯度 いどうきょりいど
double movingDistanceLongitude; //移動距離経度 いどうきょりけいど
double moveSpeedLatitude; //1秒当たりの緯度の移動量
double moveSpeedLongitude; //1秒当たりの経度の移動量
①
if (oncePassingCurrentLocationMoveBool_ == true) //roopで連続で実行しないようにする
{
oncePassingCurrentLocationMoveBool = false;
randomNum = random(70, 131) / (double)100; //movingDistanceにかけて動く量をランダムにする
currentLocationStartPointALat = currentLocationALat_; //範囲収縮が始まった直後の緯度現在地点を入れる
currentLocationStartPointALng = currentLocationALng_; //範囲収縮が始まった直後の経度現在地点を入れる
}
②
double DistanceKmCurrentLocationMove = twoPointDistance(currentLocationALat_, currentLocationALng_, registrationPointBLat_, registrationPointBLng_); //現在地と登録地点の距離を算出
③
movingDistanceLatitude = registrationPointBLat_ - currentLocationStartPointALat; //登録地点と範囲収縮が始まった直後の緯度現在地点との差
movingDistanceLongitude = registrationPointBLng_ - currentLocationStartPointALng; //登録地点と範囲収縮が始まった直後の経度現在地点との差
④
//1秒当たりのスピード == randomNum * 移動距離 / 何秒間収縮しつづけるか
moveSpeedLatitude = randomNum * (movingDistanceLatitude / moveSpeedPeroneSeconds);
moveSpeedLongitude = randomNum * (movingDistanceLongitude / moveSpeedPeroneSeconds);
⑤
//緯度を動かす
currentLocationALat = currentLocationStartPointALat + moveSpeedLatitude * elapsedTime_C;
//経度を動かす
currentLocationALng = currentLocationStartPointALng + moveSpeedLongitude * elapsedTime_C;
⑥
currentLocationStartPointALatAfterwards = currentLocationStartPointALat; //ゾーンが収縮し終わった時に動かした座標が家にたどりついていない場合はこれを使って動かす
currentLocationStartPointALngAfterwards = currentLocationStartPointALng;
moveSpeedLatitudeAfterwards = moveSpeedLatitude;
moveSpeedLongitudeAfterwards = moveSpeedLongitude;
elapsedTime_CAfterwards = elapsedTime_C;
⑦
DistanceKmCurrentLocationMove = twoPointDistance(currentLocationALat, currentLocationALng, registrationPointBLat_, registrationPointBLng_); //現在地と登録地点の距離を算出
return DistanceKmCurrentLocationMove;
}
まず、関数currentLocationMoveの引数を説明する。
currentLocationALat_は現在地の緯度を表す。
currentLocationALng_は現在地の経度を表す。
registrationPointBLat_は登録地点、つまり自宅の緯度を表す。
registrationPointBLng_は登録地点、つまり自宅の経度を表す。
oncePassingCurrentLocationMoveBool_はroopで一回だけ処理を実行させるため使用する。oncePassingCurrentLocationMoveBoolをこの引数にいれる。trueが初期値。
次に関数内で定義されている変数を説明する。
movingDistanceLatitudeは登録地点の緯度とゾーンの収縮が始まった時の現在地の緯度の差を表す。
movingDistanceLongitudeは登録地点の経度とゾーンの収縮が始まった時の現在地の経度の差を表す。
moveSpeedLatitudeは1秒当たりの現在地の緯度が移動するスピードを表す。
moveSpeedLongitudeは1秒当たりの現在地の経度が移動するスピードを表す。
moveSpeedPeroneSecondsは何秒間ゾーンを収縮させるかを表す。上記のコードにはそれを求めるコードは書いていない。
次に関数外で定義されているグローバル変数を説明する。
currentLocationALatは現在の緯度を表す。
currentLocationALngは現在の経度を表す。
DistanceKmCurrentLocationMoveは現在地から登録地点までの直線距離を表す。後々別のコードでゾーンの範囲内かどうか、家に到着したかどうかを判定するために使われる。
elapsedTime_Cはゾーンが収縮してからの経過時間を表す。
currentLocationStartPointALatはゾーンの収縮が始まった時の現在地の緯度を表す。
currentLocationStartPointALngはゾーンの収縮が始まった時の現在地の経度を表す。
流れは以下の通り、丸で番号が書かれているがそれは「コードは以下の通り」の下に書かれているコードの番号と対応しているので、どこを説明しているのかがわかる様になっている。
① oncePassingCurrentLocationMoveBool_をif文でtrueかどうか質問する。trueならoncePassingCurrentLocationMoveBoolにfalseを入れて連続で呼び出されないようにする。その後randomNumにランダムな70~131の値を100で割った値を代入している。movingDistanceLatitudeとmovingDistanceLongitudeの値もここで代入されている。
② 関数twoPointDistance()を呼び出す事によって現在地から登録地点までの直線距離を求め、DistanceKmCurrentLocationMoveに値を入れている。
③ movingDistanceLatitudeにregistrationPointBLat_とcurrentLocationStartPointALatの差を代入し、movingDistanceLongitudeにregistrationPointBLng_とmoveSpeedPeroneSecondsの差を代入している。
これをすることによりゾーン収縮が始まってから終わるまでにどのくらい緯度と経度の値が変わるかがわかる。
④ moveSpeedLatitudeに一秒あたりに移動する緯度を、moveSpeedLongitudeに一秒あたりに移動する経度を代入していく。
一秒あたりに移動する緯度は下の式で求められる。
movingDistanceLatitude ÷ moveSpeedPeroneSeconds × randomNum
式の結果がmoveSpeedLatitudeに代入される。
一秒あたりに移動する経度は下の式で求められる。
movingDistanceLongitude ÷ moveSpeedPeroneSeconds × randomNum
式の結果がmoveSpeedLongitudeに代入される。
⑤ currentLocationALatに現在の緯度を、currentLocationALngに現在の経度を代入する。
現在の緯度は以下の式で求められる
currentLocationStartPointALat + moveSpeedLatitude × elapsedTime_C
式の結果がcurrentLocationALatに代入される。
現在の経度は以下の式で求められる
currentLocationStartPointALng + moveSpeedLongitude × elapsedTime_C
式の結果がcurrentLocationALngに代入される。
⑥ このコードたちは、関数currentLocationMove()が、デモでゾーン収縮が終了した以降呼ばれないので、呼ばなくても移動できるように別の変数に代入しているコードである。
その別の変数を利用して別の場所で⑤のような処理をしている。
⑦ ②とほぼ一緒、違いは⑤を実行した後に②を実行している事。⑦だけでもいいかもしれない。
反省点は、関数の中で関数を呼んだり、その関数の中のネストが深くなってしまったせいでデバッグが難しくなってしまった。
値をグローバル変数でいろんな場所から入れたりしている所があるのも原因だと思われる。
そこの所改善していきたい。
びっくらべる
その他
かず〜っとタッチ
最後に
今回は3年間の自分のhopterで作った作品の思い出とそれのコードを解説してみた。かけていない部分があると思うが、それはまた後日時間があり次第書いていきたいと思う。ここまで呼んでくださりありがとうございました。