mieki256's diary



2022/10/31(月) [n年前の日記]

#1 [tic80] TIC-80 1.0.2164でラスタースクロール

TIC-80 1.0.2164 + Windows10 x64 21H2で、ラスタースクロールができるか試してみた。以前もやってみたことがあるのだけど、TIC-80の仕様が微妙に変わったので、ソースをちょっと修正して再度試してみた次第。

_TIC-80でラスタースクロール処理
_TIC-80でラスタースクロール処理その2

BDR関数についての簡単な説明。 :

TIC-80 0.90 以降には、BDR() という関数が用意されてる。

_BDR - nesbox/TIC-80 Wiki

この関数は、ウインドウの横1ライン分を描画する直前に呼ばれる関数。描画しようとしているy座標 + 4 の値が入った状態で呼ばれる。

要するに、昔のゲーム機で言えば、水平帰線期間(HBlank)割込みに相当する。この BDR() の中で、Screen Offset値を書き換えてやれば、1ライン毎に表示位置を変えられるから、ラスタースクロールもできる。

ちなみに、TIC-80 0.90 より前の版(0.70.6 や 0.80.1344)では、BDR() ではなくて SCN() という関数名だった。

_SCN - nesbox/TIC-80 Wiki

また、SCN() に渡される値と、BDR() に渡される値も、若干違っている。
  • SCN(n) : n = 描画するラインのy座標。0 - 135 の値が入る。
  • BDR(m) : m = 描画するラインのy座標 + 4。0 - 143 の値が入る。0 - 3 は TOP BORDER。140 - 143 は BOTTOM BORDER になっている。

Screen Offsetを書き換えてラスタースクロール。 :

まずは、BDR() の中で、Screen Offset にsin値やcos値を書き込んでみる。

tic80_1_0_2164_raster_ss1.gif

_raster1.zip (raster1.tic, tiles3.png, map3.map)

ローカル環境で動かしたい場合は、以下で実行できる。
tic80.exe raster1.tic

画像(tiles3.png)やマップデータ(map3.map)を利用したい時は、TIC-80 のコンソール上からインポートできる。
tic80.exe --fs=.
import tiles tiles3.png
import map map3.map

ソースは以下。

_raster1.lua
t=0
x=96
y=24

function TIC()
 cls(13)
 map(0,0)
 local col=0
 local scale=3
 spr(1+t%60//30*2,x,y,col,scale,0,0,2,2)
 col=12
 print("HELLO WORLD!",84,84,col)
 t=t+1
end

--function SCN(row)
function BDR(row)
 local rx,ry
 rx=8*math.cos(math.rad(3*t+4*row))
 ry=6*math.sin(math.rad(2*t+4*row))
 poke(0x3FF9,rx)
 poke(0x3FF9+1,ry)
end
  • function BDR(row) - end の中が、ラスタースクロール処理。
  • poke(0x3FF9,rx) で、Screen Offset の x値を書き換え。
  • poke(0x3FF9+1,ry) で、Screen Offset の y値を書き換え。今気づいたけど、poke(0x3FFA,ry) と書いたほうが良かったかも…。
  • Lua で sin,cos を使う時は、math.sin(), math.cos() を使う。
  • sin, cos関数に渡される値はラジアン単位。math.rad() を使って、度からラジアンに変換できる。

OVR()を使う。 :

前述のラスタースクロール処理を行うと、ウインドウ内の全体の見た目が変わってしまう。背景はラスタースクロールさせるけど、手前のスプライト相当はラスタースクロールをかけないようにしたい。

そんな時は OVR() 関数を使う。OVR()関数は、BDR() が描画処理を終えた後、一番最後に呼ばれるので、その中で描画処理をすれば、BDR() の処理が影響しない状態の描画ができる。

_OVR - nesbox/TIC-80 Wiki

tic80_1_0_2164_raster_ss2.gif

_raster2.zip (raster2.tic)

_raster2.lua
t=0
x=96
y=24

function TIC()
 local spd=2
 if btn(0) then y=y-spd end
 if btn(1) then y=y+spd end
 if btn(2) then x=x-spd end
 if btn(3) then x=x+spd end

 cls(13)
 map(0,0)
 t=t+1
end

--function SCN(row)
function BDR(row)
 local rx,ry
 local sx,sy=x/10,y/5
 rx=sx*math.cos(math.rad(3*t+4*row))
 ry=sy*math.sin(math.rad(2*t+4*row))
 poke(0x3FF9,rx) -- Screen Offset x
 poke(0x3FFA,ry) -- Screen Offset y
end

function OVR()
 local col=0
 local scale=2
 spr(257+t%60//30*2,
     x,y,col,scale,0,0,2,2)
 col=12
 print("HELLO WORLD!",84,84,col)
end

OVR() の中で、スプライト(コンピュータみたいなキャラクタ)の描画と、文字描画("HELLO WORLD!")をしているので、背景はラスタースクロールしているけれど、スプライトと文字はラスタースクロールしていない状態になっている。

注意点。TIC-80 1.0以降では、OVR() の中で描画指定をすると、パレットの0番色が必ず透明色として扱われてしまう。

上記の例では、0番色を透明色、それ以外を不透明色扱いにしてドット絵を描いてあるので、問題無さそうに見えてるけれど。TIC-80 のデフォルトのパレットデータでは、0番色 = 黒色なので、黒色を使ったドット絵を描いて OVR() の中で描画してしまうと、黒い部分が透明になってしまう。

以下のやり取りによると、任意の色番号を透明色として扱うように指定することも可能らしいけど、やり方がよく分からなかった…。何にせよ、その場合もどこか1色は透明になってしまうので、OVR() の中で描画する何かしらは15色しか使えないと思っておいたほうが良さそう。

_everything drawn in OVR with color 0 is transparent - Issue #1897 - nesbox/TIC-80

水面があるような処理。 :

そこに水面があるような見た目を、ラスタースクロールを使って実現してみる。

tic80_1_0_2164_raster_ss3.gif

_raster3.zip (raster3.tic)

_raster3.lua
t=0
x=64
y=32
sy=0

function TIC()
 local spd=2
 if btn(0) then y=y-spd end
 if btn(1) then y=y+spd end
 if btn(2) then x=x-spd end
 if btn(3) then x=x+spd end

 cls(0)
 map(0,0)
 local col=0
 local scale=2
 spr(1+t%60//30*2,x,y,col,scale,0,0,2,2)
 col=12
 print("HELLO WORLD!",84,28,col)
 t=t+1
 sy=math.floor((136*0.7)+16*math.sin(math.rad(t)))

 -- reset palette
 sync(1<<5)
end

--function SCN(row)
function BDR(row)
 local rx,ry=0,0
 
 if row==sy then
  -- palette change
  local PAL_ADDR=0x3FC0
  for i=PAL_ADDR,PAL_ADDR+16*3-1 do
   poke(i,peek(i)*0.5)
  end
 end
 
 if row<sy then
  rx=0
  ry=0
 else
  local dy=row-sy
  rx=1.5*math.cos(math.rad(4*t+55*dy))
  -- ry=-dy*2 -- TIC-80 0.70.6
  ry=dy*2 -- TIC-80 1.0.2164
 end
 
 local SCROFSX=0x3FF9
 local SCROFSY=0x3FFA
 poke(SCROFSX,rx)
 poke(SCROFSY,ry)
end

まず、BDR() に渡された値(y座標 + 4)と、値が上下に揺れるグローバル変数 sy を比較して、もし同じ値なら、そのタイミングでパレットデータを少し暗めな値に書き換えている。これで、水面相当がちょっと暗い感じの色になってくれる。

ただ、このままだと次のフレームを描画する時に、暗くなったパレットデータを使って描画してしまうので、TIC() の中の最後のあたりで sync(1<<5) を呼ぶことでパレットデータを初期化してる。

BDR() の中では、グローバル変数 sy より下を描画するときだけ、ラスタースクロールをかけている。 Screen Offset のy値を書き換えて、縦方向の表示位置を変化することで、上下反転した見た目にしている。

ただ…。TIC-80 0.70.6 / 0.80.1344 / 0.90.1723 と、TIC-80 1.0.2164 では、Screen Offset値の正負が逆なようで…。以前の版で書き込んでいた値の正負を反転して利用しないと、期待していた見た目にはならなかった。このあたりは別記事でまとめておく。

以上です。

過去ログ表示

Prev - 2022/10 - Next
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project