※ 追記
あ、そういえば実行中でもmouse()
でマウスから位置取って、mset(x,y,id)
でデータ書き込めるやん。sync()
でデータ保存もできますし、ってことで
これはもう簡易オートタイルみたいなものということでひとつ。
2方向境界タイル、2.25方向境界タイル、4方向セミオートタイル‥‥
TIC-80もってくれよ!!‥8方向semi オートタイルだっ!!!
(界王拳っぽく)
というわけで8方向セミオートタイル実装に挑戦しました。
生成元タイルはこんな感じ。
上から境界なし、横方向境界、縦方向境界、全方向境界、斜めのみ境界
そう、元タイルを4分割して、それぞれに2.25方向境界の処理を施すことにしたらすっきりしました。同じタイルをコピーで5つならべてから境界の加工をすればいいので、タイルを作るのも少し楽になりました。
(ウディタ(?)あたりと似た形式に)
ペタペタ配置して実行
じゃん!
見た目がいまいちなのはタイルのデザインのせい‥
自動生成されたタイルはこんな感じ。3列かぁ‥
生成方法ですが、パターンは47種類らしいです。こちらを参考にさせていただきました。
それぞれのパターンで、8方向のうち、どの方向の境界がONかは画像を見てそのままデータとして記載しました。
後は処理するエリアに応じて、その中から3つを抜き出して(例えば右上を処理しているなら、必要なフラグは右と上と右上のフラグのみ)どれだけ下にずらすかを算出してコピー実施。
で、表示時に隣接タイルとの差異のパターンは8方向なので2^8の256通り。
それが47種類のどれに対応するか‥‥?
うーん、ううん? あーうー‥ うん、全部書こう!(思考停止)
力こそパワー。手を動かしゃいいねん!
-- title: game title
-- author: game developer
-- desc: short description
-- script: lua
OFF,ON=1,2
LU,RU,LD,RD,U,D,L,R=1,2,3,4,5,6,7,8
autoidx={
[0]={OFF,OFF,OFF,OFF,OFF,OFF,OFF,OFF},
{ON,OFF,OFF,OFF,OFF,OFF,OFF,OFF},
{OFF,ON,OFF,OFF,OFF,OFF,OFF,OFF},
{OFF,OFF,ON,OFF,OFF,OFF,OFF,OFF},
{OFF,OFF,OFF,ON,OFF,OFF,OFF,OFF},
{ON,ON,OFF,OFF,OFF,OFF,OFF,OFF},
{OFF,OFF,ON,ON,OFF,OFF,OFF,OFF},
{ON,OFF,ON,OFF,OFF,OFF,OFF,OFF},
{OFF,ON,OFF,ON,OFF,OFF,OFF,OFF},
{ON,OFF,OFF,ON,OFF,OFF,OFF,OFF},
{OFF,ON,ON,OFF,OFF,OFF,OFF,OFF},
{ON,ON,ON,OFF,OFF,OFF,OFF,OFF},
{ON,ON,OFF,ON,OFF,OFF,OFF,OFF},
{ON,OFF,ON,ON,OFF,OFF,OFF,OFF},
{OFF,ON,ON,ON,OFF,OFF,OFF,OFF},
{ON,ON,ON,ON,OFF,OFF,OFF,OFF},
{OFF,OFF,OFF,OFF,ON,OFF,OFF,OFF},
{OFF,OFF,ON,OFF,ON,OFF,OFF,OFF},
{OFF,OFF,OFF,ON,ON,OFF,OFF,OFF},
{OFF,OFF,ON,ON,ON,OFF,OFF,OFF},
{OFF,OFF,OFF,OFF,OFF,ON,OFF,OFF},
{ON,OFF,OFF,OFF,OFF,ON,OFF,OFF},
{OFF,ON,OFF,OFF,OFF,ON,OFF,OFF},
{ON,ON,OFF,OFF,OFF,ON,OFF,OFF},
{OFF,OFF,OFF,OFF,OFF,OFF,ON,OFF},
{OFF,ON,OFF,OFF,OFF,OFF,ON,OFF},
{OFF,OFF,OFF,ON,OFF,OFF,ON,OFF},
{OFF,ON,OFF,ON,OFF,OFF,ON,OFF},
{OFF,OFF,OFF,OFF,OFF,OFF,OFF,ON},
{ON,OFF,OFF,OFF,OFF,OFF,OFF,ON},
{OFF,OFF,ON,OFF,OFF,OFF,OFF,ON},
{ON,OFF,ON,OFF,OFF,OFF,OFF,ON},
{OFF,OFF,OFF,OFF,ON,OFF,ON,OFF},
{OFF,OFF,OFF,ON,ON,OFF,ON,OFF},
{OFF,OFF,OFF,OFF,ON,OFF,OFF,ON},
{OFF,OFF,ON,OFF,ON,OFF,OFF,ON},
{OFF,OFF,OFF,OFF,OFF,ON,ON,OFF},
{OFF,ON,OFF,OFF,OFF,ON,ON,OFF},
{OFF,OFF,OFF,OFF,OFF,ON,OFF,ON},
{ON,OFF,OFF,OFF,OFF,ON,OFF,ON},
{OFF,OFF,OFF,OFF,OFF,OFF,ON,ON},
{OFF,OFF,OFF,OFF,ON,ON,OFF,OFF},
{OFF,OFF,OFF,OFF,OFF,ON,ON,ON},
{OFF,OFF,OFF,OFF,ON,OFF,ON,ON},
{OFF,OFF,OFF,OFF,ON,ON,OFF,ON},
{OFF,OFF,OFF,OFF,ON,ON,ON,OFF},
{OFF,OFF,OFF,OFF,ON,ON,ON,ON}
}
FS={
{L,U,LU},{R,U,RU},{L,D,LD},{R,D,RD}
}
OFFSET={{{0,4},{2}},{{1},{3}}}
numautoid={
[0]=0,1,2,5,3,7,10,11,4,9,8,12,6,13,14,15,
16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,
20,21,22,23,20,21,22,23,20,21,22,23,20,21,22,23,
41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
24,24,25,25,24,24,25,25,26,26,27,27,26,26,27,27,
32,32,32,32,32,32,32,32,33,33,33,33,33,33,33,33,
36,36,37,37,36,36,37,37,36,36,37,37,36,36,37,37,
45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
28,29,28,29,30,31,30,31,28,29,28,29,30,31,30,31,
34,34,34,34,35,35,35,35,34,34,34,34,35,35,35,35,
38,39,38,39,38,39,38,39,38,39,38,39,38,39,38,39,
44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46
}
-- common function from TIC-80 wiki
function sset(x,y,c,idx)
local id=idx or 0
local addr=0x4000+id*32
poke4(addr*2+x%8+y%8*8,c) end
function sget(x,y,idx)
local id=idx or 0
local addr=0x4000+id*32
return peek4(addr*2+x%8+y%8*8) end
-- my function
function make8dtile(chipid,tileid)
local cid,tid=chipid or 256,tileid or 1
for i=0,46 do
local fl=autoidx[i]
for xx=0,7 do
for yy=0,7 do
local anum=1+(xx<4 and 0 or 1)+(yy<4 and 0 or 2)
local f1=fl[FS[anum][1]]
local f2=fl[FS[anum][2]]
local f3=fl[FS[anum][3]]
local c=sget(xx,yy,cid+OFFSET[f1][f2][f3]*16)
sset(xx,yy,c,tid+i)end end end end
rm8dtile=function(tile,x,y)
local dLU=(tile==mget((x-1)%240,(y-1)%136))and 0 or 1
local dRU=(tile==mget((x+1)%240,(y-1)%136))and 0 or 2
local dLD=(tile==mget((x-1)%240,(y+1)%136))and 0 or 4
local dRD=(tile==mget((x+1)%240,(y+1)%136))and 0 or 8
local dU=(tile==mget(x%240,(y-1)%136))and 0 or 16
local dD=(tile==mget(x%240,(y+1)%136))and 0 or 32
local dL=(tile==mget((x-1)%240,y%136))and 0 or 64
local dR=(tile==mget((x+1)%240,y%136))and 0 or 128
local daid=numautoid[dLU+dRU+dLD+dRD+dU+dD+dL+dR]
return (tile==0)and 0 or tile+daid end
testinit=function()
make8dtile()
make8dtile(257,48)
make8dtile(258,96)
make8dtile(259,144)
make8dtile(260,192)
chipset={0,1,48,96,144,192}
i=1
sync(0,0,true)
end
testinit()
function TIC()
cls(13)
map(0,0,30,17,0,0,12,1,rm8dtile)
if btnp(4,1,20) then i=i%#chipset+1 end
x,y,p=mouse()
spr(496,x-x%8,y-y%8,0)
spr(chipset[i],208,8,12,3)
spr(497,208-4,8-4,12,4)
if p then mset(x//8,y//8,chipset[i])end
if btnp(5,1,20) then sync(0,0,true)end
end
どのパターンに対応するかは、エクセルを使って探しました。
境界パターンが同じなら、パターン番号を表示するようにしておきます。
(対応パターンがない方が多いので最初はエラーが大半です)
で、例えば上に境界ありなら、右上、左上のフラグが関係なくなるのでこれらをOFFに、
というのを繰り返していくと、どれかのパターンに当てはまってエラーから47のうちのどれかになります。
こんな作業をやってるうちに、「ビットマスク(?)をうまく使えばプログラムで処理できるのかな?」
と思いましたが、絶対このまま作業した方が速いだろうってことでそのまま。
結局は手作業なのでどこかにミスがあるかもしれません。
今回はテーブルに二分木っぽくデータを格納して、フラグ(1 or 2) table[flag1][falg2][flag3]みたいな感じで必要なデータを取り出すみたいなことを試してみました。
if文重ねるよりすっきりする気はするのですが、後からみてちゃんと理解できるかは心配です。