BVE Trainsim5のシナリオ(路線や車両)をつくるには
寄稿者:わっきー
ごあいさつ
こんにちは、Like A Lakeサーバー所有者のわっきーです。
BVE Trainsimまわりでは主に京阪電車シナリオの作者として認識されてるっぽいです。
しかし最近は、サイトの管理は丸投げだし、人のたくさん集まるところには相変わらずめんどくさがって行かないし、そもそもメタバースなる全然別分野での創作に浮気している散々な状況だし、総じてBVEを遊び始めてから24年経つのに9割以上浮気しておりBVEを語るのは大変おそれ多いんですが
【「今あるもの」「今残っているもの」を活用して新しい価値あるものをつくる】という営みがここ最近トレンドになっているな、
と感じておりまして、たまの遊びでさわったのをきっかけに思い出してこの筆をとっております。
「BVEで遊んでいて楽しいと思い、自分の作品を作りたいが何をしたらいいのかわからない」「作品が永遠に完成しない」「設計図は頭の中にあるけどどうやって形にしたらいいか雲をつかむようで途方に暮れている」「雲をつかむよう、というか思いっきり雲をつかんだかのようにプロジェクトが自然消滅した」といった辛酸をなめてきた方々が歩みを進めて理想を現実にする一助となれば幸いです。
1.そもそも「BVE Trainsim5のシナリオ」の実体は具体的に何か?
BVE Trainsim基本ソフトウェアがシナリオファイルを読んでごちょごちょ動く、その読む部分です(禅問答みたいですみません)。
しばらく読むのがしんどいところが続きますがご容赦ください。
シナリオファイル
BveTs Scenario 2.00:utf-8
Title = 休B1201A(201X.9) Ver.0.3.15
Author = wackey
Route = wackey.KeihanMainLine\Operations\B1201A\MapRoot_holiday.010101.txt
RouteTitle = 京阪本線・鴨東線
Vehicle = wackey.Keihan_Vehicle\Keihan8000_1989\Keihan8051_B1201A.txt
VehicleTitle = 京阪8000系(1989-,8両)
Image = wackey.KeihanMainLine\Operations\B1201A\scenario_BA_8000.JPG
Comment = 区間:出町柳-樟葉,最高運転速度110km/h,京阪式ATS(初代)
呪文の意味はだいたい以下のようになります。
基本ソフトウェア上での表示これにして、マップロードして、車両ロードして
マップ(シナリオファイルから呼び出される)の例
BveTs Map 2.01
Structure.Load('Structures_dev.txt');
Sound.Load('Sounds.txt');
Sound3D.Load('Sounds3d.txt');
Signal.Load('Signals.csv');
Signal.SpeedLimit(0,25,45,75);
Light.Ambient(1,1,1);
Light.Diffuse(1,1,1);
Light.Direction(90,0);
Adhesion.Change(0.342, 0, 0.00643);
Gauge.Set(1435);
Track['down'].Gauge(1435);
Track['up'].Gauge(1435);
Curve.SetFunction(1);
//先行列車、乗客、天候
// include 'Map_Trains_h01.txt';
// include 'Map_People_h01.txt';
Station.Load('map_StationList_dev_h01.csv');
include 'Map_Weather_h01.txt';
include 'MapStations_dev.txt';
include '../../Data/Map2017/M41323_Signal.txt';
include '../../Data/Map2017/M41323_Sign.txt';
include '../../Data/Map2017/M41323_Illuminance.txt';
include '../../Data/Map2017/M41323_RunSound.txt';
include '../../Data/Map2017/M41323_DrawDistance.txt';
include '../../Data/Map2017/M41323_Limit.txt';
include '../../Data/Map2017/M00_41323_S01_OT12_Hamaotsu.txt';
include '../../Data/Map2017/M00_41323_S01_OT12Track_Hamaotsu.txt';
include '../../Data/Map2017/M00_41323_S02.txt';
include '../../Data/Map2017/M00_41323_S02_Track.txt';
include '../../Data/Map2017/M00_41323_S03_OT32_Shinomiya.txt';
include '../../Data/Map2017/M00_41323_S03_OT32Track_Shinomiya.txt';
include '../../Data/Map2017/M00_41323_S04.txt';
include '../../Data/Map2017/M00_41323_S04_Track.txt';
include '../../Data/Map2017/M00_41323_S05_T08_Misasagi.txt';
include '../../Data/Map2017/M00_41323_S05_T08Track_Misasagi.txt';
呪文の意味はだいたい以下のようになります。
基本データロード、ロード、ロード、早く読まないとエラー吐いてしまうリストからロード、路線の基本設定、状況別のマップ状況ロード、信号と保安装置のデータをロード、分岐器を境界にしてエリア別にマップをロード、仕上がってきたら書き換える頻度が非常に低くなる線形データをロード
include先の事例 線形データ
(下りなので基準座標からキロ程を引いてBVE内Z座標として設定している)
BveTs Map 2.01
$KSS = 11750;
$KSS-5650; Gradient.BeginTransition();
$KSS-5605; Gradient.BeginConst(5.0);
$KSS-5460; Gradient.BeginTransition();
$KSS-5450; Gradient.End();
$KSS-5440-10; Curve.BeginTransition();
$KSS-5440; Curve.BeginCircular(-2000, 0);
$KSS-5425; Curve.BeginTransition();
$KSS-5425+10; Curve.End();
$KSS-5430; Gradient.BeginTransition();
$KSS-5420; Gradient.BeginConst(5.0);
$KSS-5340; Gradient.BeginTransition();
$KSS-5330; Gradient.End();
$KSS-5310; Gradient.BeginTransition();
$KSS-5295; Gradient.BeginConst(-6.3);
$KSS-5205; Gradient.BeginTransition();
$KSS-5195; Gradient.BeginConst(-10.0);
//Station OT31
$KSS-5105; Gradient.BeginTransition();
$KSS-5095; Gradient.BeginConst(-13.8);
$KSS-5005; Gradient.BeginTransition();
$KSS-4975; Gradient.BeginConst(-31.3);
$KSS-4940; Gradient.BeginTransition();
$KSS-4890; Gradient.End();
$KSS-4900-30; Curve.BeginTransition();
$KSS-4900; Curve.BeginCircular(-402.33+1.7, 107);
$KSS-4825; Curve.BeginTransition();
$KSS-4825+30; Curve.End();
$KSS-4885; Gradient.BeginTransition();
$KSS-4850; Gradient.BeginConst(-22.2);
$KSS-4760-30; Curve.BeginTransition();
$KSS-4760; Curve.BeginCircular(160.93+1.8, 107);
$KSS-4650; Curve.BeginCircular(100.58+1.8, 107);
$KSS-4630; Curve.BeginTransition();
$KSS-4620; Curve.End();
$KSS-4610; Curve.BeginTransition();
$KSS-4605; Gradient.BeginTransition();
$KSS-4595; Gradient.BeginConst(-17.3);
$KSS-4585; Curve.BeginCircular(-80+7.2+1.8, 0);
$KSS-4558; Curve.BeginTransition(); Track['up'].Position(+3.2,0, 0,0);
$KSS-4558+35; Curve.End();
呪文の意味は以下のようになります。
様式バージョンセット、基準座標セット、分岐器の終点から開始、勾配、カーブ、目印コメント、勾配、カーブ、・・・、分岐器の手前でデータ終了
車両(シナリオファイルから呼び出される)
Bvets Vehicle 0.03
PerformanceCurve = notch\notch.txt
Parameters = parameters82.txt
Panel = panel82.cfg
Sound = sound82.cfg
Ats = ATSKeihan800.dll
MotorNoise = motornoise\motornoise.txt
呪文の意味はだいたい以下のようになります。
様式バージョンセット、ノッチ曲線ロード、車両パラメータロード、運転台データロード、サウンド設定ロード、保安装置プラグインロード、モーター音設定ロード
例としてパラメータファイル
Bvets Vehicle Parameters 2.01
FirstCar = M
[Cab]
BrakeNotchCount = 10
PowerNotchCount = 5
AtsCancelNotch = 1
MotorBrakeNotch = 2
ReverserText = 後,切,前
BrakeText = 弛,8°,16°,24°,32°,40°,48°,56°,64°,72°,抜取,非常
PowerText = OFF,P1,P2,P3,P4,P5
[SMEE]
MaximumPressure = 440000
BpInitialPressure = 490000
PressureRates = 0, 0, 0.02, 0.23, 0.37, 0.51, 0.62, 0.73, 0.84, 0.95, 1,1
LeverDelay = 0.5
[LockoutValve]
MaximumPressure = 420000
RegenerationLimit = 25
[Compressor]
UpperPressure = 750000
LowerPressure = 650000
CompressionSpeed = 1600
[Bc]
ApplyStart = 30000
ApplyStop = 10000
ReleaseStart = 30000
ReleaseStop = 10000
ApplySpeed = 500
ReleaseSpeed = 300
[Brake]
PistonArea = 0.45
ShoeFriction = 0.28, 0.01, 0.035
[Sap]
ApplySpeed = 360
ReleaseSpeed = 360
VolumeRatio = 25
[Bp]
ApplySpeed = 150
ReleaseSpeed = 300
[MainCircuit]
RegenerationLimit = 1
RegenerationStartLimit = 25
PowerNotchDelay = 0.5
BrakeNotchDelay = 0.5
ReverserDelay = 0.5
[Dynamics]
MotorcarWeight = 33625
MotorcarCount = 4
TrailerWeight = 26667
TrailerCount = 3
CarLength = 18.8
[ViewPoint]
X = -0.7
Y = 2.4
Z = -1.05
呪文の意味はだいたい以下のようになります。
先頭M車にセット(グリップ挙動のシミュレーションに影響)、ハンドル設定(各段の設定)、電磁直通ブレーキ(ブレーキシステムの一つ)のパラメータ設定、主制御装置の設定(応答特性)、力学パラメータ設定、視点座標設定
ほんとはまだまだあるんですが、既に情報が洪水しまくってると思うのでこの辺にしときます。やべぇよ・・・やべぇよ・・・
基本ソフトウェアがシナリオファイルを読んでごちょごちょ動くと、以下のようになるということです。
以上「そもそも「BVE Trainsim5のシナリオ」の実体は具体的に何か?」でした。
2.シナリオ制作のゴール設定
「要件定義」と一般に呼ばれます。
同人作品としてなら、ほどほどに煮詰まったらそれで設定完了として次のステップに移行してもいいのではないかと思います。
車両
狭義の「BVEシナリオ」と言えるかも(これ一つで運転曲線が新しくできますので)。
イメージ
路線
言っちゃなんですが極論盆栽と同じ要領です。グリーンマットでも運転シミュレータとして成立します。某関西大手私鉄京〇〇津線みたいなのは盆栽の敷居を上げすぎているから参考にしてはいけません。内房線Ver.2.00(2020/09/23)などがゴールイメージを描く参考として理想的だと思います。
事業者により規格が異なるので注意が必要です。某関西大手私鉄の京〇電車みたいな特殊事例はBVEの仕様通りに作ると全然コレジャナイものになってしまうので、工夫しないと満足できる品質に仕上がらないかもしれません(複線間隔が他の路線で見られない寸法になっている、デッドマン厳しい、扉扱いは車掌ではなく運転士主導だからここで既にBVEの仕様からはみ出してる、カントえっぐ、特注構造物多すぎ、保安装置も他で例を見ないから流用できない、そもそも一駅間を除いて緩和曲線も縦曲線もない直線部分がほぼ無いとかなんなんだよ、など無数のエラーを吐いている)。
よくわからなかったらいったん一般的な設定を採用して仕上げてしまい、あとで実は違うことがわかってから対処してもよいのではないでしょうか。シナリオ制作もう一回遊べるドン!
走って止まってなんかそれっぽかったらもうそれでいいんじゃないでしょうか。
どんな解像度の高いシナリオもフィクションなのですから。
作品を完成させた経験が浅ければ以下は次回作以降の課題としてもよいと思います。
パッケージ
共有することに意義を感じているなら一番意識を向けるのはここです。どれほど高級で精巧な作品でも触れられないならそれは無いも同然と受け取り沈黙する方もいらっしゃいます。「具体的にどの体験を提供するかデザイン」とも言えます。
プレイヤーの手数を最小化して目的を果たすことを意識するとよいのではないでしょうか。
XRマーケットでのポジショニング
広く知られたいならこれを徹底的に絞り込みましょう。BVEを知らない人にもBVEを知らないままBVEを楽しんでもらい活動の場を広げていきましょう。
各地で開催される運転会などはターゲットのひとつと言えるでしょう。
BVEを活用して地域価値向上への取り組みのひとつとして展開することも考えられます(地域価値向上への鉄道の活用は1.生活特化…えちぜん鉄道など、2.生活+観光…ひたちなか海浜鉄道など、3.観光特化…大井川鐵道など、4.経営力特化…伊予鉄道など といったように分類され、特に2・3に運転体験は刺さりやすい傾向があると推測される)。
この点考察すると、京阪電車のシナリオはどれだけ細かく作りこんだとしても「SANZEN-HIROBA」にかなわないという課題が浮上します。
「SANZEN-HIROBA」にできなくてBVEにできることはないのでしょうか?
いや、あります。
「無料」「どこでも」「誰でも」「簡易的に」
BVEは作品と人の組み合わせでどんどん可能性が広がるものです。
SteamやApp Storeなどいろんなサイトがありますがうまく棲み分けできたらいいですね。
※1 BVE基本ソフトウェアはスマホ対応できませんが、そこはターゲットの絞り込み要素としましょう 他にもできないことを挙げていくとターゲットの絞り込み解像度が上がっていきます
※2 本稿は"BVEシナリオを利用したあらゆる手段による収益化を否定する主張"をするつもりはございません
話が少しふくらんでしまいました。
本稿では例として以下のようなゴール設定を行うことにします。
車両は汎用的な系列を選択
路線は特定の状況(日常の昼、季節は秋)を想定してシーンを埋める
自分で遊んで楽しいシナリオに仕上げる
シナリオの外のことはシナリオが完成してから進める、と割り切る
BVEシナリオ作りたいのはいいけど、結局あなたがしたかったのは何でしたか?という問いにある程度方向性を持っておけば道を違える危険は避けやすいです、というお話。
以上「シナリオ制作のゴール設定」でした。
3.必要な準備
どうしてBVEシナリオ制作はとんでもなく多大な労力を要するのか。
その答えが本章と次章「4.制作中の基本操作」にあります。
そして手を付ける前の準備で制作能率は大きく変わります。
まあその制作能率ってのはぶっちゃけふたを開けてみないと評価できないので、必要最低限揃ったらさっさと制作に着手しちゃって、残りは後追いでそろえるのが良いと思います。
3-1.取材道具
スマートフォン …素材写真、サウンドレコーダー、動画撮影、車両性能ロガーなどこれ一つでそれなりにできます。ただしそれぞれの機能に特化した別道具に性能は格段に劣ります。(執筆時現在)型落ちの中古で十分。これのために残業や副業を増やすくらいなら制作時間に回して手持ちの道具で作れる品質で「足るを知る」方がはるかにQOL高いのでは。
執筆時点で一番安い機種を引いてみたらこれがでてきましたが、これで十分です(動画投稿サイトにアップロードされているデータで品質を確認しました)。予算面で困難があるならこれより5年前の機種でも電池劣化に注意すれば役割を全うすることが期待できます。
もっと上位の機種をお持ちであれば、スペック相応にお使いいただけます。
カメラ …スマホで満足なら不要。ミラーレス一眼と広角レンズ(収納性重視)・望遠レンズ(35mm換算200mm以上)各1本など。非常に古い機種を中古で入手した場合でもスマートフォンでは絶対到達できない品質の素材が量産されます。バッテリーの入手性・持続時間・運用(自分の体力と相談)に注意し、電源難民にならないようにだけ。セットアップ次第で動画撮影も完結する。
RAW撮影できて最安のものを探したら例えば以下のような機種。中古で15,000円くらい。
標識の撮影などに強力な望遠はEマウントだと例えば以下のような機種。35mm換算80-300mm、中古で15,000円くらい。
コンパクトデジカメは原理的に画像品質を追求できない(センサーサイズが小さいため屋根の下で十分な受光量が得られない)のでミラーレス一眼を使えない場合の妥協点くらいで。ミラーレス一眼より安価ですから乗り換えまでのつなぎとして輝くことはあります。
例えば以下のような機種は非常に厳しい環境下での撮影に耐えますが、そんな環境のところに鉄道は走っておりませんし、最安値のミラーレス一眼に画像品質は及びません。登山や水泳もされている方が兼用される分には良いと思います。
無論、上を見ればキリがありません。お好みでセットを組みましょう。
ビデオカメラ …スマホで満足なら不要。アクションカメラの一番安い機種でスマートフォンの上位互換として機能する。一眼レフカメラよりも手ぶれに強く、コマ送りなどの際に鮮明なデータが得られます。
例えばこんな感じです。
ICレコーダー …スマホで満足なら不要。フロート録音、ガンマイク、バイノーラルマイクのセットが理想。ICレコーダー自体20年くらい進化し続けてもう来るところまで来ちゃってる感じなのでPCM録音さえできればスマートフォンの上位互換として機能する。
例えばこんな感じです。
MP3形式のみ対応でPCM録音できない、ステレオ対応していない機種はBVEシナリオ制作には向いていません。
マイクは(入手できれば)データシートを確認して特性をうまく活かしましょう。
-20dBで感度1/10、-10dBで感度約1/3です(指数関数)。以下の例では横と後ろの音はだいたい1/3くらいになり高周波数サウンドは1/10くらいになりそう、みたいに読み取れます。マスコンハンドル操作音、コンプレッサー動作音などの素材確保が捗りそうです。
距離計 …あると取材解像度が爆上がりする。ゴルフ用・建築用各1台あれば理想。一番安い機種で十分。
加速度ロガー …上級者向け。速度計目視手書きメモで十分。好みによりRaspberry Pi等活用(アプリを自作してお手持ちのスマホに放り込んでもOK)。
3-2.PCインターフェース
PC本体は最低動作環境の性能で十分です。動作試験一号機も兼用できるので(リリース前にボリュームゾーン環境での試験データもあればなお良い)。たぶん最終的にCPUがボトルネックになるでしょうが、Ryzen 3相当以上であれば問題ないでしょう。メーカー製品の中にメモリが少なすぎる罠がたまにありますが、そういう製品は売れ筋から外れていくので油断しなければハマらないと思います(新製品が頻繁に登場し旧モデルの製品ページがすぐ消えるので具体例は出しにくいです。ご容赦ください)。
理想を言えば3画面以上。2画面までなら簡単にできますが3画面以上は本稿執筆時点で(BVEシナリオ制作入門者のボリュームゾーンは中高生と想定して)かなり高額の出費となります。その出費をするよりはとにかく作品を出してステップアップ目指した方が得策だと思います。
もし実現できた場合どうなるかですが、
「タスク管理」「編集」「資料表示」「シナリオビューワ」を開けている状況を想定して
「編集」「シナリオビューワ」を別画面にするだけで格段に能率が上がりますし
「編集」「資料表示」「シナリオビューワ」それぞれ別画面でほとんどストレスを感じません(個人の感想です)し、
そこからさらに4画面あればタスク管理も常時見やすく資料を2画面出してさらに能率向上という運用もできます。
Xを開けて時間浪費する罠には注意しましょう。
キーボードは人間工学系の製品が理想ですが、高価で手が届かない場合でもキーストロークが深い有線フルキーボードで十分です。(ノートPCなどでみられる一部のキーが特殊キーで呼び出され圧縮配置されているものだと能率が非常に悪いので外付けしてでも避けるべき)
「薄型キーボード」と称している製品はキーストロークが浅いのでBVEシナリオ制作には向いていません。
マウスやタッチパッドよりトラックボールの方が圧倒的に高能率です。一番安い中古のでいいからトラックボールを使いましょう。初めてさわる場合でもまあ2週間もあれば慣れます。もしかすると一番コスパがいい投資先かもしれないです。(あれっこの話は某艦〇れ界隈でも聞いた気がするでち)
3-3.BVE基本ソフトウェア最新版
開発環境であり実行環境でもあるものとして基本ソフトウェアをインストールします。
作品を共有する際、動作環境の明示に必要なのでバージョンと公開日を控えましょう。
例:「BVE基本ソフトウェアバージョン:5.8.7554.391 公開日:2020/09/23」
3-4.シナリオ制作支援ツール
必要なものを導入し、お好みによりデスクトップショートカットなどで呼び出しやすくしましょう。
3-5.エディタ
いくつか選択肢があります。
VSCode
メリット:機能が充実している・カスタマイズしやすい・バージョン管理システムに対応している・BVE制作支援ツール対応
デメリット:以前よりだいぶマシになったがまれにバグり散らして対処不能な状況が生じることがある まあMSだし
Notepad++
メリット:動作が軽い・BVE制作支援ツールを当てるだけで見やすく編集時の指向ノイズが少ない
デメリット:ファイルサイズが大きくなると動作が重くなる(10000行以上のマップファイルを編集していたら「早くリリースまでこぎつけないとまずい・・・」とひしひし感じていました)
お好みのテキストエディタ
文字コード指定保存できるなら制作に利用可能です。
3-6.(推奨)表計算ソフト
MS Excelがよく使われるようです。
座標計算、性能計算いろいろできます。
3-7.画像編集・加工ソフト
選択肢はたくさんありますが使い慣れたソフトを選びましょう。
シナリオの規模により何万回も開くこともあるので・・・
GIMP
Photoshop
最先端の機能はPhotoshopでなければ利用できませんが、GIMPでも十分作品完成までこぎつけられます。
軽いから、操作に熟練していて高能率だから、と他のお好みのソフトを使い続けても(必要な機能が揃っているなら)大丈夫です。
3-8.サウンド編集ソフト
お好みで。
Sazanami
Adobe Audition CC
3-9.3Dモデリングソフト
Metasequoia
Blender
3-10.ファイル内検索
WindowsOS標準機能でもフリーソフトでもお好みで。
「あの構文書いたのどこだっけ??」は結構な頻度で発生します。
3-11.バージョン管理システム
お好みで。
あれば保安度が高くなりますがなくても作品は完成します。
BVEシナリオ制作能率向上と親和性が高いのはGitですが、完成品をユーザフレンドリーなフォーマットに整えるにはSVNの方が円滑です。
なお昨今のアプリ多様化の流れで分野横断的にGitが選ばれやすい状況となっており、今後も続くと予想されます。
Git
SVN
3-12.必要な科目の再履修
シナリオの表現範囲に応じて頭にインストールしましょう。
慣れないうちは全部取らずに今得意なところだけで一作品ずつ仕上げ、それから増やしていった方がいいと思います。
英語:エラー発生時にある程度自力で対処できる程度
物理:力学・電磁気学・波動(サウンド編集に必要)
公民:倫理・社会のルール(取材からシナリオ共有までの作法)
数学:集合と論理・三角関数・微分・図形・データ分析・確率あたりで。制作中特に障壁となりやすい分野である。制作中につまづいてから再履修してもよい。
プログラミング:ATSEx(おーとまさん)を活用する場合適宜(プログラミングが苦手な場合もBVEをきっかけに挑戦するのはとても素晴らしいと思います)
以上「必要な準備」でした。
4.制作中の基本操作
頭にインストールしましょう。
4-1.エディタとビューワの切り替え
左手で「Alt」+「Tab」を押している間リストが表示されるので「Tab」を押して移動、離すと切り替え。
「VSCode」or「Notepad++」⇔「BVE」切り替え等で頻繁に使います。
4-2.とてもよく使うショートカットキー
エディタ内検索:「Ctrl」+「F」
切り取り:「Ctrl」+「X」 ※Z座標移動で非常によく使います
コピー:「Ctrl」+「C」
貼り付け:「Ctrl」+「V」
一手戻す:「Ctrl」+「Z」
戻しすぎたのをやり直す:「Ctrl」+「Y」
全部選択状態にする:「Ctrl」+「A」
複数選択:「Shift」+「→」「↓」「←」「↑」
上書き保存:「Ctrl」+「S」
4-3.バージョン管理
GitやSVNを活用しているならそれらのシステムの操作方法に従います。
Like A Lake制作チームではSVNを使っていますが、個人制作の場合は(メジャー,マイナー,パッチ)のバージョン番号とコミットメッセージつけて「BunBackup」等ソフトで自動バックアップ組んでおけばだいたい事足りるのではないでしょうか。
とりあえず何かしらのトラブルで何千時間かけたシナリオがパーという事態を避けれたらそれでいいと思います。
以上「制作中の基本操作」でした。
5.シナリオ制作の流れ
大変長らくお待たせいたしました。
「2.シナリオ制作のゴール設定」のゴールまで走り切る時がようやく来ました。
5-1.取材
どうして「3.必要な準備」にこの節が含まれなかったかというと、ここまでの準備が穴だらけの状態では取材時に要点を押さえることが難しいこと、ならびにシナリオ制作中にも再取材を必要とするケースが多々あり制作の営みに組み込まれた概念として解説することがお役に立ちやすいのではないかと考えたためです。
さて取材しに出発する前にマインドセットを。
大前提:
あなたは運送約款が適用される旅客の一人として法的に扱われます。
他のお客様のご旅行やプライバシーにも十分配慮し、駅係員・乗務員等から指示を受けた場合は滞りなく従いましょう。
危険が予想される行動の例:
通行者の多い場所での撮影(衝突による怪我であなたが苦しむことはもちろん、視覚や聴覚に難のある方を巻き込んだ場合重大な事故につながるおそれがあります)
大人数での取材(他のお客様が通行時微妙な気分になるかもしれません)
他の旅客や事業者係員等のプライバシーを侵害する取材(顔だけでなく持ち物の特徴で個人を特定できることも多いです。収音中の声も同様です。
私だと目を閉じていても声だけで誰が乗務しているか特定できますし…)不安定な姿勢での取材(列車接近時は思いがけず突風に見舞われる場合があり、転倒・転落など重大な事態を引き起こす恐れがあります)
長い棒の先に取材道具を付けスピーカーに向けて伸ばす(あなたが高圧電撃を受け命の危険にさらされるおそれがあります)
三脚の使用(ホーム上だろうと列車内だろうと原則として公道上のルールが適用されます。家の前の公道で三脚立てられたら困りますよね)
フラッシュの使用(威力業務妨害で立件される場合もあります)
非常用経路をふさぐ体勢での取材(取材中に震度7来たらあなた込みで非常に多くの方の命が危険にさらされます)
お身体の不自由な方を補助する設備付近での取材(お相手様はあなたが何をしているのかわからないので無防備で衝突し大けがの原因になります)
荷物を散らかす(原則として公道上以下略)
黄色い点字ブロックの以下略(時間がもったいないからこれ以上書かせないでください)。
一度の取材、一本の行程で全ての素材をそろえることは無理です。
誤差やノイズがゼロになる収録方法はありません。
想定している品質への影響が大きくないのであれば、採れた素材を組み合わせて活用しとにかく仕上げてしまいましょう。
どんな解像度の高いシナリオもフィクションなのですから。
路線
配線 …トポロジー、分岐器のクロッシング番数(応用 構造、材質、付帯設備)
曲率半径 …軌道中心線のものか?各線路のものか?入力前に検証
勾配 …標識の中で一番見つけやすいかも。書き取り漏らしが怖かったら望遠写真を撮ることで検証しやすい。
各変曲点のキロ程 …架線柱に番号を付けて各々Z座標を求め、標識との位置関係から求める。慣れないうちは100m精度とかで十分それっぽくできると思います。5m精度でも10km以上のマップ制作に何年もかかるのはざらなので欲張りすぎると危険。
信号機 …対向の信号機座標も記録しましょう。運転時の目印となる場合があります。
速度制限標 …対向の標識も記録しましょう。
停止目標 …対向の標識も記録しましょう。
セクション標 …BVEのシステムであまり表現されている例を見ませんが、実際は止まってはいけない箇所であり運転上重要なので記録しましょう。
駅設備 …屋根、昇降機、看板など
構造物 …橋梁、トンネル、留置線など
隣接構造物や建造物の特徴 …線路の上を横切っているものをだいたい網羅していたらなんとかなるんじゃないでしょうか。踏切のキロ程を把握できれば誤差の小さい路線データに仕上げやすいです
自然物 …大きさにより国土地理院データなども活用しましょう
放送 …スピーカーのなるべく正面から指向性マイクを向けて収録。指向性マイクなくても編集ソフトで放送っぽく演出すればよし。車内放送はスピーカー位置を確認して収音しましょう。例えば京阪プレミアムカーでは「10C」「11C」席など。
ダイヤ、運用 …対向列車の設定に
車両
運転台 …運転台本体、圧力計、各種表示灯、速度計、保安装置表示灯など
サウンド …ブレーキ込め緩め、ドア開閉音左右、フランジ音、警笛、分岐器通過音、補助電源作動音、モーター音、ハンドル操作音、定速走行音、空気ばね作動音、コンプレッサー作動音など
場合により車外からの収音が適していることもあります。
ジョイント音は運転席または台車直上から可能な限り近い位置から収録しましょう。
主制御装置とモーターは離れたところにあるので同時に収録することが困難です。例えば京都市交10系電車の場合、主電動機は1800形(国際会館寄り1両目)にも搭載されていますがチョッパ制御のサウンドは1700形・1200形(2両目・5両目)でなければ聞こえないでしょう。補助電源は1800形・1600形・1100形(1・3・6両目)コンプレッサーは1800形・1100形(1・6両目)にあります。
性能 …一般的に実車はカタログスペックより余裕を持った性能を持っているので、たくさん実測しましょう。カタログスペック上起動加速度2.8km/h/s?でも実測だと起動から60km/hまで20秒というのはよくあることです。
保安装置 …システム構造、地上子位置、動作仕様など実装に必要な情報を入手しましょう。
5-2.車両制作
まずは白紙状態の車両を作りましょう
基本ソフトと一緒にインストールしたであろう京成千葉線の京成3500形をコピーし、(この段階では正常に動作しなくていいので)取材で得た素材を上書きします。
全ファイル置き換えできた状態の車両をもって「白紙状態の車両」データとします。(白紙状態の車両は次回作のためのテンプレートとして保存するとよいかもしれません)
こういうところは生成AIでやればいいんじゃないか、と私は思いますが、執筆時点でやってみたら全然使えないデータが出てきました(ファイル構成が間違っている、BVE2とBVE5の書式が入り乱れている、文法に誤りがある、ファイルとパラメータの対応が間違っている)。そのデータを訂正できるスキルがあるなら生成AIを使わなくていいと思います。未来人に希望を託します。
白紙状態の車両から編集を進めていき完成に運びましょう。
vehicle.txt
Bvets Vehicle 2.00
PerformanceCurve = notch\notch.txt
Parameters = parameters.txt
Panel = panel6.cfg
Sound = sound.cfg
MotorNoise = motornoise\motornoise.txt
Ats32 = ATS_Kh_2gen_32.dll
Ats64 = ATS_Kh_2gen_64.dll
呪文の意味:性能データロード、車両パラメータロード、運転台データロード、サウンドデータロード、保安装置プラグインロード
notch.txt 性能ファイル
[Power]
Params = power\params.csv
Force = power\force.csv
MaxForce = power\force.csv
Current = power\current.csv
MaxCurrent = power\current.csv
NoLoadCurrent = power\current0.csv
[Brake]
Params = brake\params.csv
Force = brake\force.csv
MaxForce = brake\force.csv
Current = brake\current.csv
MaxCurrent = brake\current.csv
NoLoadCurrent = brake\current0.csv
呪文の意味:力行とブレーキにセクションを分ける、進段パラメータロード、空車状態引張力テーブルロード、満車状態引張力テーブルロード、電流テーブルロード
説明がよくわからなかったら京成3500形を開けて考察したらいいと思います。
params.csv 進段パラメータファイル
bvets vehicle performance table 0.01
#
BreakerDelay_On,0.5,0.5,0.5,0.5
BreakerDelay_Off,0.5,0.5,0.5,0.5
ResetTime,1,0,0,0
jerkregulation_up,20,20,20,20
jerkregulation_down,20,20,20,20
CurrentReducingTime,0,0,0,0
currentlimitingtime,0,0,0,0
requirednotch_up,2,3,4,5
requirednotch_down,0,1,2,3
stepdelay_up,0,0,0,0
stepdelay_down,0,0,0,0
cutoffcurrent_empty,0,0,0,0
cutoffcurrent_full,0,0,0,0
VVVF車の事例です。界磁位相制御とかの緻密な再現をしようとしたらだいぶ複雑になるので、慣れないうちはVVVF車のような挙動をする設定で近似するのがいいと思います(緻密な再現はリメイク時にすればよいでしょう。そもそも100点の車両データなどこの世にないということに留意して着地点を設定しましょう)。
force.csv
bvets vehicle performance table 0.01
#
0,13547,17627,26131,29587
15,13547,17627,26131,29587
48,4234,17627,26131,29587
49,4148,17627,25598,28984
50,4065,17627,25086,28404
55,3695,17627,22806,25822
60,3387,16159,20905,23670
65,3127,14916,19297,21849
70,2903,13850,17919,20289
75,2547,12149,15717,17796
76,2484,11847,15327,17354
引張力=電流の関数、電流=走行速度の関数としてモデルを作り、引張力=走行速度の関数として投射したモデルです。
走行速度の間隔が空いているところは線形補完されます。
特性域(この例だと48km/h以上)は非線形になるのでデータを打つ数が多くなります。
電流=走行速度の関数 でテーブルを作ることで電流テーブル(current.csv)も作成できます。
応過重最大のケースは1人65kg×定員で設定するケースが多いようです。
panel.txt
本体とパーツを適宜配置してください。
Layerは手前から降順な点がBVE独特。
sound.txt
対応するサウンドファイルに設定してください。
車両のための保安装置
全部出すと長すぎるので機能面で最低限の部分だけ載せてみました。
約20年前のBVE4での作り方(つまりめっちゃ古い)なので、都度適切なやり方に置き換えてお納めください。
Ats.cpp 例示用
クラス定義やインスタンス生成は省略。
// ヘッダ読み込み
#include "stdafx.h"
#include "CVehicle.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved ){
初期値を入れる。
(中略)
return true;
}
// 車両クラス初期化と解放
ATS_API void WINAPI Load(void){ pVehicle = new CVehicle; }
ATS_API void WINAPI Dispose(void){ delete pVehicle; }
ATS_API void WINAPI atsSetVehicleSpec(ATS_VEHICLESPEC vehicleSpec){ pVehicle->SetVSpec(vehicleSpec); }
ATS_API void WINAPI atsInitialize(int brake){ pVehicle->Init(brake); }
// メインループ
ATS_API ATS_HANDLES WINAPI atsElapse(ATS_VEHICLESTATE vehicleState, int *panel, int *sound){
pVehicle->SetATScond(vehicleState); // ATSの状態更新
pVehicle->CSound(sound); // サウンド処理
pVehicle->ElapseState(vehicleState); // 諸状態の更新
pVehicle->ElapseHandle(&HOutput); // ハンドル指令の更新
pVehicle->SetPanel(panel); // 運転台表示の更新
return HOutput;//ATS_HANDLES構造体を返します。
}
ATS_API void WINAPI atsSetSignal(int signal){
信号が変化したら照査パターンを更新するなど。
}
以下略
ATSsampleroute.cpp
例としてK-ATSを想定してATSの挙動を制御します。簡略化しています。
ヘッダ読み込み
void CVehicle::SetATScond(ATS_VEHICLESTATE vehicleState){
停止パターン制限速度 = 停止パターン関数(vehicleState.Location);
減速パターン制限速度 = 減速パターン関数(vehicleState.Location);//減速信号や曲線・勾配の制限速度を守るパターン
パターン接近検知速度 = パターン接近検知関数(vehicleState.Location);
フレーム更新時処理(諸状態の条件から外れていれば解除する)
if(vehicleState.Speed > パターン接近検知速度) パターン接近状態に更新(CVehicleメンバ関数に作っておく)
if(vehicleState.Speed > 減速パターン制限速度) ATS減速制御状態に更新
if(vehicleState.Speed > 停止パターン制限速度) ATS停止制御状態に更新
}
実際には減速パターンは信号や曲線、勾配などで複数重ね合わされます。制限速度は全パターンのうち最も低いものが適用されます。
保安装置により地上子通過時にパターン更新する場合がありますが、それはSetBeaconData関数からSetATScond関数にあたるものを呼び出します。
パターン曲線は平方根関数となり、走行位置でのパターン制限速度は以下の式から得られます(走行位置と速度制限開始位置との運動エネルギーの関係式から変形 導出略)。
(簡易実装で勾配を考慮しないならsqrt内3項目は不要です)
常用最大ブレーキ減速度が4.00km/h/sの場合、a=4.00/3.60=1.11m/s/sとなります。
重力加速度は9.80m/s/sが一般的に採用されます。
制限速度が適用される位置座標は残り距離をBeacon.Put構文を介して保安装置プラグインに入力します(信号によるパターンか曲線によるパターンかといった情報も地上子種別や送る値を工夫して渡します)。Beacon.Put構文は信号に干渉せずATSによる減速制御で速度制限を守れるよう配置します。
パターン接近検知については、減速・停止パターン-5km/h以上で検知する場合や半ブレーキ(常用最大の半分のブレーキ力)で所定速度まで減速する状態で検知する場合などがあり、保安装置ごとに異なりますので仕様を確認してください。
保安装置が点制御であれば、常時照査する必要はなく地上子を通過した時にATS状態を更新すればよいです(復帰にはリセットスイッチを実装)。
その他、BVE基本ソフトウェアに実装されていないけれども演出上重要な機能(転動防止ブレーキやドアが開いている時はチャイムを鳴らす機能など)もATSプラグインで実装します。
5-3.路線制作
5-3-1.準備
まずは白紙状態のマップを作りましょう
車両データの初期状態表示試験に使っているマップのコードを以下に示します。
BveTs Map 2.02
0;
実際の制作では以下の感じかなと(路線や演出状況によりパラメータは異なります)
BveTs Map 2.02
Structure.Load('Structures.csv');
Sound.Load('Sounds.csv');
Sound3D.Load('Sounds3D.csv');
Signal.Load('Signals.csv');
Station.Load('Stations.csv');
Section.SetSpeedLimit(0,8,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110);
Irregularity.Change( 0.0005, 0.0010, 0.0003, 100, 100, 25 );
Light.Ambient(0.9375, 0.9375, 0.9375);
Light.Diffuse(0.125, 0.125, 0.125);
Light.Direction(75, 225);
Adhesion.Change(0.234, 0, 0.005478851);
Fog.Set(0.0004, 0.875, 0.9375, 1);
Curve.SetGauge(1435/1000); Curve.SetCenter(1435/2000); Curve.SetFunction(1);
Track['Up'].Cant.SetGauge(1435/1000); Track['Up'].Cant.SetCenter(1435/2000); Track['Up'].Cant.SetFunction(1);
Track['Down'].Cant.SetGauge(1435/1000); Track['Down'].Cantr.SetCenter(1435/2000); Track['Down'].Cant.SetFunction(1);
白紙状態のマップは次回作のためのテンプレートとして保存するとよいかもしれません。
5-3-2.線形の仮置き
自線、本線、自線から近い順に別線の順で配置しましょう。
架線柱のZ座標推定値ははじめのうちは精度が高くなくてよいのでとにかく出して仮置きに活用しましょう。
この段階ではまだ風景を埋めてはいけません(風景を埋めた後のZ座標修正は作業量が膨大になるため)。
立体交差の事例:
(最初は変曲点の座標に大きな誤差が無ければ十分で、そこから調整していけばいいと思います)
$MLS = 50338;
$MLS-44676; //架線柱
$MLS-44673-75/2;
Gradient.BeginTransition();
Track['JRNara_down'].Y.Interpolate(0.6,-4000);
$MLS-44673;
$MLS-44673+75/2;
Gradient.BeginConst(33.0);
Track['JRNara_down'].Y.Interpolate(-0.6,0);
$MLS-44669; //ニノ橋踏切+-6.5
$MLS-44650; //府道
$MLS-44640;
Track['JRNara_down'].X.Interpolate(+15.6,0);
$MLS-44631; //架線柱
$MLS-44586; //架線柱
$MLS-44538; //架線柱
$MLS-44513; //架線柱
$MLS-44510-75;
Curve.BeginTransition();
Track['down'].Cant(0);
Track['up'].Cant(0);
Track['up'].Position(+3.4,0, 0,0);
Track['JRNara_down'].X.Interpolate(+22.6,-800);
$MLS-44510-75/2;
Track['JRNara_down'].X.Interpolate(+27.1,-300);
$MLS-44510;
Curve.BeginCircular(+201.17+1.9, 148);
Track['down'].Cant(148);
Track['up'].Cant(148);
Track['up'].Position(+3.4+0.21,0, 0,0);
Track['JRNara_down'].X.Interpolate(+28.1,-220);
$MLS-44510+52;
$MLS-44488; //架線柱
$MLS-44463; //架線柱
$MLS-44460-52;
$MLS-44460;
Curve.BeginTransition();
Track['down'].Cant(148);
Track['up'].Cant(148);
Track['JRNara_down'].X.Interpolate(+20.1,-200);
$MLS-44460+55/2;
Track['JRNara_down'].X.Interpolate(+10.3,-800);
$MLS-44460+55;
Curve.End();
Track['down'].Cant(0);
Track['up'].Cant(0);
Track['up'].Position(+3.4+0.21,0, 0,0);
Track['JRNara_down'].X.Interpolate(-2.7,1200);
$MLS-44438; //架線柱
$MLS-44435-75/2;
Gradient.BeginTransition();
Track['JRNara_down'].Y.Interpolate(-6.3,4000);
$MLS-44435;
$MLS-44435+75/2;
Gradient.End();
Track['JRNara_down'].Y.Interpolate(-7.5,0);
$MLS-44408; //架線柱
//奈良線立体交差
$MLS-44373; //架線柱
$MLS-44348; //架線柱
$MLS-44345-75/2;
Gradient.BeginTransition();
Track['JRNara_down'].Y.Interpolate(-7.5,4000);
$MLS-44345;
$MLS-44345+75/2;
Gradient.BeginConst(-33.0);
Track['JRNara_down'].Y.Interpolate(-6.3,0);
$MLS-44325-75;
Curve.BeginTransition();
Track['down'].Cant(0);
Track['up'].Cant(0);
$MLS-44325-75/2;
Track['JRNara_down'].X.Interpolate(-22.5,280);
$MLS-44325;
Curve.BeginCircular(-261.52+1.9, -160);
Track['down'].Cant(-160);
Track['up'].Cant(-160);
Track['up'].Position(+3.46+0.16,0, 0,0);
Track['JRNara_down'].X.Interpolate(-35.5,300);
$MLS-44325+68;
$MLS-44323; //架線柱
$MLS-44298; //架線柱
$MLS-44273; //架線柱
$MLS-44248; //架線柱
$MLS-44223; //架線柱 変電所接続
$MLS-44220;
Curve.BeginTransition();
Track['down'].Cant(-160);
Track['up'].Cant(-160);
Track['JRNara_down'].X.Interpolate(-44.0,320);
$MLS-44145-75/2;
Track['JRNara_down'].X.Interpolate(-38.3,800);
$MLS-44145;
Curve.End();
Track['down'].Cant(0);
Track['up'].Cant(0);
Track['up'].Position(+3.4+0.16,0, 0,0);
Track['JRNara_down'].X.Interpolate(-29.0,-1200);
$MLS-44193; //架線柱
$MLS-44163; //架線柱
$MLS-44123; //架線柱
$MLS-44123-75/2;
Gradient.BeginTransition();
Track['JRNara_down'].Y.Interpolate(-1.2,-4000);
$MLS-44123;
$MLS-44123+75/2;
Gradient.End();
Track['JRNara_down'].Y.Interpolate(0.0,0);
$MLS-44145;
Curve.BeginTransition();
Track['down'].Cant(0);
Track['up'].Cant(0);
$MLS-44123-22/2;
Track['JRNara_down'].X.Interpolate(-26.1,-380);
$MLS-44123;
Curve.BeginCircular(+402.34+1.8, 106);
Track['down'].Cant(106);
Track['up'].Cant(106);
Track['up'].Position(+3.4+0.11,0, 0,0);
$MLS-44123+45/2;
$MLS-44083; //架線柱
$MLS-44043; //架線柱
$MLS-44053-45/2;
$MLS-44053;
Curve.BeginTransition();
Track['down'].Cant(106);
Track['up'].Cant(106);
Track['up'].Position(+3.4+0.11,0, 0,0);
Track['JRNara_down'].X.Interpolate(-12.8,-400);
$MLS-44053+45/2;
Track['JRNara_down'].X.Interpolate(-12.1,0);
$MLS-44053+45;
Curve.End();
Track['down'].Cant(0);
Track['up'].Cant(0);
Track['up'].Position(+3.4,0, 0,0);
$MLS-44013; //架線柱
プレイ中にゆがみが目立たなければ十分だと思います。
2面4線島式ホームの駅の事例:
$MLS = 21347;
// PLS=池田秦線連立事業高架切替地点からの調整座標
$PLS = $MLS+135;
// RLS=枚方市駅連立事業高架切替地点からの破差調整座標
$RLS = $PLS-85;
// KLS=牧野駅高架化事業船橋川橋梁地点からの破差調整座標
$KLS = $RLS-42;
//S21:丹波橋1番線
$KLS+39700;
Track['Tanbabashi3'].Cant.SetGauge(1435/1000); Track['Tanbabashi3'].Cant.SetCenter(1435/2000); Track['Tanbabashi3'].Cant.SetFunction(1);
Track['Tanbabashi4'].Cant.SetGauge(1435/1000); Track['Tanbabashi4'].Cant.SetCenter(1435/2000); Track['Tanbabashi4'].Cant.SetFunction(1);
$KLS+39753;
Track['Up'].Position(0, 0);
Track['Up'].X.Interpolate(0, 0);
Track['Down'].Position(3.6, 0);
Track['Down'].X.Interpolate(3.6, 0);
Track['Tanbabashi2'].Position(0, 0);
Track['Tanbabashi2'].X.Interpolate(0, 0);
Track['Tanbabashi3'].Position(3.6, 0);
Track['Tanbabashi3'].X.Interpolate(3.6, 0);
Track['Tanbabashi1'].Position(0, 0);
Track['Tanbabashi1'].X.Interpolate(0, 0);
Track['Tanbabashi4'].Position(3.6, 0);
Track['Tanbabashi4'].X.Interpolate(3.6, 0);
$KLS+39758;
//1番線分岐
SpeedLimit.Begin(25);
Curve.Begin(-166.4);
Track['Tanbabashi1'].X.Interpolate(0, 0);
Track['Tanbabashi2'].X.Interpolate(0, 166.4);
Track['Tanbabashi3'].X.Interpolate(3.6, 166.4);
Track['Tanbabashi4'].X.Interpolate(3.6, 166.4);
$KLS+39758+20;
SpeedLimit.End();
Curve.End();
Track['Tanbabashi1'].X.Interpolate(0, 0);
Track['Tanbabashi2'].X.Interpolate(1.2, 0);
Track['Tanbabashi3'].X.Interpolate(3.6+1.2, 0);
$KLS+39773;
//4番線分岐
Track['Tanbabashi4'].X.Interpolate(4.3, 115);
$KLS+39778;
Track['Tanbabashi4En'].X.Interpolate(15.3, 0);
$KLS+39773+20;
Track['Tanbabashi4'].X.Interpolate(8.0, -1000);
$KLS+39788;
Curve.Begin(1000);
$Tanbabashi2_X = 2.4;
Track['Tanbabashi2'].X.Interpolate($Tanbabashi2_X, -1000);
Track['Tanbabashi3'].X.Interpolate($Tanbabashi2_X+3.6, -1000);
Track['Tanbabashi4En'].X.Interpolate(16.7, -1000);
$KLS+39788+120;
Curve.End();
// この部分はホーム幅が資料から既知なので変数使わない
Track['Tanbabashi2'].X.Interpolate(9.8, 0);
Track['Tanbabashi3'].X.Interpolate(9.8+3.6, 0);
Track['Tanbabashi4'].X.Interpolate(9.8+3.6+10.4, 0);
$KLS+39813-15;
Gradient.BeginTransition();
$KLS+39813;
$KLS+39813+15;
Gradient.End();
$KLS+39833;
Track['Tanbabashi4'].X.Interpolate(19.0, -100);
$KLS+39853;
Track['Tanbabashi4'].X.Interpolate(22.3, -1000);
Track['Tanbabashi4En'].X.Interpolate(22.3, 0);
$KLS+39963;
Curve.Begin(300);
Track['Tanbabashi2'].X.Interpolate(9.8, -400);
Track['Tanbabashi3'].X.Interpolate(9.8+3.6, -800);
Track['Tanbabashi4'].X.Interpolate(9.8+3.6+2.8+7.6, -300);
Track['Tanbabashi3'].Cant.BeginTransition();
$KLS+39983;
$Tanbabashi2_X = 9.3;
Track['Tanbabashi2'].X.Interpolate($Tanbabashi2_X, -900);
Track['Tanbabashi3'].X.Interpolate($Tanbabashi2_X+3.7, -900);
Track['Tanbabashi4'].X.Interpolate($Tanbabashi2_X+13.9, -300);
$KLS+40003;
Track['Tanbabashi4'].X.Interpolate(21.3, -600);
$KLS+40028;
Curve.Begin(900);
$Tanbabashi2_X = 5.9;
Track['Tanbabashi2'].X.Interpolate($Tanbabashi2_X, 900);
Track['Tanbabashi3'].X.Interpolate($Tanbabashi2_X+4.6, 900);
Track['Tanbabashi4'].X.Interpolate(17.6, 2000);
Track['Tanbabashi3'].Cant.Begin(150/1000);
$KLS+40048;
SpeedLimit.Begin(25);
Curve.Begin(100);
// トングレールは内側のみ可動、外側リードレールは基本レールと直結されている
$Tanbabashi2_X = 3.9;
Track['Tanbabashi2'].X.Interpolate($Tanbabashi2_X, -200);
Track['Tanbabashi3'].X.Interpolate($Tanbabashi2_X+5.1, -200);
Track['Tanbabashi4'].X.Interpolate(14.1, -200);
Track['Tanbabashi1An'].X.Interpolate(0, -100);
$KLS+40068;
Curve.Begin(-100);
$Tanbabashi2_X = 1.0;
Track['Tanbabashi2'].X.Interpolate($Tanbabashi2_X, 60);
Track['Tanbabashi3'].X.Interpolate($Tanbabashi2_X+5.7, 60);
Track['Tanbabashi4'].X.Interpolate($Tanbabashi2_X+8.8, 80);
Track['Tanbabashi1An'].X.Interpolate(-2.03, 100);
//1番線合流
$KLS+40078;
SpeedLimit.Begin(65);
Curve.Begin(600);
Track['Tanbabashi1'].X.Interpolate(0, 0);
Track['Tanbabashi2'].X.Interpolate(0, 0);
Track['Tanbabashi3'].X.Interpolate(5.4, 0);
Track['Tanbabashi4'].X.Interpolate(5.4+1.6, 166.4);
Track['Tanbabashi1An'].X.Interpolate(-3.5, 400);
Track['Tanbabashi4'].Cant.BeginTransition();
$KLS+40088;
Track['Tanbabashi1An'].X.Interpolate(-4.3, 0);
//4番線合流
$KLS+40098;
Track['Tanbabashi3'].X.Interpolate(4.3, 400);
Track['Tanbabashi4'].X.Interpolate(4.3, 0);
Track['Tanbabashi4'].Cant.Begin(150/1000);
Curve.BeginTransition();
$KLS+40110-29;
Gradient.BeginTransition();
$KLS+40110+29;
Gradient.Begin(28.6);
$KLS+40123;
Curve.Begin(402+1.8);
Track['Tanbabashi2'].Position(0, 0);
Track['Tanbabashi2'].X.Interpolate(0, 0);
Track['Tanbabashi3'].Position(3.6, 0);
Track['Tanbabashi3'].X.Interpolate(3.6, 0);
Track['Tanbabashi1'].Position(0, 0);
Track['Tanbabashi1'].X.Interpolate(0, 0);
Track['Tanbabashi4'].Position(3.6, 0);
Track['Tanbabashi4'].X.Interpolate(3.6, 0);
Track['Up'].Position(0, 0);
Track['Up'].X.Interpolate(0, 0);
Track['Down'].Position(3.6, 0);
Track['Down'].X.Interpolate(3.6, 0);
大きな駅の事例:
//0m=東京駅から400km地点
$KytStStart = 90000;
(中略)
$KytStStart+23256;
Curve.BeginTransition();
Track['kyoto_5'].Position(0,0, 0,0);
Track['up_in_2'].Position(+9.0,0, 2000,0);
Track['up_out_1'].Position(+12.8,0, 1000,0);
Track['storage'].Position(+4.5,0, 1200,0);
Track['shinkan_u'].Position(-55,8, 500,0);
//高倉通立体交差
$KytStStart+23270;
Track['5_3'].Position(+2.25,0, -300,0);
$KytStStart+23280;
Track['kyoto_7'].Position(-8.5,0, 700,0);
//7-8渡り線
Track['7_8'].Position(-8.5,0, -500,0);
Track['nara_dw'].Position(-13.0,0, 500,0);
Track['kyoto_9'].Position(-13.0,0, -500,0);
$KytStStart+23291;
//架線柱
$KytStStart+23300;
Track['storage'].Position(+4.9,0, 400,0);
Track['5_3'].Position(+4.9,0, 0,0);
$KytStStart+23305;
Curve.BeginCircular(-400,-45);
Track['up_in_2'].Position(+9.6,0, 400,0);
Track['up_out_1'].Position(+13.8,0, 200,0);
Track['kyoto_7'].Position(-11.8,0, 900,0);
Track['7_8'].Position(-13.0,0, 400,0);
Track['kyoto_9'].Position(-17.0,0, 600,0);
$KytStStart+23325;
Track['nara_dw'].Position(-17.3,0, -500,0);
Track['up_in_2'].Position(+11.1,0, 500,0);
Track['storage'].Position(+6.8,0, 800,0);
Track['kyoto_3'].Position(+6.8,0, 800,0);
Track['storage_2'].Position(+6.8,0, 160,0);
//4番線分岐
Track['kyoto_4'].Position(0,0, 200,0);
$KytStStart+23326;
//架線柱
$KytStStart+23330;
Curve.BeginTransition();
//奈良線シーサス
Track['9_10'].Position(-21.1,0, -300,0);
Track['10_9'].Position(-24.9,0, 180,0);
$KytStStart+23335;
Curve.BeginCircular(-800,-45);
Track['shinkan_u'].Position(-60,8, 600,0);
$KytStStart+23345;
Track['nara_dw'].Position(-18.5,0, 0,0);
Track['7_8'].Position(-18.5,0, 0,0);
Track['kyoto_8'].Position(-18.5,0, 800,0);
Track['kyoto_9'].Position(-23.0,0, 600,0);
$KytStStart+23350;
Track['storage_2'].Position(+11.5,0, 500,0);
Track['up_in_2'].Position(+14.0,0, 200,0);
Track['kyoto_4'].Position(+2.0,0, -400,0);
Track['up_out_1'].Position(+22.6,0, 0,0);
Track['kyoto_1'].Position(+22.4,0, 0,0);
//0番線分岐
Track['kyoto_0'].Position(+22.4,0, 300,0);
$KytStStart+23355;
Track['9_10'].Position(-26.1,0, 150,0);
Track['10_9'].Position(-26.1,0, -300,0);
$KytStStart+23365;
Curve.BeginTransition();
$KytStStart+23366;
Track['kyoto_4'].Position(+3.6,0, 400,0);
//架線柱
$KytStStart+23370;
Curve.BeginCircular(-400,-45);
Track['shinkan_u'].Position(-58,8, 400,0);
$KytStStart+23375;
Track['storage_2'].Position(+18.8,0, 0,0);
Track['kyoto_3'].Position(+13.8,0, -1500,0);
Track['up_in_2'].Position(+19.0,0, 300,0);
Track['kyoto_2'].Position(+18.8,0, 600,0);
Track['kyoto_0'].Position(+30.4,0, -500,0);
Track['2_1'].Position(+18.8,0, 200,0);
$KytStStart+23380;
Track['9_10'].Position(-30.0,0, 0,0);
Track['10_9'].Position(-26.2,0, 0,0);
$KytStStart+23395;
Curve.BeginTransition();
Track['kyoto_4'].Position(+6.6,0, -3000,0);
Track['kyoto_8'].Position(-22.0,0, 0,0);
Track['kyoto_9'].Position(-27.0,0, -1000,0);
$KytStStart+23396;
//架線柱
$KytStStart+23400;
Curve.End();
Track['kyoto_1'].Position(+34.9,0, -400,0);
Track['kyoto_0'].Position(+39.4,0, -400,0);
Track['kyoto_2'].Position(+27.8,0, -260,0);
Track['2_1'].Position(+29.6,0, -180,0);
Track['kyoto_7'].Position(-16.1,0, -1000,0);
//留置線分岐
Track['kyoto_st_1'].Position(+18.1,0, -400,0);
$KytStStart+23405;
Curve.BeginTransition();
Track['kyoto_4'].Position(+8.1,0, -1000,0);
$KytStStart+23426;
//架線柱
$KytStStart+23430;
Curve.BeginCircular(373,45);
Track['kyoto_3'].Position(+22.7,0, -500,0);
Track['kyoto_4'].Position(+11.4,0, -600,0);
Track['kyoto_8'].Position(-22.5,0, 2000,0);
Track['kyoto_9'].Position(-28.5,0, 2000,0);
Track['shinkan_u'].Position(-50,8, -400,0);
$KytStStart+23440;
Track['kyoto_st_1'].Position(+21.8,0, -800,0);
Track['kyoto_st_2'].Position(+21.8,0, -300,0);
$KytStStart+23450;
Track['kyoto_2'].Position(+40.0,0, -400,0);
Track['2_1'].Position(+45.0,0, 0,0);
$KytStStart+23456;
//架線柱
$KytStStart+23470;
Track['kyoto_st_2'].Position(+21.5,0, 800,0);
Track['kyoto_7'].Position(-16.3,0, 0,0);
$KytStStart+23470-5;
Gradient.BeginTransition();
$KytStStart+23470+5;
Gradient.End();
$KytStStart+23492;
//架線柱
$KytStStart+23495;
Curve.BeginTransition();
$KytStStart+23515;
Curve.End();
Track['kyoto_4'].Position(+14.9,0, 0,0);
Track['kyoto_3'].Position(+27.0,0, 0,0);
Track['kyoto_2'].Position(+44.0,0, 0,0);
Track['kyoto_1'].Position(+48.5,0, 0,0);
Track['kyoto_0'].Position(+53.0,0, 0,0);
Track['kyoto_st_1'].Position(+23.2,0, 0,0);
Track['kyoto_st_2'].Position(+19.4,0, 0,0);
Track['shinkan_u'].Position(-45,8, 0,0);
5-3-3.信号・標識の配置
信号機 → 停止標識 → 速度制限標識 → 踏切遮断反応灯 → 架線死区間標識 → 勾配標 → 曲線標 → 距離標(現時点ではまだ正確な座標出なくてよい) → 力行標・惰行標 → その他運転に必要な標識
みたいな順で配置するとよいでしょう。
架線柱とのZ座標位置関係を把握できていれば円滑に進行できます。
信号の配置例を以下に示します。
もしかしたら修正するかもしれない事態に備えて修正する構文はひとまとめで配置します。
//4103
$MLS-41760;
Structure['SigPole01'].Put('down', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01L'].Put('down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Sig_4LED'].Put(1,'down', -1.9,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,3,4);
Structure['SignalNB_4103'].Put('down', -1.9,+3.5-0.01,0, 0,0,0, 1,0);
$MLS-41449-5;
Structure['MissstartStoperHold02'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['MissstartStopperLoop_5m'].Put('down', 0,0.05,0, 0,0,0, 1,0);
$MLS-41449;
Structure['MissstartStoperHold02'].Put('down', 0,0,0, 0,0,0, 1,0);
$MLS-41449;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-41449+10;
//Beacon.Put(1,1,1);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
$MLS-41449; //確
Structure['StopAttention_kaku'].Put('down', -2.5,+2.1,-0.4, 0,0,0, 1,0);
Structure['StopAttention_light_on'].Put('down', -2.5,+2.1,-0.4, 0,0,0, 1,0);
$MLS-41263;
//Beacon.Put(2,1,1);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-41265; //通
Structure['StopAttention_p'].Put('down', -2.75,+2.1,-0.4, 0,0,0, 1,0);
Structure['StopAttentionCover'].Put('down', -2.75,+2.1,-0.4, 0,0,0, 1,0);
Structure['StopAttention45'].Put('down', -2.75,+1.4,-0.4, 0,0,0, 1,0);
$MLS-41223-122;
Beacon.Put(0,1,150); // 30照査
Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-41223-47;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
// 閉塞用
$MLS-41223-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-41223-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-41223;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//4101
$MLS-41223;
Structure['SigPole01'].Put('down', +5.65,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01R'].Put('down', +5.3,+3.5,0, 0,0,0, 1,0);
Signal['Sig_4LED'].Put(1,'down', +5.3,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,3,4);
Structure['SignalNB_4101'].Put('down', +5.3,+3.5-0.01,0, 0,0,0, 1,0);
$MLS-40933-122;
Beacon.Put(0,1,150); // 30照査
Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-40933-47;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
// 閉塞用
$MLS-40933-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40933-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40933;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//4003
$MLS-40933;
Structure['SigPole01'].Put('down', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01L'].Put('down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Sig_4LED'].Put(1,'down', -1.9,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,3,4);
Structure['SignalNB_4003'].Put('down', -1.9,+3.5-0.01,0, 0,0,0, 1,0);
$MLS-40573-122;
Beacon.Put(0,1,150); // 30照査
Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-40573-47;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
// 閉塞用
$MLS-40573-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40573-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40573;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//4001
$MLS-40573;
Structure['SigPole01'].Put('down', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01L'].Put('down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Sig_4LED'].Put(1,'down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Dir_4_C'].Put(1,'down', -2.1,+3.0,0.1, 0,0,0, 1,0);
Section.BeginNew(0,2,3,4);
Structure['SignalNB_4001'].Put('down', -2.25,+2.5,0, 0,0,0, 1,0);
//第1場内中継
$MLS-40414;
Signal['Sig_Relay'].Put(1,'down', -2.75,+3.5,-0.3, 0,0,0, 1,0);
Structure['SignalNB_RelayArr1'].Put('down', -2.75,+3.5,-0.3, 0,0,0, 1,0);
$MLS-40218-122;
Beacon.Put(0,1,150); // 30照査
Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-40218-47;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
$MLS-40218-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40218-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40218-4.16;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40218;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//丹波橋
//第1場内
$MLS-40218;
Structure['SigPole01'].Put('down', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_5_tie01L'].Put('down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Sig_5LED'].Put(1,'down', -1.9,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,3,3,4);
Structure['SignalNB_arr1_03_1L'].Put('down', -1.9,3.5,0, 0,0,0, 1,0);
Structure['Signal_4_tie01R'].Put('down', -2.55,+3.3,0, 0,0,0, 1,0);
Structure['Sig_4LED_0'].Put('down', -2.5,+3.3,0, 0,0,0, 1,0);
Structure['SignalNB_arr1_04_1L'].Put('down', -2.5,+3.3,0, 0,0,0, 1,0);
$MLS-40028-147;
Beacon.Put(0,1,150); // 30照査
Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-40028-77;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
$MLS-40028-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40028-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40028-4.16;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-40028;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//第2場内
$MLS-40028;
Structure['SigPole01'].Put('down', +1.95,0,0.2, 0,0,0, 1,0);
Structure['Signal_5_tie01R'].Put('down', +1.6,+3.5,0, 0,0,0, 1,0);
Signal['Sig_5LED'].Put(1,'down', +1.6,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,2,3,4);
Structure['SignalNB_arr2_03_1L'].Put('down', +1.6,3.5,0, 0,0,0, 1,0);
//$MLS-39833-122;
//Beacon.Put(0,1,150); // 30照査
//Structure['Beacon09_Lim25'].Put('down', 0,0,0, 0,0,0, 1,0);
//Structure['BeaconBox09'].Put('down', -1.95,0,-4.16, 0,90,0, 1,0);
$MLS-39833-57;
Beacon.Put(0,1,50); // 20照査
Structure['Beacon09_Lim15'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,-2.77, 0,90,0, 1,0);
Structure['StopLimit15_board'].Put('down', +1.7,0,-2.77, 0,0,0, 1,5);
Structure['StopPosHolder11'].Put('down', +1.7,0,-2.77, 0,0,0, 1,5);
$MLS-39833-9.72;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-39833-6.94;
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
Structure['BeaconBox09'].Put('down', -1.95,0,0, 0,90,0, 1,0);
$MLS-39833;
Beacon.Put(0,1,0);
Structure['Beacon09'].Put('down', 0,0,0, 0,0,0, 1,0);
//出発
$MLS-39850;
Structure['SigPole01'].Put('down_sub', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01L'].Put('down_sub', -1.9,+3.5,0, 0,0,0, 1,0);
Structure['Sig_4_0'].Put('down_sub', -1.9,+3.5,0, 0,0,0, 1,0);
$MLS-39833;
Structure['SigPole01'].Put('down', -2.25,0,0.2, 0,0,0, 1,0);
Structure['Signal_4_tie01L'].Put('down', -1.9,+3.5,0, 0,0,0, 1,0);
Signal['Sig_4'].Put(1,'down', -1.9,+3.5,0, 0,0,0, 1,0);
Section.BeginNew(0,2,3,4);
5-3-4.駅部分の基本オブジェクト配置
駅部分のZ座標範囲を表現する最低限のオブジェクトを配置しましょう。
長すぎるのでコードは省略します。
5-3-5.Z座標調整
プレイに大きな影響が出る誤差(駅間距離が実際より大幅に長い、曲線長が不自然)や画面表示が乱れる場合などがあれば、諸構文のZ座標を最適化しましょう。
キロポストの座標もこの段階で合わせます。高架化工事などの影響でBVE内Z座標とキロポストが合わないのはとてもよくあることですが、この段階ではシナリオがどこからどこまでなのか固まっているはずなので帳尻合わせします。
5-3-6.風景オブジェクトの配置
この段階では多分Z座標が大幅に狂うおそれがないので、じゃんじゃんオブジェクトを配置していきましょう。
5-3-7.(上級者向け)対向列車の配置
運用調査するなどして必要な情報を持っていたら対向列車の配置に挑戦するのもいいでしょう。
5-4.マニュアル
まずは適当に書いてみて、AIに添削させましょう。
手順書の体をなした文章ができているならAIにスライド生成させてもそれなりのものが出てくるかも。
実際の画面とアイコンを用いて視覚的に示しましょう。
もちろん自力でデザインしても全然OK
5-5.パッケージング
5-5-1.インストーラ作成
頒布ファイル作成作業用ディレクトリに必要なファイルをコピーし、セキュリティチェックの後、インストールファイルを作成します。
ZIP形式の場合はインストール手順書を同梱しましょう。
依存関係(動作に必要な他のBVEデータ 共通ストラクチャなど)を確認し、インストール前に円滑な導入ができるよう示しましょう。
ライセンスを明確にしましょう(そうしないと他の方があなたのBVEシナリオの話題に触れることを避けてしまう恐れがあります。ただしライセンスを厳格にしすぎると逆にあなたを縛ることもあるので気を付けましょう)。
事業者により「公共物は公共物として扱ってください」「このデザインの権利は全てわが社に属する」など異なるので、現物所有者の意思表示をよく確認してください(発車メロディーとか非常に面倒なケースが多いです)。契約書は全部読んで理解してから同意しましょうみたいなみっともないことは書きたくないよぉ。
インストールテストは必ず複数環境で行いましょう。
5-5-2.共有ページ
「Bve trainsim 制作・公開ガイドライン」を守りましょう
わかりやすいタイトル(BVEを知らない人でも意味が通じる)を掲げましょう
スクリーンショット・デモ動画・「今すぐダウンロード」
機能説明
システム要件
インストール手順
サポート
公開したらテストとプロモーション(SNS等宣伝)しましょう。
プレイヤーさんとつながるまでがBVEシナリオ制作です。
完成例ですか?作る時間なかったので、どなたかのプレイ動画をテキトーにご参照いただければ・・・
以上「シナリオ制作の流れ」でした。
6.よくある詰まり方と対処法
だいたいいつも詰まった側も対処法提示する側もだるいなあと思ってるので投げやりな感じになっちゃってますがご容赦頂ければ幸いです。
取材対象までのアクセスが大変
ターゲットの沿線に住みましょう。
取材したサウンドデータが乱れている
収音レベルが低すぎる → 機材自体のわずかな電位揺らぎもノイズになり、サウンドの中で無視できない大きさになってしまいます。可能な限り収音レベルは高くしましょう。理想は最大位相約-6dB程度ですが、室内収録ではなく自然環境下での収録においては非常に強い音が入る場合があります。私の音源を適当に開けてみたら最高速度で走行中のジョイント音最大位相約-12dB程度で調整されていました。適切なレベルは機材により異なり、収音テストを多岐にわたる条件下で繰り返し行うことで見出すことができます。まあフロート録音したらはじめから問題起きないんですけどね。
収音レベルが高すぎる → 音量が記録フォーマットからはみ出したことで最大位相に張り付く形で潰れノイズとして聞こえる状態になってしまいます。
音が曇る → MP3録音では普通の人にはわかりにくい高音がカットされるため原理的に避けられない音の曇りが発生します。圧縮率が高ければカットされる音も多くなり劣化が目立つようになります。収音機材の解像度もボトルネックになります。対処法は1.確保できた音源で満足する 2.PCM録音可能な機材を導入する 3.高品質のマイクを導入する 4.フロート録音可能な機材を導入する といったことが挙げられます。
録音設定が不適切 → ノイズカット機能は放送を収録する場合以外むやみに使わない。入力感度自動調整は必ずオフにする。
人の話し声が入っている → プライバシーに関わるのでその音源はお蔵入りして次のカットを収録しましょう。自分はどうなんやと私の記録をひいてみたら100カット/年くらい取ってそこから素材を作ってました。
自分では乱れているのがわからないけれど人に指摘された → 完璧な耳を持つ人など実際にはおらず、認知の個性による場合が非常に多いです(視覚や味覚と同じ)。一方、品質を徹底的に追求した音源に触れたことが無ければわからないこともあります。この話題を突き詰めると某料理マンガの「究極のメニューVS至高のメニュー」みたいなことになりかねないのでほどほどにしたいですが、まあ個人の資金力で入手可能な機材で追求しようとしたらそれだけで一生が終わってしまうので今手持ちの機材でトレーニングされひらめきを得たら次のステップに進まれるのがよいのではないでしょうか。
人が多すぎて取材が難しい
路線によりますが、私の作品モチーフだと一年の中で人が少ないのは1月1日・4月1日・8月15日・12月31日・2月11日、逆に多いのは11月23日・10月1日・4月7日といったように日によって大きく変動します。いろいろ要因はありますが分析して狙いましょう(ただし近年では列車ごとの乗車率平準化がかなり進んでおり、空いている列車はダイヤ改正ごとに運用取りやめとなるケースが多いです。例えば、昔は京阪の終夜運転午前3時~5時で非常に空いている急行がいっぱい走っていましたが、2022-2023終夜運転ダイヤからは種別も本数も需要とかなりマッチしていて空いている急行はゼロになったりしています)。
完成する気がしない
要求品質の設定が高すぎるのかもしれません。まずは完成することが大事なので、できないことはやらない仕様に改めましょう。BVEシナリオ制作はとにかく面倒で最終的に自分との戦いになりがちなので、うまく負けるが勝ちかなと。
モチベが維持できない
BVEシナリオ制作はアウトプット活動なので、インプットを超えることは無理です。気持ちいいインプットを100倍くらい吸いましょう。てか100倍でも足りないかも。
時間足りない
面倒なことはAIにやらせて時間を作りましょう
ファイル名とかの命名ネーミングセンスなさすぎて作ってて萎えるんですがどうしましょう
プレイ中見えないから気にしないでください 人を傷つける感じのはアカンけど
作品の質を上げたいけれど何をしたらいいか分からなくてどうしたらいいか困っている
素材の質を上げましょう。素材の品質より上の作品はフィクションに振り切らない限り出せません。素材の質が現時点でそれ以上にできないのであれば、作品をシェアしましょう。それでその作品は0点から50点になり、あとは流れに身をゆだねれば自然と100点に近づいていきます。
とにかくわからん。誰か教えて
オフ会行くのが手っ取り早いです。「誰か教えて」がイラスト描いている時なら人口が多いから気の合う人とつながって学ぶとか本を買うとかできますが、BVEシナリオ制作は現時点でそれができる状況にありません。ゲームであればデッキを晒せばヒマな人がアドバイスくれる場合もありますがBVEシナリオ制作だとデッキを晒すに相当することの手間が大きすぎて無理筋です。SNSでサーバー土下座して教えを乞うのもお互いどんな人物かよくわかっていないまま話を進めて事故るリスクがあるのでお勧めできない・・・というかぶっちゃけ止めに入りたい。そんな感じです。
前提知識多すぎてどうすればいいかわからないから一つだけ選ぶとしたらどれですか
物理。
以上「よくある詰まり方と対処法」でした。
7.完成後はどうするか
BVEシナリオ制作を一通りやってみた時には既に人生の何割かをベットしたはず。
後生に禍根を残す事態を可能な限り避けるには、一連の活動に意味づけして道を違えぬよう次に進むのが寛容かと存じます。
BVEシナリオ制作はあなたと関係者にとって何だったのか?
ライフワーク?
→ 生き様。(制作のやり方・社会貢献・教育・環境活動)
ライクワーク?
→ 快楽として。
ライスワーク?
→ 生活費を得るため。
(私の場合はライフワークとライクワークにまたがっていてややライクワークに寄ってる感じですね)
BVEシナリオ制作で何を積み上げられたか?これからの見込みは?
人とのつながり?
技能蓄積?
有形資産?
気持ちを整理して次なる活動に進みましょう。
もちろん「数をこなせば質は後からついてくる」みたいな考え方で本章の課題を後回しにしてさっさと次回作に取り組む、というやり方もいいと思います。
しかし本稿執筆時において、あらゆる分野での創作物・表現者が供給過多どころか飽和を通り越している状況にあると私は認識しており、その状況下ではどんないいものを作って公開しても99%誰にも見向きされないと予想されます。20年以上前私がコミケに初めて参加した時に会場で起こっていたことがリアル日常にもサイバー空間にも飛び出してきたのが今起こっていることだな、と受け取っています。
ゆえに、やりたいことに飛びつくのはいいじゃない、せやかてその後はどうするの?そしてその後は?と問いを提示させていただきました。
私自身もしばらく新作を一般公開していないですが、それは私がBVEを始めた頃に比べて鉄道というもののあり方自体が急激に変化してしまい(例えば京阪間三社競争論など平成中期時点で既に過去のものになっていたにも関わらずそれが続いているかのような喧伝が専門誌でずっと出され多くの人の混乱した反応を招いていて日常的に利用する人達と大きな温度差が生じており2024年現在も拡大し続けていることなど)、その中でどのあたりに落ち着こうかイメージはぼんやりあるんですけれども、前に踏み出して得られることが期待できるものと予想されるリスクとを天秤にかけたら引き伸ばしの答えが出続けていることに因る結果です。これからもっと視野を広く持ち、自分の道を進めるには今どう行動するかしっかり見据えて歩んでいきたいと思います。
おわりに
BVEシナリオをつくるには、と簡単に書き出してはみたものの、簡単とはとても言えませんね。だからこそ書いてみた甲斐がありました。
本稿中では誰にでも必要不可欠とは限らないオプションも提示しましたが、制作中につまづいて抜け出し方が全く見えないケースを数えきれないくらい見てきたのでこれくらい出しといていいのかなと。
意見感想改善案その他文句などがありましたらぜひ「BVEシナリオをつくるにはをつくるには」を出してみてください。
本稿は行き当たりばったりで書いたつもりではなく、じつは本稿で示した手順で制作されたシナリオがあります。それはJR琵琶湖線です(ただし、本稿説明の例には話の通りやすさを重視して別の素材を使用しています)。
10年前から「BVEシナリオをつくるには」は出したいと思っていたのですが、何回も作ってはボツにしては、を繰り返し今にいたります。制作道具紹介は2024年に合わせてアップグレードしましたが、完成にこぎつけるための考え方は変わっていません。そしてBVEが現在のあり方でい続ける限りは「完成させるにはどういう道筋があるかという概念は変わらない」「道具は分野ごとにブレイクスルーがある都度アップグレード」という姿勢が続くでしょう。もし本稿に続編があるとすれば、各章さらにかみくだいた解説をする、アップグレードの解説をする、といったものになると思います。
BVEシナリオをつくるのはすっごい面倒でだるいですが「BVEシナリオをつくるには」をつくるのもまたすっごい面倒でだるいです。しかし一旦着地してみようかと思い、ちょっと走ってみました。
私がBVEシナリオを初めて作った時から今に至るまで俯瞰して、プレイヤーの皆さんのニーズは多様化細分化しており、今後この傾向がさらに加速すると予想されますが、今残っているもの、今あるもの、これから出てくる作品を通して人々が心を寄せ合い、文化が途切れることなく安定的に続いていくことを望みます。