8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PyxelAdvent Calendar 2024

Day 4

【Pyxel】data_ptrを使って高速化

Last updated at Posted at 2024-11-27

前記事:【Pyxel】16色を超える色を使ってのゲーム作りでpsetコマンドを使ってドット絵を描画することにより、16色を超える色を使うことができるようになります。

ただ、psetコマンドを使うと処理負荷がかかってしまいます。

ブロックだけならそうでもないですが、背景の模様の描画にも16色を超える色を使うと処理負荷は結構かかってしまってました。

そんな時、Pyxelのdiscodeにて「~psetよりdata_ptr使えばいいと思う」とのご指摘を頂きました。

その時初めて聞く単語「data_ptr」って何?と思って調べてみると、

PyxelのIssuesにPyxel開発者北尾さんの書き込みを見つけました。

In Pyxel 1.9.13, data_ptr method is added to the Image class.

You can get the pointer to data like this:

ptr1 = pyxel.tilemap(0).data_ptr()
ptr2 = pyxel.screen.data_ptr()
The type of pointer is POINTER(c_ubyte). So you can also make Numpy array by using it.

また、Xにも投稿を見つけました。

Pyxelは仮想マシンではないのでPICO-8のようなpeek,poke命令はありませんが、Imageクラス、Tilemapクラスのdata_ptrメソッドで実データアドレスが取得できます。画面もImageクラスのインスタンスの一つなのでそのアドレス経由でPICO-8相当か、もっと無茶な操作が可能です。

「ドット絵からテキストを作成」部分は、以下の通り色データのみで構成します。
ただ、data_ptrでは全部を描画するため透明なデータを多く使用するものには使えません。ブロックの四隅は元々透明にしてましたが黒でも違和感が無かったので使えました。

#MULTI BLOCK
#	0 1 2 3 4 5 6 7   8 9 a b c d e f
#0	□■■■■■■■ ■■■■■■■□
#1	■■■■■■■■ ■■■■■■■■
#2	■■■■■■■■ ■■■■■■■■
#3	■■■■■■■■ ■■■■■■■■
#4	■■■■■■■■ ■■■■■■■■
#5	■■■■■■■■ ■■■■■■■■
#6	■■■■■■■■ ■■■■■■■■
#7	■■■■■■■■ ■■■■■■■■
#8	□■■■■■■■ ■■■■■■■□

mblk_tbl = [
	#16x9
	0,1,2,2,2,2,2,2,2,2,2,2,2,2,3,0, 
	1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3, 
	2,2,3,3,3,3,3,3,3,3,3,3,3,3,6,6, 
	2,2,3,3,3,3,3,3,3,3,3,3,3,3,6,6, 
	2,2,3,3,3,3,3,3,3,3,3,3,3,3,6,6, 
	2,2,3,3,3,3,3,3,3,3,3,3,3,3,6,6, 
	2,2,3,3,3,3,3,3,3,3,3,3,3,3,6,6, 
	3,3,3,4,4,4,4,4,4,4,4,4,4,5,5,5, 
	0,3,4,4,4,4,4,4,4,4,4,4,4,4,5,0,
]

描画関数は以下の通り。

#-----------------------------------------------------------------
#ドットパターン描画(ブロックは16dotx9dot)
#-----------------------------------------------------------------
def dot_pattern( _dx, _dy, _tp, _adr ):
	_scrptr = pyxel.screen.data_ptr()
	for _yp in range(9):
		for _xp in range(16):
			_scrptr[ ( ( _dy + _yp ) * SCREEN_WIDTH ) + ( _dx + _xp ) ] = _adr[_yp * 16 + _xp] + ( _tp * 0x10 )

ここのSCREEN_WIDTHは画面横サイズになります。

イメージとしては以下の図の通りスクリーンイメージの左上のポインタが取得できるので直接描画できるということ。つまりpsetで1ドットずつ置くのではなく、まとめて描画できるということになります。
data_ptr.png

ブロック以外に背景描画もdata_ptrを使って、変更前後で処理速度73%減となりかなりの高速化が達成できました。html化しても処理落ちが無くなりました。

これは仕様書には載ってない方法です。
PyxelのIssuesやdiscodeなどこまめにチェックすると、もしかしたら他にも有用な技が隠されているのかもしれません。
想像ですが・・・

8
4
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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?