2023/11/04(土) [n年前の日記]
#1 [hsp] hsp3dishでスクリーンセーバを作れそうか試したけど無理っぽい
Windows10 x64 22H2 + HSP 3.7beta7 で、hsp3dish を使ってスクリーンセーバを作れそうなのか試していた。
結論を先に書くと、無理っぽい。
結論を先に書くと、無理っぽい。
◎ 無理な理由 :
HSP には多数のサンプルが同梱されていて、sample\ssaver\arusave.hsp がスクリーンセーバ作成のサンプルになってる。そのサンプルでは、スクリーンセーバのフルスクリーン表示モード時に、以下の処理が書かれてる。
しかし、hsp3dish を使う場合は、以下の制限がある。
それを踏まえた上で。
hsp3dish を使ってスクリーンセーバを作るなら…。ウインドウID2の表示ウインドウを新規作成せずに、既に存在するウインドウID0をフルスクリーン表示にして、そこに描画していけばスクリーンセーバを作れるのではないかな、などと甘いことを考えていたのだけど…。
実際にやってみたら、そうは問屋が卸さなかった。見た目だけはそれらしくなったけど、マウスを動かしたりキーボードを叩いても終了してくれないプログラムになってしまった。これではスクリーンセーバにならないわけで…。
どういう仕組みになっているのか分からないけれど、HSPでスクリーンセーバを作る際、フルスクリーンモード時では、手付かずのウインドウID0と、ガンガン描画をしていくウインドウID2、この2つの表示ウインドウが存在してる状態じゃないといけないようだなと…。
では、hsp3dish ではなく、HGIMG4 ならどうだろう。HGIMG4 なら複数の表示ウインドウを作れたりしないか? 調べてみたけれど、サンプルを眺める限り、表示ウインドウを1つしか持てないのは hsp3dish と同じらしい。HGIMG4 は hsp3dish を拡張して作られたプラグインなので、hsp3dish と同じ制限を引き継ぐ模様。
ならば HGIMG3 ではどうかとサンプルを眺めてみたら、screen命令でもう1つの表示ウインドウを確保しているサンプルが見つかった。ひょっとすると HGIMG3 を使えばスクリーンセーバが作れるのでは、と期待しているところ。実験してみないと…。
- HSP製プログラム実行時にデフォルトで作られる表示ウインドウ(ウインドウID0)には、一切手を付けない。
- ウインドウID2の表示ウインドウをフルスクリーン表示で新規に作成して、そちらに描画をしていく。
しかし、hsp3dish を使う場合は、以下の制限がある。
- 表示ウインドウは1つしか持てない。複数の表示ウインドウは作れない。
- プログラム実行時に作られるウインドウID0の表示ウインドウだけが、描画可能なウインドウになる。
それを踏まえた上で。
hsp3dish を使ってスクリーンセーバを作るなら…。ウインドウID2の表示ウインドウを新規作成せずに、既に存在するウインドウID0をフルスクリーン表示にして、そこに描画していけばスクリーンセーバを作れるのではないかな、などと甘いことを考えていたのだけど…。
実際にやってみたら、そうは問屋が卸さなかった。見た目だけはそれらしくなったけど、マウスを動かしたりキーボードを叩いても終了してくれないプログラムになってしまった。これではスクリーンセーバにならないわけで…。
どういう仕組みになっているのか分からないけれど、HSPでスクリーンセーバを作る際、フルスクリーンモード時では、手付かずのウインドウID0と、ガンガン描画をしていくウインドウID2、この2つの表示ウインドウが存在してる状態じゃないといけないようだなと…。
では、hsp3dish ではなく、HGIMG4 ならどうだろう。HGIMG4 なら複数の表示ウインドウを作れたりしないか? 調べてみたけれど、サンプルを眺める限り、表示ウインドウを1つしか持てないのは hsp3dish と同じらしい。HGIMG4 は hsp3dish を拡張して作られたプラグインなので、hsp3dish と同じ制限を引き継ぐ模様。
ならば HGIMG3 ではどうかとサンプルを眺めてみたら、screen命令でもう1つの表示ウインドウを確保しているサンプルが見つかった。ひょっとすると HGIMG3 を使えばスクリーンセーバが作れるのでは、と期待しているところ。実験してみないと…。
◎ ソース :
スクリーンセーバにはならなかったけれど、デモプログラムとしては動かせるので、一応ソースを置いておく。
_h3dshscr.hsp
使用画像は以下。
_preview.png
_star.png
実行画面は以下。静止画ではさっぱり伝わらないけれど、星が奥から飛んでくるアレ。昔のWindowsに入ってた「宇宙飛行」スクリーンセーバみたいなソレ。
_h3dshscr.hsp
; screensaver sample for hsp3dish.
; fork arusave.hsp
;
; This program does not work.
;
; hsp3dish を使ってスクリーンセーバが作れるか実験したが、失敗に終わった。
;
; Windows10 x64 22H2 + HSP 3.7 beta7
;
; 2023/11/04 by mieki256
#include "hsp3dish.as"
#include "d3m.hsp"
; 以下の行のコメントアウトを外すとスクリーンセーバとして実行ファイルを作成する
; #define SCREENSAVER_ENABLE
#define TITLE_STR "Screensaver sample for hsp3dish"
#define VER_STR "0.0.1"
#packopt name "h3dshscr"
#ifdef SCREENSAVER_ENABLE
#packopt type 2
#else
#packopt type 0
#endif
#packopt xsize 640 ; 設定画面横幅
#packopt ysize 360 ; 設定画面縦幅
#define TEX_FILE "star.png"
#define PREVIEWFILE "preview.png"
#pack TEX_FILE
#pack PREVIEWFILE
#define KB_ESC $000080
#define FRAMERATE 60
fps_display_enable = 1
; ----------------------------------------
; parse command line option
s = dir_cmdline ; get command line option
i = instr(s, 0, "/") ; "/" の出現位置を検索
if i = -1 {
; not option
#ifdef SCREENSAVER_ENABLE
goto *config_mode
#else
goto *fullscreen_mode
#endif
; goto *preview_mode
}
a = strmid(s, i, 2) ; 2文字だけ取り出し
if a == "/p" or a == "/P" : goto *preview_mode ; プレビュー
if a == "/s" or a == "/S" : goto *fullscreen_mode ; フルスクリーン
if a == "/c" or a == "/C" : goto *config_mode ; コンフィグ
; コマンドラインがどれでもない時はエラー表示
dialog "Unknown switch [" + s + "]"
end
*config_mode
; 設定画面
screen 0, 640, 360, 0
gsel 0
cls
tt = "Config - " + TITLE_STR + " " + VER_STR
title tt
font "Tahoma", 24, 1
redraw 0
color 0, 0, 0
pos 20, 20
mes "Config - " + TITLE_STR
pos 20, 50
mes "Version : " + VER_STR
pos 520, 300
button "OK", *ssend
redraw 1
stop
*ssend
end
*preview_mode
; プレビュー画面
; スクリーンセーバー選択時の、小さな画面内でのプレビューの処理。
; HSPのWindow ID0がプレビュー画面に合わせて小さくなっているので、
; ginfo_winx, ginfo_winy で画面サイズを取得後、その中に描画する。
; 経験上、単に画像を表示してstopしたほうが不具合が起きにくい。
wdw_w = ginfo_winx
wdw_h = ginfo_winy
; load preview image
imgid = 3
w = 152
h = 112
buffer imgid, w, h
picload PREVIEWFILE
iw = ginfo_winx
ih = ginfo_winy
; draw
gsel 0
redraw 0
cls 4
gmode gmode_gdi, iw, ih
gzoom wdw_w, wdw_h, imgid, 0, 0, iw, ih, 1
redraw 1
stop
; ----------------------------------------
*fullscreen_mode
; フルスクリーン描画処理
; get desktop size
dispw = ginfo_dispx
disph = ginfo_dispy
; initialize window without frame
; bgscr WindowID, width, height, mode, x, y
bgscr 0, dispw, disph, 0, 0, 0, dispw, disph
; load image
imgid = 3
celload TEX_FILE, imgid
; split image. set orign
celdiv imgid, 512, 512, 256, 256
; Set the buffer to draw from. Windows ID 0
gsel 0, 1
; Set screen clear color to be performed when redraw 0 is called.
; 0 or 1, color ($000000 - $ffffff)
; setcls CLSMODE_SOLID, $4080c0
setcls CLSMODE_SOLID, $000000
font "Tahoma", 24, 1
randomize
star_size = 0.75
dist = 150.0 ; screen distabce
area_z = 5000
zmax = double(area_z) + dist
; rnd() only accepts 1 to 32768.
; adjust the value to stay within that range.
area_m = 4.0
area_w = int((double(dispw) * zmax) / dist / area_m)
area_h = int((double(disph) * zmax) / dist / area_m)
objmax = 512
; initialize stars work
ddim posx, objmax ; position x
ddim posy, objmax ; position y
ddim posz, objmax ; position z
dim px, objmax ; display position x
dim py, objmax ; display position y
ddim scalev, objmax ; scale
dim alpha, obj_max ; alpha value
dim patidx, obj_max ; pattern index
repeat objmax
gosub *get_newpos_xy
posx(cnt) = nx
posy(cnt) = ny
patidx(cnt) = idx
posz(cnt) = double(rnd(area_z)) + dist
px(cnt) = 0
py(cnt) = 0
scale(cnt) = 0.0
alpha(cnt) = 0
loop
time_start = d3timer()
endfg = 0
; ----------------------------------------
*mainloop
while endfg == 0
tm = d3timer() - time_start
fps = d3getfps() ; get FPS
#ifndef SCREENSAVER_ENABLE
; ESC key to exit
stick key, 0
if key & KB_ESC : endfg = 1
#endif
; move stars
spd = 40.0
repeat objmax
posz(cnt) -= spd
if posz(cnt) < (dist / 2.0) {
posz(cnt) += zmax
gosub *get_newpos_xy
posx(cnt) = nx
posy(cnt) = ny
patidx(cnt) = idx
}
; get display x, y position
px(cnt) = int(posx(cnt) * dist / posz(cnt)) + (dispw / 2)
py(cnt) = int(posy(cnt) * dist / posz(cnt)) + (disph / 2)
scalev(cnt) = star_size * dist / posz(cnt)
size = int(512.0 * scalev(cnt))
x0 = px(cnt) - (size / 2)
y0 = py(cnt) - (size / 2)
x1 = px(cnt) + (size / 2)
y1 = py(cnt) + (size / 2)
if x1 < 0 or x0 > dispw or y1 < 0 or y0 > disph {
; out of display area. position reset
posz(cnt) += zmax
gosub *get_newpos_xy
posx(cnt) = nx
posy(cnt) = ny
patidx(cnt) = idx
px(cnt) = int(posx(cnt) * dist / posz(cnt)) + (dispw / 2)
py(cnt) = int(posy(cnt) * dist / posz(cnt)) + (disph / 2)
scalev(cnt) = star_size * dist / posz(cnt)
}
; get alpha value
az = double(area_z) * 0.7
if posz(cnt) < az {
alpha(cnt) = 255
} else {
; fade in
z = posz(cnt)
if z > zmax : z = zmax
v0 = z - az
v1 = zmax - az
alpha(cnt) = int(255.0 - (255.0 * v0 / v1))
}
loop
; ----------------------------------------
; draw start
redraw 0
; clear screen
; color 64, 128, 192
; boxf
; draw stars
repeat objmax
rot = 0.0
idx = 0
; draw image by celput
gmode gmode_add, 512, 512, alpha(cnt)
pos px(cnt), py(cnt)
rot = 0.0
idx = patidx(cnt)
celput imgid, idx, scalev(cnt), scalev(cnt), rot
loop
; draw text
if fps_display_enable {
gmode gmode_rgb0
color 255, 255, 255
pos 10, 10
mes strf("[%dx%d] %d/%dFPS", dispw, disph, fps, FRAMERATE)
}
; draw end. screen refersh
redraw 1
await (1000 / FRAMERATE)
; await 12
wend
*jobend:
end
*get_newpos_xy
nx = double(rnd(area_w) - (area_w / 2)) * area_m
ny = double(rnd(area_h) - (area_h / 2)) * area_m
idx = rnd(4)
return
使用画像は以下。
_preview.png
_star.png
実行画面は以下。静止画ではさっぱり伝わらないけれど、星が奥から飛んでくるアレ。昔のWindowsに入ってた「宇宙飛行」スクリーンセーバみたいなソレ。
[ ツッコむ ]
以上です。
