|
|
|
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を添字とする配列変数とかに変えると
複数のメッセージを同時に流すとかもたぶんできます
| |
|
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
| |
|
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
パーセントをマイナス値にするとローディングっぽくグルグルするようにもしてみました。
(イージング入れないとあんまりそれっぽくないかな・・・)
| |
|