pyxelでシミュレーションゲームを作る(4-1)
前回は領地の建築に「改修」コマンドを追加したところまで作りました。そろそろこのゲームの目的というか「プレイヤーの立場」を明確にして、イベントなども作っていきたいと思います。
そんなこんなで考えたのですが、信長の野望のような「国盗り」ゲームはどうにも作れそうにないので、もっと小さな規模でやってみようと思います。具体的には「プレイヤーは尾張と三河の間あたりにいる小さな豪族」で「織田と今川が対立する中うまいこと生き残っていく」ことを目標にします。織田信長やら今川義元にいろいろいびられながらも、何とかやり過ごし、自分の領地を守っていくことを目指します。
それでは始めていきます。
前回のnoteは以下になります。よろしければご参照ください。
さて、ゲームの目的は決まったので、具体的にどのように実現していくかを考えます。まずは第一段階として、外交イベントを作ります。外部の大名家から使者が来てなんか言ってくわけですが、今回は「資源提供を求めてくる」イベントを作ろうと思います。具体的には「戦に備えて兵糧をくれ」みたいなことを言ってくるわけです。承諾すると有効度が上がり、断ると下がります。
まずは大名を登場させるためのクラスを新設します。
class Daimyo:
def __init__(self,a,b,c,d,e,m,v):
self.kome = a
self.sikin = b
self.heisi = c
self.yuko = 50
self.sei = d
self.mei = e
self.msg = m
self.event_cnt = v
self.event_flug = False
def Turn_change(self,d):
if d == 1:
self.kome += 300
self.sikin += 200
self.heisi += 100
elif d == 2:
self.kome += 500
self.sikin += 500
self.heisi += 200
self.event_cnt += randint(5, 10)
if self.event_cnt >= randint(51, 100):
self.event_flug = True
▲Daimyoクラスです。
プレイヤーと同様に「米・資金・兵士」の3要素があり、その他「友好度」や「姓」、「名」などがあります。msgにはセリフを格納しています。このあたりの情報は外部モジュールに以下のように記載しています。
def oda():
d = {
"kome":2000,
"sikin":1000,
"heisi":1000,
"sei":["O","DA"],
"mei":["NO","BU","NA","GA"],
"msg":{"0-1":["SU","MA","NA","I","GA",],
"0-2":["I","KU","SA","NI","MU","KE","TE"],
"0-3":["I","I","KA","GE","NN","NI",],
"1-1":["HI","yo","U","RO","U","NO",],
"1-2":["SI","KI","NN","NO",],
"1-3":["HE","I","SI","NO",],
"2":["TE","I","KI","yo","U","WO"],
"3-1":["O","NE","GA","I","SI","TA","I"],
"3-2":["TA","NO","MI","TA","I"],
"3-3":["SE","YO",],
"4":["KA","NN","SI","ya","SU","RU"],
"5":["SO","U","KA",".",".","."],
"6":["MU","RI","JI","I","HA"],
"7":["SU","MA","I",],}
}
return d
▲外部モジュール「Game_status.py」のoda関数です。信長に関する情報があり、本体側から呼び出した際に戻り値として返します。
セリフが入っているmsgは辞書型になっており、各キーとセリフが紐づいています。
Daimyoクラスの説明に戻ります。
def Turn_change(self,d):
if d == 1:
self.kome += 300
self.sikin += 200
self.heisi += 100
elif d == 2:
self.kome += 500
self.sikin += 500
self.heisi += 200
self.event_cnt += randint(5, 10)
if self.event_cnt >= randint(51, 100):
self.event_flug = True
▲Daimyoクラス内のTurn_change関数です。引数として大名を区別する「d」を持たせています。
とはいっても今は信長と義元しかいないので1(信長)か2(義元)しか入りません。
この関数はターンが経過する際の大名の動きを制御します。まずは引数dによって分岐させ、各大名の資源を増やしています。織田家よりは今川家の方が大きいでしょうから、d == 2の場合の方が増分が大きいです。
その後、event_cntにランダムで数値を足しあげます。event_cntと51~100のランダム数値の比較で、event_cntが大きかったらイベント用フラグを立てます。ターンが経過するごとにイベント発生の可能性が高くなる仕組みです。
次に実際にイベントフラグが立った際の動きを作ります。
#Turn change
elif self.window_ctr == 98:
if pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON):
x = pyxel.mouse_x
y = pyxel.mouse_y
if ((64 < x < 128) and (114 < y < 128)):
if ((self.daimyo1.event_flug == True) and
(self.daimyo2.event_flug == True)):
self.daimyo_flug = randint(1, 2)
self.window_ctr = 101
self.msg_num = randint(1, 3)
elif self.daimyo1.event_flug == True:
self.daimyo_flug = 1
self.window_ctr = 101
self.msg_num = randint(1, 3)
elif self.daimyo2.event_flug == True:
self.daimyo_flug = 2
self.window_ctr = 101
self.msg_num = randint(1, 3)
else:
self.window_ctr = 0
▲本体のターン経過部分のコードです。
Daimyoクラスのインスタンスであるdaimyo1とdaimyo2のevent_flugによって分岐します。どちらのフラグも立っているならランダムで、そうでないならフラグの立っている方の大名の番号をdaimyo_flugに代入して、window_ctrを101にします。101番のウィンドウはイベント発生を知らせるウィンドウで今回新規作成しました。msg_numが1~3のランダムになっているのは「米・資金・兵士」のどれかをランダムで要求するようにしたかったからです。
▲101番の外交ウィンドウその1です。信長がやってきました。本来であればこんな小さな勢力相手に大名自ら出てくるわけはないと思いますが、今回は見た目の派手さを取ります。
やっぱり有名どころに出てきてもらいたいのです。
コードは以下のようになっています。
#Gaiko
elif self.window_ctr == 101:
if pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON):
x = pyxel.mouse_x
y = pyxel.mouse_y
if ((64 < x < 128) and (114 < y < 128)):
self.window_ctr = 102
self.answer_tgt = 116
▲update関数内の101番ウィンドウに関するコードです。「りょうかい」が押された際に102番ウィンドウに遷移します。answer_tgtは次の画面で使う要求に対する返答の初期カーソル位置です。
#Gaiko
elif self.window_ctr == 101:
pyxel.rect(0, 80, 128, 46, 0)
pyxel.rectb(0, 80, 128, 46, 7)
if self.daimyo_flug == 1:
sei = self.daimyo1.sei
mei = self.daimyo1.mei
self.Draw_fonts(sei, 5, 85)
self.Draw_fonts(mei, 30, 85)
elif self.daimyo_flug == 2:
sei = self.daimyo2.sei
mei = self.daimyo2.mei
self.Draw_fonts(sei, 5, 85)
self.Draw_fonts(mei, 45, 85)
self.Draw_fonts(self.text_list["114"], 85, 85)
self.Draw_fonts(self.text_list["115"], 5, 95)
pyxel.rect(0, 114, 64, 14, 0)
pyxel.rectb(0, 114, 64, 14, 7)
pyxel.rect(64, 114, 64, 14, 0)
pyxel.rectb(64, 114, 64, 14, 7)
self.Draw_fonts(self.text_list["107"], 69, 117)
▲draw関数内の101番ウィンドウに関するコードです。ここはごちゃごちゃ書いてますがやってきた大名の名前を表示させている以外は特に何もしていません。
次の画面が実際に交渉が行われるメインの場所になります。
▲のぶながにカツアゲされています。これで断ったら機嫌悪くなるんだから、自分で作っておいてなんですけど、勝手な奴だと思いますね。
次回はこの画面から再開したいと思います。
ここまで読んでいただき、ありがとうございました。
ここまで読んでいただきありがとうございます!