それはさておき、プログラミングの方は4度目の再走(初めから書き直し)経て、ある程度形になってきたので、色々考えたりしたことや、コーディングの方針の変遷を記録しておくことにします。
前提
- 「TIC-80」上の「Lua」でスクリプトを書く
- 筆者は使える言語がない
FizzBuzzが書けるのがLuaとMSX-BASICのみ。
学生の時に習った scheme や Pascal (TurboPascalを使っていたような?)はすっかり忘れました。C言語とJavaScript(オールドスタイル)は一応読めば処理の流れくらいはおおまかに理解できることがある程度です。
よって以降の記述は「こうすればいいよ」という解説や提言ではなく、
自分はこの環境でこのように記述している、という記録にすぎないということです。
(用語も間違いだらけだと思います)
「国盗りす」基本の基本
上のgif動画は自分の当時の脳内国盗りすを再現したものです。
以下基本的な仕様
- 「自機」(赤いの)は空を漂っている「兵糧」(白いの)をくっつけることができる
- 「兵糧」はある程度の塊で移動や接触判定がある
- 「自機」の管理下でない「兵糧」同士の接触判定はない
- 「自機」管理下の「兵糧」は「自機」を中心に「90度右回転」と「左右反転」が可能
兵糧群のデータ構造
とりあえず、この兵糧が集まった塊をデータで表現する必要があると思いました。
そこでテトリスなどのゲームの解説を参考にしようとしたのですが、
だいたいが、(テトロミノなどの)ピース、フィールドを二次元配列で表現していました。
ただし、兵糧群の大きさは固定ではないことからこの方法ではしんどいと思い、
基準位置とそこからの相対位置の組で表すことにしました。
下の図(に近いもの)は2回目のリライト時に書きました。
それまでなんとなくコードだけで書いていて混乱したので(遅いやろ)
基本のデータ構造は当初から変わっていないのですが、
最初は基準位置表記は x と y でした。
ただ対応させるフィールドが二次元リストなので、1行目、1列目、と指定する
表として考えた方がよいと思い、行と列で表すことにしました。
x,yとしていたときは表示と合わないので マイナス1したりと
混乱していましたが、基本的にはcol,rowで処理を進めていき、
表示など x,y の座標に変換する際に 1 を引いたり マスのサイズをかけたりと
いった処理が必要、ということを意識するようになり、混乱が減りました。
( counting のリストと offset の座標は別物 )
この表記と意識変更は3回めのリライト時(だから遅いって)
もう少しデータ構造を分かりやすく書くならこんな感じですかね。
(markdownで書こうとして挫折)
操作関数はこのような感じに
-- piece function
pce={}
pce.make=function (vec,column,row,dir,h)
local vec=vec or {{0,0}}
local c,r=column or 1,row or 1
local dir,h=dir or 0,h or HEIGHT
local p={}
p.col,p.row=c,r
p.dir,p.h=dir,h
p.size=#vec
for i,v in ipairs(vec) do
local d={v[1],v[2]}
table.insert(p,d)
end
return p
end
pce.rotate=function(p,n) -- piece rotate right 90 degree n times
local n=n or 1
n=n%4
for j=1,n do
for i,v in ipairs(p) do
v[1],v[2]=-v[2],v[1]
end
end
end
pce.reverse=function(p,vertical) --piece flip
local vtcl=vertical or false
if vtcl then
for i,v in ipairs(p) do
v[1],v[2]=v[1],-v[2]
end
else
for i,v in ipairs(p) do
v[1],v[2]=-v[1],v[2]
end
end
end
他の言語を使用している方は「クラスとか定義しないのか」とか
「list と hash を混ぜて使うのか」とか感想を持たれるかも知れません。
Lua でも table にfunctionを持たせてオブジェクト指向っぽい書き方が
できるらしいのですが、オブジェクト指向自体よく理解していないため
今回は使っていません。
とりあえず、Lua の標準ライブラリの table 操作関数と同様の表記、動作を
するようなものを目指しました。(3回目のリライト時)
- 操作対象を引数で受け取る
- データを書き換える(操作後のデータを返り値で返すのではなく)
- 操作関数をテーブルにまとめる(今回は pce テーブルにまとめた)
結構表記は変更しています。たとえば pce.reverse() だと
- hyourou_hasoteso (1回目リライト時)
- piece_reverse (2回目リライト時)
- piece.reverse (3回目リライト時)
- pce.reverse (4回目リライト時)
「国盗りす」原作にならってツッコミどころが満載です。
とりあえず今回はここまで。