LoginSignup
1
0

More than 5 years have passed since last update.

【TIC-80】8方向簡易オートタイル

Last updated at Posted at 2018-10-25

※ 追記

あ、そういえば実行中でもmouse()でマウスから位置取って、mset(x,y,id)でデータ書き込めるやん。sync()でデータ保存もできますし、ってことで

autotile8.gif

これはもう簡易オートタイルみたいなものということでひとつ。


2方向境界タイル、2.25方向境界タイル、4方向セミオートタイル‥‥
TIC-80もってくれよ!!‥8方向semi オートタイルだっ!!!
(界王拳っぽく)

というわけで8方向セミオートタイル実装に挑戦しました。

8方向元タイル.gif

生成元タイルはこんな感じ。
上から境界なし、横方向境界、縦方向境界、全方向境界、斜めのみ境界

そう、元タイルを4分割して、それぞれに2.25方向境界の処理を施すことにしたらすっきりしました。同じタイルをコピーで5つならべてから境界の加工をすればいいので、タイルを作るのも少し楽になりました。
(ウディタ(?)あたりと似た形式に)

8方向マップ.gif

ペタペタ配置して実行

8方向結果.gif

じゃん!
見た目がいまいちなのはタイルのデザインのせい‥

自動生成.gif

自動生成されたタイルはこんな感じ。3列かぁ‥

生成方法ですが、パターンは47種類らしいです。こちらを参考にさせていただきました。

それぞれのパターンで、8方向のうち、どの方向の境界がONかは画像を見てそのままデータとして記載しました。

後は処理するエリアに応じて、その中から3つを抜き出して(例えば右上を処理しているなら、必要なフラグは右と上と右上のフラグのみ)どれだけ下にずらすかを算出してコピー実施。

で、表示時に隣接タイルとの差異のパターンは8方向なので2^8の256通り。
それが47種類のどれに対応するか‥‥?

うーん、ううん? あーうー‥ うん、全部書こう!(思考停止)
力こそパワー。手を動かしゃいいねん!

semi8dtile.lua
-- 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文重ねるよりすっきりする気はするのですが、後からみてちゃんと理解できるかは心配です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0