【第1章】車両で遊ぼう
第7回 パンタグラフを上げ下げしよう
その3 1つのキーでパンタグラフを上げ下げしよう
カウンタとなる変数を使ってみましょう。
【使用するPython命令】global
関数内からグローバル変数を扱うための宣言です。
【使用するPython命令】%
剰余演算子で、割り算してその余りを返す。
前回は4つのキーを使ってパンタグラフの4つの状態を再現しましたが、今回はそれを1つのキーを押すたびに変化していく形にしてみましょう。
【やってみよう】「親子で学ぼう用レイアウト(2初期状態).vrmnx」を開き、編成「TRAIN_11」にスクリプトをこのように書こう。書くのが大変ならコピペしよう。完成品は「親子で学ぼう用レイアウト(7-3).vrmnx」です。
#OBJID=11
import vrmapi
keyCount = 0
def vrmevent_11(obj,ev,param):
if ev == 'init':
car = obj.GetCar(1)
car.SetPantograph(0,False)
car.SetPantograph(1,False)
obj.SetEventKeyDown('X',106)
(中略)
elif ev == 'keydown':
global keyCount
keyCount = keyCount + 1
surplus = keyCount % 4
car = obj.GetCar(1)
if param['eventUID'] == 106:
if surplus == 1:
car.SetPantograph(0,True)
car.SetPantograph(1,False)
if surplus == 2:
car.SetPantograph(0,False)
car.SetPantograph(1,True)
if surplus == 3:
car.SetPantograph(0,True)
car.SetPantograph(1,True)
if surplus == 0:
car.SetPantograph(0,False)
car.SetPantograph(1,False)
vrmapi.LOG(surplus)
【解説】さて4つのキーをまとめて1つのキーにするには1回目、2回目、3回目、4回目と回数をカウントする必要があります。また4回目の次は5回目ですが、プログラムにはまた1回目として認識させなければなりません。
では解説です。まず「import vrmapi」の次に「keyCount = 0」が来ています。グローバル変数ですね。あまり使うべきではないのですがカウンタを作る上ではグローバル変数の方が簡単なので一旦グローバル変数で作ります。あとでこれをグローバル変数を使わない形に改造したものも紹介します。
'init'イベント内では前回やったことが書かれ、初期状態はパンタグラフが両方下降した状態になっています。そしてXキーで呼び出される'keydown'イベント内ではまず「global keyCount」と関数外で宣言したグローバル変数をこのイベント内で使うことが宣言がされています。初期値は0で「keyCount = keyCount + 1」を実行する度に1が足されていきます。ここでグローバル変数を使わないとどうなるかというと
def vrmevent_11(obj,ev,param):
keyCount = 0
if ev == 'init':
またはこうしても
elif ev == 'keydown':
keyCount = 0
keyCount = keyCount + 1
となるので毎回カウンターがリセットされてしまいカウンターの役目が果たせません。ですのでグローバル変数を使う必要が出てきてしまいます。その後の「surplus = keyCount % 4」は変数surplusにカウンタの数値を4で割った余りを代入しなさいという命令です。よって1回目は1÷4で答え0余り1、2回目は2÷4で答え0余り2、3回目は3÷4で答え0余り3、1回目は4÷4で答え1余り0、5回目は5÷4で答え1余り1・・・となって1、2、3、0を繰り返していきます。よってそれを「if surplus == 1:」などで場合分けしてパンタグラフの昇降を実行しています。またその1、2、3、0をスクリプトLOGウィンドウで確認できるように「vrmapi.LOG(surplus)」が「if param['eventUID'] == 106:」と同列の部分に追加されています。
【実践】それでは「運転」を押してビューワーを起動させましょう。Xキーを押して順番に変化していれば成功です。スクリプトLOGウィンドウも表示して動作を確認してみましょう(^^)/
【使用するVRMNX命令】色々な部品にある命令:GetDict()
dict型メンバー変数を参照します。
【発展】グローバル変数を使わない方法です。完成品は「親子で学ぼう用レイアウト(7-3dict).vrmnx」です。
#OBJID=11
import vrmapi
def vrmevent_11(obj,ev,param):
di = obj.GetDict()
if ev == 'init':
di['keyCount'] = 0
car = obj.GetCar(1)
car.SetPantograph(0,False)
car.SetPantograph(1,False)
obj.SetEventKeyDown('X',106)
(中略)
elif ev == 'keydown':
di['keyCount'] = di['keyCount'] + 1
surplus = di['keyCount'] % 4
car = obj.GetCar(1)
if param['eventUID'] == 106:
if surplus == 1:
car.SetPantograph(0,True)
car.SetPantograph(1,False)
if surplus == 2:
car.SetPantograph(0,False)
car.SetPantograph(1,True)
if surplus == 3:
car.SetPantograph(0,True)
car.SetPantograph(1,True)
if surplus == 0:
car.SetPantograph(0,False)
car.SetPantograph(1,False)
vrmapi.LOG(surplus)
【解説】辞書(dictionary)型変数diを使います。以前から出てきていますが改めて、辞書型とは{}の中にキーと値の組み合わせが並んだ変数で{キー1:値1,キー2:値2,キー3:値3・・・・}となっています。そしてdi['キー1']と書くと値1を返します。「if ev == 'init':」の前の位置(関数内で有効となる位置)で「di = obj.GetDict()」を書いて変数diを作成し、'init'イベントで「di['keyCount'] = 0」を書いてkeyCountというキーに0を代入(初期化)します。以降はグローバル変数と同様に扱います。こちらが理解出来たらカウンタにはグローバル変数は使わずに辞書型変数を使うようにしましょう。
【余談】なぜ辞書型変数なら大丈夫なのか
def vrmevent_11(obj,ev,param):
di = obj.GetDict()
if ev == 'init':
di['keyCount'] = 0
ここですね。'init'の前で辞書型変数diを定義してvrmevent_11内にスコープがあり、'init'の後で辞書型変数diのキー'keyCount'を初期化しているから初期化は1回しか行われないという点です。di = obj.GetDict()はイベントが発生するたびに実行されますからここにkeyCount = 0みたいな普通のローカル変数を置くと毎回初期化されてしまいますが、辞書型変数定義はここにおいても値は影響を受けません。非常に上手いやり方ですが、これを考え出したのは私ではなく「「鉄道模型シミュレーターnx」で学ぶpythonプログラミング」の著者である角卓さんです。
←戻る 目次 進む→