HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2021
0922
ベインlayerobjでemesの代わりを作ってみた3解決


ベイン

リンク

2021/9/22(Wed) 00:29:04|NO.93940

emesはlayerobjの好例だと思ったので、サンプルを作ってみました

以下のスレッドのGENKIさん・沢渡さんのコードを参考にしています:
"emesでプログラムを停止させずにゆっくりと文字表示"
(https://hsp.tv/play/pforum.php?mode=all&num=93831)
"emesで処理を止めない"
(https://hsp.tv/play/pforum.php?mode=all&num=93933)


#include "kernel32.as" #include "user32.as" ; オブジェクト配置 pos 5, 50 layerobj 300, 300, objlayer_posteff | objlayer_multi, *emes_proc obj_id = stat ; 表示する文字列を設定 s = "いろはにほへとちりぬるを\nわかよたれそつねならむ\nうゐのおくやまけふこえて\nあさきゆめみしゑひもせす" objprm obj_id, s repeat redraw 0 ; 通常の画面描画のイメージ hsvcolor ,, 255 ; 白 boxf color ; 黒 pos 5, 5 mes "cnt = " + cnt redraw 1 await 1000 / 16 loop *emes_proc switch lparam case objlayer_cmdprms ; objprmで文字列を指定したときここに来る a = refstr ; objprmに指定された文字列 ; UTF-16 に変換する。 sdim a16, strlen(a) * 2 + 2 cnvstow a16, a ; UTF-16 基準で文字数 (コードユニット数) を数える。 lstrlenW varptr(a16) len16 = stat c = 0 ; 表示する文字数 frame = 6 ; 文字を増やす間隔 (フレーム数) tick = 0 return case objlayer_cmddraw if c < len16 && tick \ frame == 0 { c++ } tick++ gosub *emes_draw return default: return swend *emes_draw ; 位置 px, py i = objinfo(wparam, objlayer_info_axis) px = i & 0xffff py = i >> 16 ; 大きさ sx, sy i = objinfo(wparam, objlayer_info_size) sx = i & 0xffff sy = i >> 16 hsvcolor ,, 255 ; 白 boxf px, py, px + sx - 1, py + sy - 1 color ; 黒 rect = px, py, px + sx, py + sy ; 文字列の前からc文字を表示する ; (DrawTextWはUTF-16の文字列を表示するAPI ; https://www.tokovalue.jp/function/DrawText.htm ; 次に画面が再描画されたとき表示される。) DrawTextW hdc, varptr(a16), c, varptr(rect), 0 return

*emes_proc の部分をモジュールにしておくと、
自分のスクリプトではlayerobjの作成だけ書けばよくなるので手軽になります

いまメッセージ表示の状態を変数aやcに入れているのを
オブジェクトIDを添字とする配列変数とかに変えると
複数のメッセージを同時に流すとかもたぶんできます



この記事に返信する


MIZUSHIKI

リンク

2021/9/22(Wed) 19:33:10|NO.93950

非常に面白いですね!!
emes中にメッセージをスキップ出来るようにして、ADVゲーム風にして遊んでみましたヾ(❛ᴗ˂ )

#include "kernel32.as" #include "user32.as" #include "a2d.hsp" //oemes状態 #enum global OEMES_STOP = 0 #enum global OEMES_DRAW #enum global OEMES_SKIP _OEMES_STATUS_@ = OEMES_STOP screen 0,800,600 //素材ロード buffer 1 : picload dir_tv+"bg05.jpg" alCreateImageByFile 0, dir_tv+"kei_school1_5.png" : hx=100:hy=-120 alCreateImageByFile 1, dir_tv+"janbg.png" gsel 0 font "メイリオ",28 ; オブジェクト配置 pos 50, 420 layerobj 700, 150, objlayer_posteff | objlayer_multi, *emes_proc obj_id = stat ; 表示する文字列を設定 s = "いろはにほへとちりぬるを わかよたれそつねならむ\nうゐのおくやまけふこえて あさきゆめみしゑひもせす" objprm obj_id, s repeat redraw 0 ; 通常の画面描画のイメージ pos 0,0 : gcopy 1, 0,0,800,600 ; 背景 alResetCopyMode : alCopyImageToScreen 0,0, hx+rnd(10)-5, hy+rnd(10)-5 ; 人 alCopyModeAlpha 0.75 : alStretchImageToScreen 1,0, 0,0,640,480, 20,400,760,180 ; 枠 color 255,255,255; 白 pos 5, 5 mes "メッセージスキップ : スペース/エンター/emes枠内クリック" mes "cnt = " + cnt mes "状態:"+_OEMES_STATUS_ ; メッセージが終わっていてクリックされたら次の文章を開始させる if _OEMES_STATUS_ == OEMES_STOP { if oemes_checkclk(obj_id) { sc++ s = "色は匂へど 散りぬるを 我が世誰ぞ 常ならむ\n有為の奥山 今日越えて 浅き夢見じ 酔ひもせず\n("+sc+"回目)" objprm obj_id, s } } redraw 1 await 1000 / 16 loop *emes_proc switch lparam case objlayer_cmdprms ; objprmで文字列を指定したときここに来る a = refstr ; objprmに指定された文字列 ; UTF-16 に変換する。 sdim a16, strlen(a) * 2 + 2 cnvstow a16, a ; UTF-16 基準で文字数 (コードユニット数) を数える。 lstrlenW varptr(a16) len16 = stat c = 0.0 ; 表示する文字数 [実数] frame = 4.0 ; 文字を増やす間隔 (フレーム数) [実数] _OEMES_STATUS_@ = OEMES_DRAW return case objlayer_cmddraw c += 1.0/frame if c > len16 : c = double(len16) gosub *emes_draw return default: return swend *emes_draw ; 位置 px, py i = objinfo(wparam, objlayer_info_axis) px = i & 0xffff py = i >> 16 ; 大きさ sx, sy i = objinfo(wparam, objlayer_info_size) sx = i & 0xffff sy = i >> 16 ;hsvcolor ,, 255 ; 白 ;boxf px, py, px + sx - 1, py + sy - 1 ;color ; 黒 rect = px, py, px + sx, py + sy ; 文字列の前からc文字を表示する ; (DrawTextWはUTF-16の文字列を表示するAPI ; https://www.tokovalue.jp/function/DrawText.htm ; 次に画面が再描画されたとき表示される。) DrawTextW hdc, varptr(a16), int(c), varptr(rect), 0 ; 状態管理 if oemes_checkclk(wparam) { frame = 0.15 _OEMES_STATUS_@ = OEMES_SKIP } if c >= len16 : _OEMES_STATUS_@ = OEMES_STOP return //スペース/エンター/オブジェクト内クリックを検出 #defcfunc oemes_checkclk int id i=objinfo(id,objlayer_info_axis):px=i&0xffff:py=i>>16 i=objinfo(id,objlayer_info_size):sx=i&0xffff:sy=i>>16 stick s if (s&16) || (s&32) || ( (s&256)!0 && px<=mousex && mousex<=px+sx && py<=mousey && mousey<=py+sy ) { return 1 } return 0



ベイン

リンク

2021/9/24(Fri) 20:12:43|NO.93958

いい感じですね

オブジェクトごとにアニメーションをもたせると面白そうなので
スイッチを作ってみました

デザインの参考:
https://jp.infragistics.com/products/indigo-design/help/components/switch

stickをdraw中にやるとキートリガーの判定がうまくいかないみたいなので
stickはメインループ側でやったほうがよさそうです


pos 5, 45 : switcher 60, 30 pos 5, 85 : switcher 80, 40, 1 ; チェック済み repeat stick trigger@ ; ←モジュールで使う redraw 0 hsvcolor ,, 255 ; 白 boxf color pos 5, 5 : mes "cnt = " + cnt redraw 1 await 1000 / 60 loop ; ======================================== #module m_switcher #deffunc switcher int sx1, int sy1, int checked1 layerobj sx1, sy1, objlayer_posteff | objlayer_multi, *switcher_proc, checked1 != 0 return *switcher_proc switch lparam case objlayer_cmdinit case objlayer_cmdprmi checked_array(wparam) = iparam != 0 ; アニメーション状態 ; (1以上なら移動中、0で完了) transition_array(wparam) = 0 return case objlayer_cmddraw : gosub *switcher_draw : return default: return swend *switcher_draw ; 位置 px, py i = objinfo(wparam, objlayer_info_axis) px = i & 0xffff : py = i >> 16 ; 大きさ sx, sy i = objinfo(wparam, objlayer_info_size) sx = i & 0xffff : sy = i >> 16 id = wparam ; クリック処理 clicked = (trigger@ & 256) != 0 ; 左クリック clicked &= px <= mousex && mousex <= px + sx clicked &= py <= mousey && mousey <= py + sy if clicked { checked_array(id) = 1 - checked_array(id) transition_array(id) = 5 ; 5フレームの間アニメーション } checked = checked_array(id) t = double(transition_array(id)) / 5 ; 球の直径 d = limit(sx, , sy) ; min ; 棒 h = d * 3 / 5 ; 縦幅 if checked { hsvcolor 65, 60, 220 ; 薄い緑 } else { hsvcolor ,, 192 ; 薄い灰色 } boxf px + d / 4, py + (sy - h) / 2, px + sx - d / 4, py + (sy + h) / 2 ; 球 y = py + (sy - d) / 2 if checked { hsvcolor 65, 130, 180 ; 緑 x1 = px x2 = px + sx - d } else { hsvcolor ,, 168 ; 濃い灰色 x1 = px + sx - d x2 = px } x = t * (x2 - x1) + x1 ; x1→x2に移動するアニメーション circle x, y, x + d, y + d ; アニメーション更新 transition_array(id) = limit(transition_array(id) - 1, 0) ; max return #global



MIZUSHIKI

リンク

2021/9/25(Sat) 22:14:54|NO.93970

おぉ!!
オブジェクトにアニメーションを持たせるの良いですね! カッコイイε٩( º∀º )۶з

>stickをdraw中にやるとキートリガーの判定がうまくいかない
複数layerobjがあると一度のループで *switcher_drawが複数回呼ばれて何度もstick判定してるのが問題っぽいですね。
最初の一回だけstick判定をさせることが出来たら良さそうです。

と、いうことで以下のような細工を考えてみました。

: case objlayer_cmddraw ; ←変更 if drawID >= wparam : stick trigger ; ←追加 drawID = wparam ; ←追加 gosub *switcher_draw return default: return : // trigger@ ⇒ trigger に要変更。(メインループのstick消すのも。)
drawID変数にdrawしたIDを控えて、一番小さくなった時だけstickを使用する感じです。


で!、
私も何かオブジェクトにアニメーションさせてみたいと思い、デザインの参考にされてたサイトから
https://jp.infragistics.com/products/indigo-design/help/components/progress
このProgress (プログレス)を真似て、 必 要 な い の に 値変更時にアニメーションするようにしてみました!

pos 200 : p=0.75 : input p objsize 150,20 : button gosub "%変更( 0.0〜1.0で指定 )",*henko pos 100, 85 : progress 80, 0.75 ; サイズ[80], パーセント(75%) id_progress = stat pos 100, 200 : progress 40, 0.58 ; サイズ[40], パーセント(58%) pos 100, 300 : progress 60, -1.0 ; マイナス値でローディング repeat redraw 0 hsvcolor ,, 255 ; 白 boxf color pos 5, 5 : mes "cnt = " + cnt redraw 1 await 1000 / 60 loop *henko objprm id_progress, double(p) ; パーセント値の変更 return ; ======================================== #module m_progress #include "gdi32.as" #deffunc progress int sr, double per layerobj sr, sr, objlayer_posteff | objlayer_multi, *progress_proc id = stat if vartype(per_array) ! 3 : ddim per_array,id+1 : ddim oldPer_array,id+1 ; まだなら初期化 per_array(id) = per oldPer_array(id) = per ; アニメーションのため前回の値を記憶しておく変数 ; アニメーション状態 ; (1以上なら移動中、0で完了) transition_array(id) = 0 ;アニメーション(最初はアニメーションしない) return id *progress_proc switch lparam case objlayer_cmdprmd if per_array(wparam) >= 0.0 { transition_array(wparam) = 10 ; 10フレームの間アニメーション oldPer_array(wparam) = per_array(wparam) ; 前回の値を記憶 }else { transition_array(wparam) = 0 ; ローディングからの復帰時はアニメーションしない oldPer_array(wparam) = refdval } per_array(wparam) = refdval return case objlayer_cmddraw gosub *progress_draw return default: return swend *progress_draw oldPxy = ginfo_cx, ginfo_cy ; カレントポジションを控えておく ; 位置 px, py i = objinfo(wparam, objlayer_info_axis) px = i & 0xffff : py = i >> 16 ; 大きさ sx, sy i = objinfo(wparam, objlayer_info_size) sx = i & 0xffff : sy = i >> 16 id = wparam t = double(transition_array(id)) / 10 ; 10フレームの間アニメーション pe = per_array(wparam) - (per_array(wparam)-oldPer_array(wparam))*t ; アニメーション中のパーセント ; arcの角度を計算しておく if per_array(wparam) >= 0.0 { as = 90.0 al = -360.0*( pe ) }else { ; マイナス値ならローディング as = 360+(transition_array(id)*5+90)\360 al = (transition_array(id)*5)\720+360 -30 ; -30で少し被らせることでなんとなく加速感(?) } ; オブジェクト描画 ; ペン作成 hPen_C = CreatePen( 0, 6, 224<<16|224<<8|224 ) hPen_A = CreatePen( 0, 6, 255<<16|153<<8|0 ) ; 円,円弧描画 hOldPen = SelectObject( hdc, hPen_C ) MoveToEx hdc, px,py-sy/2, dummy AngleArc hdc, px,py, sy/2, 90.0,-360.0 AngleArc hdc, px,py, sy/2, 90.0, double(as)-90.0 ; ローディングのとき動かさないといけないMoveToEx代わり SelectObject hdc, hPen_A AngleArc hdc, px,py, sy/2, as, al ; ペン削除 SelectObject hdc, hOldPen DeleteObject hPen_C DeleteObject hPen_A ; パーセント文字 if per_array(wparam) >= 0.0 { pe4s5n = int(pe*1000+5)/10 ; パーセント(四捨五入) pos ginfo_sx,ginfo_sy ; 一度、枠外に書いて mes ""+pe4s5n+"%" pos px-ginfo_mesx/2+1,py-ginfo_mesy/2+1 ; ginfo_mesx,yを考慮して中心に描画 mes ""+pe4s5n+"%" } ; アニメーション更新 if per_array(wparam) >= 0.0 { transition_array(id) = limit(transition_array(id) - 1, 0) ; max }else { ; ローディングのときは制限しないでずっとカウンターとして使用 transition_array(id)-- } pos oldPxy(0), oldPxy(1) ; カレントポジションを戻しておく return #global
パーセントをマイナス値にするとローディングっぽくグルグルするようにもしてみました。
(イージング入れないとあんまりそれっぽくないかな・・・)



ONION software Copyright 1997-2023(c) All rights reserved.