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


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0713
Kainループ命令を維持したまま裏でいろいろと処理させたい18解決


Kain

リンク

2018/7/13(Fri) 21:23:44|NO.84754

自分HSPは初心者で馬鹿なので、優しくお願いします(´;ω;`)あと日本語おかしいかもです。
いま、画面にiPhoneとかによくあるクルクル歯車を表示したままデータを保存したりさせたいのですが、
全くやり方がわかりません。いろんなページを調べたり、HSP命令リファレンスを見ても自分が求めているものが
見つかりませんでした...
iPhoneのような歯車は、画像を1枚1枚読み込んで表示させています。(今はrepeat命令とloop命令で補っています)
ですが、この方法だとなんか個人的には嫌なんです...。

つまり、何が言いたいのかと言うと画像を使ったアニメーションのループを維持したまま、
裏でデータのセーブなどを行う方法を聞きたいのです(´・ω・`)

※意味わからんかも知れませんが、その場合は質問してください。
意味が伝わるように出来るかどうかはわかりませんが...(´;ω;`)



この記事に返信する


aaa

リンク

2018/7/13(Fri) 22:01:38|NO.84756

gosub命令を使い、処理が終了したらreturn命令を
実行すれば良いのではないのでしょうか?



Kain

リンク

2018/7/13(Fri) 22:04:00|NO.84757

試してみます



Kain

リンク

2018/7/13(Fri) 22:06:44|NO.84759

すいません。
Gosub命令時はアニメーションが止まってしまいます(´;ω;`)



あらや

リンク

2018/7/13(Fri) 22:07:25|NO.84760

ゲームなんかでよくあるロードやセーブ中に
何らかのアニメーションを行なうような処理をしたいということですよね?

ゲーム以外でもPCの起動画面やダウンロード中にバーが少しずつ増えるのとか。



そういった処理はアニメーションと保存処理を別々のスレッドで行なう
いわゆるマルチスレッド処理が必要かと思います。

マルチスレッドはコールバック関数が必要になるので
HSPでは少し前までは無謀だったのですが、
現在はコールバック用モジュールが標準で付属しているので
それを使うと(きっと)出来るはずです。



Kain

リンク

2018/7/13(Fri) 22:48:58|NO.84761

なるほど。参考になるソースなどはありますか?(´・ω・`)



Velgail

リンク

2018/7/13(Fri) 22:52:12|NO.84762

こちらのサイトのサンプルスクリプトを理解すれば実装できます。
http://chokuto.ifdef.jp/advanced/usertimer.html

*RedrawClock の処理に軽量なローディング待ちの画面を描画させて、
[重要]データ保存処理などは、軽量なレベルに分割処理にする必要があります。
(例えば100MBのbsaveを発行する場合は、512kB単位で保存するといった対応)
この処理をしないと、ローディング待ちのアニメーションがガクガクします。

(あと、サンプルの250msはアニメーションにはおそすぎるので、16msとかにしておくといいかもです。
 その分高速な描画処理じゃないと、重すぎて処理が何もできなくなります)



Kain

リンク

2018/7/14(Sat) 00:51:45|NO.84764

なるほど。
今からサンプルの方を見ていろいろ試してみます。
分からないことがあったらまた聞きますね!
(その時はよろしくお願いします。)



Kain

リンク

2018/7/14(Sat) 10:16:08|NO.84766

RedrawClockのラベルにアニメーションの画像をセットしたら、何故かRuntimeErorr!!C++
というエラーが大量に発生します。何故ですか?
それから、サンプルを見て理解しようと頑張って見ましたが理解できませんでした(´・ω・`)
どうやってアニメーションを維持したまま裏で処理させるかは未だ分からないままです(;´・ω・)



Velgail

リンク

2018/7/14(Sat) 12:55:52|NO.84767

サンプルソースを作ってみました。右下のウェイトサークルを容赦なく描画で潰してくるため、ランダムサークル描画のエリアを避けていますw

#uselib "user32.dll" bgscr 1,480,1 gradf 0,0,160,1,0,$ff0000,$00ff00 gradf 160,0,160,1,0,$00ff00,$0000ff gradf 320,0,160,1,0,$0000ff,$ff0000 buffer 2,64,64 gsel 0 #module #deffunc rcircle int x,int y,int r circle x-r,y-r,x+r,y+r return #deffunc drawCircle count++ if(count>=48){ count-=48 } drawing=ginfo_sel for i,0,10 gsel 1 if(i*48+count*10>480){ pget i*48+count*10-480,0 }else{ pget i*48+count*10,0 } r=ginfo_r g=ginfo_g b=ginfo_b gsel 2 color r,g,b rcircle 32.0+16.0*cos(M_PI*i/5),32.0+16.0*sin(M_PI*i/5),4 next gsel drawing return #global #func SetTimer "SetTimer" int,int,int,int #func KillTimer "KillTimer" int,int #define WM_TIMER 0x0113 #define TIMER_ID 1 ; タイマーID gosub *RedrawClock ; メッセージ処理の登録 oncmd gosub *OnTimer, WM_TIMER ; プログラム終了時の処理の登録 onexit goto *OnQuit ; タイマーを設定(0.25秒間隔) SetTimer hwnd, TIMER_ID, 16, 0 if stat == 0 { dialog "タイマーの設定に失敗しました。", 1, "エラー" end } repeat color rnd(256),rnd(256),rnd(256) rcircle rnd(640-128),rnd(480-128),rnd(64) wait 0 loop *OnTimer ; ====== タイマーメッセージの処理 ====== if wparam == TIMER_ID : gosub *RedrawClock return 0 *RedrawClock ; ====== 再描画処理 ====== drawCircle pos_x@cur=ginfo_cx pos_y@cur=ginfo_cy pos 640-64,480-64 gcopy 2,0,0,64,64 pos pos_x@cur,pos_y@cur return *OnQuit ; ====== 終了時の処理 ====== ; タイマーを破棄 KillTimer hwnd, TIMER_ID end



Kain

リンク

2018/7/14(Sat) 13:47:18|NO.84768

わざわざサンプルソースを作っていただけるなんて!とてもありがたいです!
このソースについて質問なんですが、
circle x-r,y-r,x+r,y+r
で作成した小さい円を一つだけ
にして、その一つの円をなんか、こう、Huaweiのスマホのプログレスバー(参考にして作ったアニメーションがHuaweiなのでw) みたいにしたいのですが...



Kain

リンク

2018/7/14(Sat) 13:49:26|NO.84769

分に抜かりがあったので

Huaweiスマホのような、小さい円を加速現ありで回転させる方法はないでしょうか?
作っていただいたサンプルソースをみていろいろ試しましたが、うまくいかず、ついにはアニメーションがとまったりで...



Y_repeat

リンク

2018/7/14(Sat) 16:14:47|NO.84771

こんにちわ

自分も最近、似たようなことで悩んでましたが
このケースだとループしなくても大丈夫そうです
100ミリ秒なり200秒なりに一回描画すると考えてはどうでしょうか
シングルCPUのマルチな実行のイメージで
(Velgailさんは16ミリ秒にしてみては?っておっしゃてますね)

やってる処理の途中、途中で
サブルーチンで時間を計測して
経過してたら描画サブルーチンを呼ぶかんじだと思います

ってVelgailさんのサンプルスクリプトまんまですね



Kain

リンク

2018/7/14(Sat) 18:37:28|NO.84773

Y_repeatさんこんにちは。
まだあまりよくわかっていませんが、
gosub命令で指定しラベルに移動して、
そこで時間を計測して、指定した時間になったらgosub命令でアニメーション専用の
ラベルに移動させるということですか?

でも、いまだよくわかっていません(;´・ω・)

そして、Velgailさんが作ってくださったソースの*RedrawClockに
アニメーション用で制作した画像をバッファーに保存し、gcopyで描画するようにしてみようと
試したのですが、画像が表示されなかったり、エラーが発生したりといろいろあってうまくいきません...


目的としては、 screen 1でウィンドウを二つ表示させ、screen 1でアニメーションを再生したまま、
データを保存(例として、テキストデータを保存など)行いたいのです。
そのために、裏でデータのセーブ中など(時間がかかる場合)にずっとウィンドウにはアニメーション(全て画像)
を繰り返しさせておきたいのです。

(screen 1に、ウィンドウメッセージとロード、セーブ時の「アニメーション(現在はrepeat3とloop命令で、repeatの繰り返し回数に達したら次の命令でセーブを行うようにしています)」を表示させています)

※日本語文がおかしいのと、意味不明なことばかり言ってるかもしれませんw



あらや

リンク

2018/7/14(Sat) 20:12:26|NO.84774

Huaweiのスマホを持っていないので違うかもしれませんが
たぶんこんな感じでしょうか?

アニメーション部分だけです。

lr = 50; // 周の半径 cr = 5; // 円の半径 arg = 270; // 初期位置(真上) fflag = 1; // 落下フラグ count = 0; // カウンタ(加速度) *main redraw 0; color 0, 0, 0: boxf; cx = cos(deg2rad(arg))*lr + 320; cy = sin(deg2rad(arg))*lr + 240; color 255, 255, 255: circle cx-cr, cy-cr, cx+cr, cy+cr, 1; redraw 1; await 33; if( fflag ) { // 上から下に移動するときは徐々に加速 count++; if( count == 19 ): fflag = 0; } else { // 下から上に移動するときは徐々に減速 count--; if( count == 1 ): count = 0: fflag = 1; } arg += count; arg \= 360; goto *main;



Y_repeat

リンク

2018/7/14(Sat) 21:15:32|NO.84776

こんばんわ。あらやさんのサンプルスクリプトを改造してみました
debug window表示してください
taskマクロでなんか作業してるのをイメージしてください
自分では時間計測書くの時間かかりそうではしょりました



lr = 50; // 周の半径 cr = 5; // 円の半径 arg = 270; // 初期位置(真上) fflag = 1; // 落下フラグ count = 0; // カウンタ(加速度) #define task(%1) await 10 // なんかTASKしてることをイメージして下さい *subr while 1 task hoge task piyo task hogehoge task piyopiyo logmes "hogepiyo" gosub *main_r task bar task baz task barbar task bazbaz logmes "barbaz" gosub *main_r wend *main_r redraw 0; color 0, 0, 0: boxf; cx = cos(deg2rad(arg))*lr + 320; cy = sin(deg2rad(arg))*lr + 240; color 255, 255, 255: circle cx-cr, cy-cr, cx+cr, cy+cr, 1; redraw 1; if( fflag ) { // 上から下に移動するときは徐々に加速 count++; if( count == 19 ): fflag = 0; } else { // 下から上に移動するときは徐々に減速 count--; if( count == 1 ): count = 0: fflag = 1; } arg += count; arg \= 360; return



Kain

リンク

2018/7/14(Sat) 22:59:02|NO.84777

これです!
自分が求めていたものはこれです!ありがとうございます!!
あとは*subrの処理内容を変えておいたらいいだけですかね?(´・ω・`)



Velgail

リンク

2018/7/14(Sat) 23:34:01|NO.84778

ヒント:
私のサンプルソースの、drawCircleは
「呼ばれるたびにモジュール内変数のcountが1増えて、48に達したら0になる」ように設計されています。

同じように、「アニメーションを数式だけで書けるように」して、
数字が1増えるたびにどこに来るかを計算すると、うまく書きやすいです。
例えば以下のように書いてしまうと、きれいに一周で速度差を定義するのが極めて困難に……
(上のサンプルソースの改変部分です。#module〜#global間の差し替えです)

#module #define oneroll 60 #deffunc rcircle int x,int y,int r circle x-r,y-r,x+r,y+r return #deffunc drawCircle if(vartype(rad)==4){ rad=0.0 } count++ if(count>=oneroll){ count-=oneroll } drawing=ginfo_sel gsel 2 cls setease 0.06,0.16,ease_cubic_inout|ease_loop speed=geteasef(count,oneroll/2) rad+=speed rcircle 32.0+16.0*cos(rad),32.0+16.0*sin(rad),4 gsel drawing return #global

けれども、動きに使う角度のグラフを書くと、(ここはひらめきでもあるけど)シグモイド関数っぽい。なら、楽なシグモイド系の関数で置き換えようとする
https://ja.wikipedia.org/wiki/シグモイド関数
今回はx/√(1+x^2)を使ってみて、その振幅を-1〜1のときに0〜2πになるように係数値を調整(ease関数内)して以下の通り。


#module #defcfunc sigmoidal double x return x/sqrt(1.0+x*x) #defcfunc ease double count,double max return M_PI*2*(sigmoidal(count/(max/2)-1)+sqrt(0.5))/sqrt(2) #deffunc rcircle int x,int y,int r circle x-r,y-r,x+r,y+r return #deffunc drawCircle #define oneroll 60 count++ if(count>=oneroll){ count-=oneroll } drawing=ginfo_sel gsel 2 cls rad=ease(count,oneroll) rcircle 32.0+16.0*cos(rad),32.0+16.0*sin(rad),4 gsel drawing return #global

しかし、これを理解できるかどうかはっ……(理解できるように書いた気がしない)



Kain

リンク

2018/7/14(Sat) 23:54:48|NO.84779

な、なるほど(そもそもソース内のコードの意味すら理解出来ていないおバカ)
モジュール内のcoumt命令についてはよく分かりました!
みなさん本当に協力して下さってありがとうございます!
Velgailさんが教えてくださったシグモイド関数のことについては、ネットで色々調べて見たりしてみます!
そして、皆さんが教えてくださったソース内のコードに関しても完全理解していませんので、理解できる所では
頑張って調べたりしようと思います。

aaaさん、あらやさん、Velgailさん、Y_repeatさん。
本当にありがとうございました!!



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