駅名だけのオープンワールド
次のプログラムを実行すると駅名だけの日本を散歩することができます。
// 駅名だけのオープンワールド
// プログラミング言語「ドリトル」
// V3.31以降のインストール版ドリトルで実行してください。
// 2020.06.16 蕪木 孝
// ******************** スタート地点の郵便番号 ********************
郵便番号 = "1000005"。 // ←自由に変更してください
// ********************************************************
// -------------------- 設定値 --------------------
一度の距離 = 110.94297。 // km。緯度経度の1度分の距離。
画角 = 110。 // 度。ウインドウの左端から右端までの視野。
駅一文字の幅 = 0.05。 // km。オープンワールド上での駅名一文字の幅。
最大文字サイズ = 240。 // これ以上大きくすると表示がおかしくなる。
最小文字サイズ = 3。 // どんなに遠い駅でもこのサイズで表示される。
進む距離 = 0.01。 // km。前進、後進ボタンで一度に進む距離。
回る角度 = 15。 // 度。左旋回、右旋回ボタンで一度に回る角度。
方角 = 90。 // 自分が向いている方角。初期値は北の90度。
// 東が0度、北が90度、西が180度、南が-90度。
画面の幅 = 画面 ! 幅?。 // ウインドウの幅。
画面の高さ = 画面 ! 高さ?。 // ウインドウの高さ。
// メッセージを表示するためのラベル
ラベル1文字サイズ = 24。
ラベル1y = 150。 // ラベル1のy座標
ラベル1 = ラベル ! 作る (ラベル1文字サイズ) 文字サイズ。
ラベル1表示中 = はい。
駅一覧 = 配列 ! 作る。 // 取得した最寄り駅を保存するための配列
// -------------------- 自分が向いている方角を示す矢印(線)を描く --------------------
カメ = タートル ! 作る。
矢印 = カメ ! 0 80 移動 図形を作る。
矢印 ! (画面の幅 / 2 - 100) (画面の高さ / 2 - 100) 位置。
カメ ! 消える。
// -------------------- ブロックを作る (ブロックは機能のかたまり) --------------------
// 機能 : JSONデータから引数「key」で指定した値を読む
// 引数 : data : JSONデータ
// key : 読む値を指定するキー
// 戻り値 : 読んだ値
値を読む = 「
| data key ; p len n |
p = data ! (key) 何文字目?。
p = p + (key ! 長さ?) + 1。
len = data ! 長さ?。
n = 0。
// ダブルクオテーションの手前の文字までが値
「ぜんぶ ! ((data ! (p + n) 1 部分) != dq) ((p + n) <= len) 本当」 ! の間 「
n = n + 1。
」 実行。
data ! (p) (n) 部分。
」。
// 機能 : 緯度経度から最寄り駅を取得して駅一覧に追加する
// 引数 : 緯度 : 現在位置の緯度
// 経度 : 現在位置の経度
// 戻り値 : 無し
最寄り駅 = 「
| 緯度 経度 ; w ret str 駅名 a 駅緯度 駅経度 駅数 i 追記済駅 |
w = webapi ! 作る。
w : url = "http://express.heartrails.com/api/json"。
w : method = "getStations"。
w : y = 緯度。
w : x = 経度。
ret = w ! 読む。
str = ""。
str = str + ret。
駅名 = 値を読む ! (str) " name:" 実行。
a = "最寄り駅は「" + 駅名 + "」"。
ラベル1 ! (a) 書く。
ラベル1 ! ((a ! 長さ?) * ラベル1文字サイズ / 2 * (-1)) (:ラベル1y) 位置。
駅数 = (:駅一覧 ! 要素数?) / 3。
i = 0。
「i <= 駅数」 ! の間 「
「i < 駅数」 ! なら 「
追加済駅 = :駅一覧 ! (i * 3 + 1) 読む。
「駅名 == 追加済駅」 ! なら 「i = 駅数」 実行。
」
そうでなければ 「
// 新しい最寄り駅なので駅一覧に追加する
:駅一覧 ! (駅名) 書く。
駅緯度 = 値を読む ! (str) " y:" 実行。
:駅一覧 ! (駅緯度) 書く。
駅経度 = 値を読む ! (str) " x:" 実行。
:駅一覧 ! (駅経度) 書く。
a = "駅ラベル" + (駅数 + 1) + " = ラベル ! 作る。"。
a ! 実行。
」 実行。
i = i + 1。
」 実行。
」。
// 機能 : 画角内の駅を表示する
// 引数 : 無し
// 戻り値 : 無し
駅表示 = 「
| ; 駅数 駅名 駅緯度 駅経度 y x d 駅方角 len 円周 円弧 s 角度 x座標 y座標 幅 高さ a |
駅数 = (:駅一覧 ! 要素数?) / 3。
「
| i |
駅名 = :駅一覧 ! ((i - 1) * 3 + 1) 読む。
駅緯度 = :駅一覧 ! ((i - 1) * 3 + 2) 読む。
駅経度 = :駅一覧 ! ((i - 1) * 3 + 3) 読む。
// 現在地から駅までの距離を計算する
y = 駅緯度 - :緯度。
x = 駅経度 - :経度。
d = sqrt((y ! 2 pow) + (x ! 2 pow)) * :一度の距離。 // km
// 現在地から駅への方角を計算する
駅方角 = x!(y) atan2。 // 東が0度、北が90度、西が180度、南が-90度
// 駅名の文字サイズを計算する
円周 = d * 2 * 3.14159。 // km
円弧 = 円周 * :画角 / 360。 // km
s = round(:画面の幅 * :駅一文字の幅 / 円弧)。
「s > :最大文字サイズ」 ! なら 「
s = :最大文字サイズ。
」
そうでなければ 「s < :最小文字サイズ」 なら 「
s = :最小文字サイズ。
」 実行。
// 自分が向いている方角から駅への角度を計算する
// 自分の真正面が0度。左方向がプラス、右方向がマイナスの角度
角度 = 駅方角 - :方角。
「角度 > 180」 ! なら 「角度 = 角度 - 360」
そうでなければ 「角度 < (-180)」 なら 「角度 = 角度 + 360」 実行。
// 駅が画角内なら表示する
「ぜんぶ ! (角度 >= (:画角 / 2 * (-1))) (角度 <= (:画角 / 2)) 本当」 ! なら 「
len = (駅名 ! 長さ?)。
x座標 = round((角度 * (-1) * :画面の幅 / :画角) - (s * len / 2))。
y座標 = s / 2。
幅 = s * len。
高さ = s。
a = "駅ラベル" + i + " ! 現れる。"。 a ! 実行。
a = "駅ラベル" + i + " ! " + 幅 + " " + 高さ + " 大きさ。"。 a ! 実行。
a = "駅ラベル" + i + " ! " + s + " 文字サイズ。"。 a ! 実行。
a = "駅ラベル" + i + " ! " + x座標 + " " + y座標 + " 位置。"。 a ! 実行。
a = "駅ラベル" + i + " ! " + dq + 駅名 + dq + " 書く。"。 a ! 実行。
」
そうでなければ 「
a = "駅ラベル" + i + " ! 消える。"。 a ! 実行。
」 実行。
」 ! (駅数) 繰り返す。
」。
// -------------------- メイン --------------------
// スタート地点の郵便番号の緯度経度を調べる
w = webapi ! 作る。
w : url = "http://geoapi.heartrails.com/api/json"。
w : method = "searchByPostal"。
w : postal = 郵便番号。
ret = w ! 読む。
str = ""。
str = str + ret。
緯度 = 値を読む ! (str) " y:" 実行。 // スタート地点の緯度
経度 = 値を読む ! (str) " x:" 実行。 // スタート地点の経度
最寄り駅 ! (緯度) (経度) 実行。 // スタート地点の最寄り駅を取得
駅表示 ! 実行。
// -------------------- キーボード操作の設定 --------------------
排他フラグ = 0。 // キー長押しで発生するプログラムダウンの対策用
// (それでもたまにダウンするが)
最寄り駅取得ボタン = ボタン ! "" "ENTER" 作る 消える。
最寄り駅取得ボタン : 動作 =
「
「:排他フラグ == 0」 ! なら 「
:排他フラグ = 1。
最寄り駅 ! (:緯度) (:経度) 実行。
駅表示 ! 実行。
ラベル1 ! 現れる。
:ラベル1表示中 = はい。
:排他フラグ = 0。
」 実行。
」。
前進ボタン = ボタン ! "" "UP" 作る 消える。
前進ボタン : 動作 =
「
「:排他フラグ == 0」 ! なら 「
:排他フラグ = 1。
:緯度 = :緯度 + 1 / :一度の距離 * :進む距離 * sin (:方角)。
:経度 = :経度 + 1 / :一度の距離 * :進む距離 * cos(:方角)。
駅表示 ! 実行。
「:ラベル1表示中 == はい」 ! ならば 「
ラベル1 ! 消える。
:ラベル表示中 = いいえ。
」 実行。
:排他フラグ = 0。
」 実行。
」。
後進ボタン = ボタン ! "" "DOWN" 作る 消える。
後進ボタン : 動作 =
「
「:排他フラグ == 0」 ! なら 「
:排他フラグ = 1。
:緯度 = :緯度 - 1 / :一度の距離 * :進む距離 * sin (:方角)。
:経度 = :経度 - 1 / :一度の距離 * :進む距離 * cos(:方角)。
駅表示 ! 実行。
「:ラベル1表示中 == はい」 ! ならば 「
ラベル1 ! 消える。
:ラベル表示中 = いいえ。
」 実行。
:排他フラグ = 0。
」 実行。
」。
右旋回ボタン = ボタン ! "" "RIGHT" 作る 消える。
右旋回ボタン : 動作 =
「
「:排他フラグ == 0」 ! なら 「
:排他フラグ = 1。
:方角 = :方角 - :回る角度。
「:方角 == (-180)」 ! なら 「:方角 = 180」 実行。
駅表示 ! 実行。
矢印 ! (:回る角度) 右回り。
「:ラベル1表示中 == はい」 ! ならば 「
ラベル1 ! 消える。
:ラベル表示中 = いいえ。
」 実行。
:排他フラグ = 0。
」 実行。
」。
左旋回ボタン = ボタン ! "" "LEFT" 作る 消える。
左旋回ボタン : 動作 =
「
「:排他フラグ == 0」 ! なら 「
:排他フラグ = 1。
:方角 = :方角 + :回る角度。
「:方角 == (180 + :回る角度)」 ! なら 「:方角 = (-180 + :回る角度)」 実行。
駅表示 ! 実行。
矢印 ! (:回る角度) 左回り。
「:ラベル1表示中 == はい」 ! ならば 「
ラベル1 ! 消える。
:ラベル表示中 = いいえ。
」 実行。
:排他フラグ = 0。
」 実行。
」。
実行方法
これは教育用プログラミング言語「ドリトル」で書いたプログラムです。
インストール版ドリトルを以下のサイトからダウンロードしてください。
https://dolittle.eplang.jp/download
パソコンのOSがWindowsなら「Windows用」をクリックするとダウンロードがはじまります。
ダウンロードしたら解凍してください。
解凍したら dolittle.bat をダブルクリックするとドリトルが起動します。
プログラムを貼り付けて「実行!」をクリックすると画面が表示されます。
操作方法
「↑」「↓」キーで前進、後進します。
「←」「→」キーで左旋回、右旋回します。
Enterキーで現在地の最寄り駅を表示します。
プログラムを実行したときの位置は東京駅の目の前です。
プログラム実行前にプログラム先頭の郵便番号を書き換えることでスタート地点を変更できます。
エラーになって実行できない場合
このプログラムはインターネット経由で駅の情報を取得するためにWeb APIというものを使っています。
エラーになって実行できない場合の調査については同じようにWeb APIを使っている次の記事の「緯度、経度、乗組員数が表示されない場合」を参照してください。
操作のコツ
見つけた最寄り駅を視野に入れた状態で後進すると移動しやすいです。
東京駅スタートで鎌倉まで行ってみましたが迷わず行けました。
土地勘があれば行きたい場所へ行けるようです。
このプログラムは株式会社ハートレイルズが提供する次のWeb APIを使用しています。
緯度経度から最寄り駅を取得するために使用したWeb API
http://express.heartrails.com/api.html
郵便番号から緯度経度を取得するたに使用したWeb API
http://geoapi.heartrails.com/api.html
この記事が気に入ったらサポートをしてみませんか?