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


HSPTV!掲示板


未解決 解決 停止 削除要請

2021
0728
大富豪時間計測について d3timer()18解決


大富豪

リンク

2021/7/28(Wed) 14:35:03|NO.93343

宜しくお願いします。

d3timer()
windows起動後の経過時間を利用して
ラップタイマーのようなものを作っています。


■質問1
----------------------------------
”ウインドウ起動=計測開始"ではなく、
キー入力で計測開始にしたいです。
----------------------------------

下記のソースではキーINでラップを記録していますが、
それとの差分で解決するハズなんですが、

※気になる点
キーINした瞬間がwindow起動経過時間の4s800msだった場合、
キーIN後の1秒カウントアップ表示が200ms後になると思います。
(キーIN後の経過時間がジャスト1秒で1秒のカウントにならない)

開始 4s400ms ---> 計測完了 6s200ms
 経過=6s-4s:1000ms-400ms+200ms=2s800ms


開始 4s600ms ---> 計測完了 6s800ms
 経過=6s-4s:1000ms-600ms+800ms=2s1200ms
 1000msを超えているので秒数を1up =3s200ms

※表示用の計算と計測用の計算を区別する必要があると思うのですが、
やはり計算するしか方法が無いでしょうか...^^;


■質問2
d3timer()とd3timer()から抽出した秒数[s]の
カウントアップされるタイミングがズレますが何故でしょうか・・・。
(パソコンの性能に依存?)



※以下制作中のソースです
----------------------------
screen 0,400,300,0,10,10
#include "d3m.hsp"
t0=d3timer()
sec=0

repeat
redraw 0
color 0,0,0:boxf:color 200,200,200
pos 10,10
mes "t0="+t0+""
mes "d3timer()="+d3timer()+""
mes "sec="+sec+":ms="+ms+""
mes "1.r1a="+r1a+":r1b="+r1b+""
mes "2.r2a="+r2a+":r2b="+r2b+""
mes "3.r3a="+r3a+":r3b="+r3b+""
mes "sw="+sw+""

stick ky
if ky=32:gosub *rec
if ky=128:end
if sec>60:end

sec=(d3timer()-t0)/1000
tmk=(d3timer()-t0)
aa=str(sec)
bb=str(tmk)
ms=strmid(bb,strlen(aa),strlen(bb))
redraw 1
await 16
loop

*rec
sw+1
if sw=1:r1a=sec:r1b=ms
if sw=2:r2a=sec:r2b=ms
if sw=3:r3a=sec:r3b=ms
if sw=4:end

return



この記事に返信する


ffAddoner

リンク

2021/7/28(Wed) 15:13:13|NO.93344

ミリ秒単位まで気にされていて、とてもすごいです・・・。
どんな結果がお望みなのかわかりませんが・・・
開始 4s400ms ---> 計測完了 6s200ms
経過時間は2s800msではなく1s800ms?
時間の計算ってむずかしいですよね。
コードを読みこみ、下記のように解釈してみました。

/* sec=(now-t0)/1000 //ミリ秒から秒 tmk=(now-t0)//ミリ秒のまま aa=str(sec)//秒を文字列に ex)123 bb=str(tmk)//ミリ秒を文字列に ex) 123456 ms=strmid(bb,strlen(aa),strlen(bb))// 123456 から 123 [ 456 ] を切り出す? */
無駄があるような気がします・・・無駄と言ってすみません。
原型に近い形でリコーデしてみました。

screen 0,400,300,0,10,10 #include "d3m.hsp" t0=d3timer() sec=0 repeat now = d3timer() /* sec=(now-t0)/1000 ;//ミリ秒から秒 tmk=(now-t0);//ミリ秒のまま aa=str(sec);//秒を文字列に ex)123 bb=str(tmk);//ミリ秒を文字列に ex) 123456 ms=strmid(bb,strlen(aa),strlen(bb));// 123456 から 123 [ 456 ] を切り出す? */ tmk = now - t0 // ミリ秒のまま sec = tmk / 1000 // ミリ秒から秒 ms = tmk \ 1000 // 1000で割り切れない余り=ミリ秒 stick ky if ky=32:gosub *rec if ky=128:end if sec>60:end redraw 0 color 0,0,0:boxf:color 200,200,200 pos 10,10 mes "t0="+t0+"" mes "d3timer()="+d3timer()+"" mes "sec="+sec+":ms="+ms+"" mes "1.r1a="+r1a+":r1b="+r1b+"" mes "2.r2a="+r2a+":r2b="+r2b+"" mes "3.r3a="+r3a+":r3b="+r3b+"" mes "sw="+sw+"" redraw 1 await 16 loop *rec sw+1 if sw=1:r1a=sec:r1b=ms if sw=2:r2a=sec:r2b=ms if sw=3:r3a=sec:r3b=ms if sw=4:end return
プログラムは、
1,取得
2,計算
3,入力受付
4,描画
の順に整理してみました。
ど素人の分際で回答して、恐縮です。目的の解は得られたでしょうか。
それでは失礼します。



ffAddoner

リンク

2021/7/28(Wed) 15:14:33|NO.93345

あ、肝心なことを言い忘れました。
いたるところでd3timer()を使っていますが、それが時間のずれの根本のような気がします。
的外れでしたらすみません。
それでは失礼します。



大富豪

リンク

2021/7/28(Wed) 16:11:39|NO.93346

>ffAddoner 様
ご返答ありがとうございます。

そうですね間違えました^^;
開始 4s400ms ---> 計測完了 6s200ms =1s800ms
(秒の単位が単純なマイナスではない(6s-4sが成立しない))


計測の基準がwindows起動時間なのですが、
(計測開始=ウインドウ起動[F5]時間)
【計測開始を何かのキーを押した時】にしたいのです。

F5でウインドウを起動した直後はバックでd3timer()が動いていますが計測は開始せず、
【手動でキーINした時に測定を開始したい(+ラップ記録機能)という感じです。


ラップ計測から続きでプログラムを考えていたのですが、
その計算式と条件式が・・・思考回路がシャットダウンした状況です@@;


※ズレの件了解しました、
ご提示下さったソースは変数に置き換えるという事ですかね。
分かりました色々考えてみます。

ズレていても大きな問題にはならないのですが、
なんか気になりまして;



usagi

リンク

2021/7/29(Thu) 04:19:41|NO.93349

■質問1について
キー入力した時間を記憶して置いて、現在の時間との差分をとると良いと思います。

■質問2について
キー入力した瞬間(直後)の時間を記録する必要があります。
ソースを見ると、キー入力から時間の取得まで、複数の命令やawaitで時間待ちをしている為に、
ズレや精度の悪さが出ていると思われます。
※イメージですが、おおよそ16msの周期での判定なので、msで表示したいなら精度が悪い

一例ですがどうぞ

#uselib "winmm.dll" #cfunc global d3timer "timeGetTime" #module #defcfunc hms int t ; 時分秒表示用 h = (t/36000000) : m = (t/60000)\60 s = (t/1000)\60 : ms = t\1000 return strf("%02d:%02d:%02d.%03d",h,m,s,ms) #global onkey gosub *INTERRUPT_KEY ; キーボードが押されたら割り込みジャンプ #enum STATE_STOP = 0 ; タイマーがストップしている #enum STATE_START ; タイマーがスタートしている state = STATE_STOP ; タイマーの状態 screen 0,400,800,0,100,100: title "Digital stopwatch": font "",48,1 repeat if state = STATE_START { nowTime = oldTime + d3timer() - startTime } ; 計算 redraw 0; 描画開始 color 0,0,0: boxf pos 0,0: color 240,100,150: font "",32,1 ; ↓タイマーの状態表示用 if state = STATE_START: mes "Push S key to STOP\nPush L key to LAP" if state = STATE_STOP : mes "Push S key to START\nPush L key to RESET" color 100,150,240: font "",48,1 mes hms(nowTime) ; 表示用現在時間 repeat lapCount ; ラップ表示用 color 100,100,100: font "",32,0 mes strf("Lap%02d - %s",cnt,hms(lap.cnt)) loop redraw 1 await 16 loop *INTERRUPT_KEY ; キーを押すとここにジャンプします time = d3timer() ; キーを押したすぐ直後の時間を保存 switch iparam case 83 ; Sキー スタート&ストップ if state = STATE_STOP { ; ストップ時はスタート処理 startTime = time ; スタート時間を記憶 state = STATE_START } else:if state = STATE_START { ; スタート時はストップ処理 oldTime += time - startTime ; 今の時間とスタート時間の差を加算 state = STATE_STOP } swbreak case 76 ; Lキー ラップ&リセット if state = STATE_START { ; スタート時はラップ処理 lap.lapCount = oldTime + time - startTime ;過去の時間と今の時間を加算してラップ記憶 lapCount++ } else:if state = STATE_STOP { ; ストップ時はリセット処理 nowTime = 0 oldTime = 0 lapCount = 0 dim laps,10 } swbreak case 27 ; Escキー エンド end swend return



大富豪

リンク

2021/7/29(Thu) 05:01:48|NO.93350

>usagi様
お世話になっております。
ご回答頂きありがとうございます。

※先に質問になって申し訳ないのですが、

>case 76 ; Lキー ラップ&リセット
この部分を case 96 (テンキーの0)、以降数字のコードにすると、
なぜか反応しないのですが何か理由がありますか?
getkeyのコードと同じですよね;

>case 83 ; Sキー スタート&ストップ
case 13 (Enter)は10キーでも反応します。

10キーで操作できないと困る事情がありまして・・・。
(stickからgetkeyに変える予定でした)
すみません;



ffAddoner

リンク

2021/7/29(Thu) 11:25:39|NO.93353

>そうですね間違えました^^;
>開始 4s400ms ---> 計測完了 6s200ms =1s800ms
>(秒の単位が単純なマイナスではない(6s-4sが成立しない))
6s200ms – 4s400ms = 1s800ms
となる計算をしたいのでしたら、計算する単位をひとつに統一することです。
1s = 1000msでしょうから、単純に
6200ms – 4400ms = 1800ms
このように求められると思います。
表示上、s:ms形式にしたければ、表示する際に計算すればいいと思います。
内部的にはms単位で変数に保持しておき、表示の際にs:ms形式にするって感じですね。

>F5でウインドウを起動した直後はバックでd3timer()が動いていますが計測は開始せず、
この表現は少し誤解があるかと思います。
d3timer()は呼び出した時点での経過時間を返しています。
1回の呼び出しで1回しか、時間を返していません。
バックで動かす(様に見せる)にはループで繰り返し呼び出す必要があります。
裏で動いているのは、パソコンのタイマーなんですけどね(*'m`*)

>計測の基準がwindows起動時間なのですが、
>(計測開始=ウインドウ起動[F5]時間)
>【計測開始を何かのキーを押した時】にしたいのです。
キーを押した時にd3timer()を呼び出し、この初回の呼び出しを基準に次のキー押下との差をラップとして表示すれば、ゴールにたどり着いたも同然ではないでしょうか!
すみません、興奮してしまいまして。オリンピック期間中だからでしょうか。脱線してしまい申し訳ありません。
陸上はド素人なので、ラップとはどの時間のことなのか調べてみました。ラップ、スプリット、グロス、ネット、などの時間があるようです!

>ラップ計測から続きでプログラムを考えていたのですが、
>その計算式と条件式が・・・思考回路がシャットダウンした状況です@@;

1s = 1000ms 1m = 60s = 60000ms 1h = 60m = 3600s = 3600000ms 1d = 24*60h = 24*60*60m = 24*60*60*60s = 24*60*60*60*1000ms ; 24が入ると暗算できず・・・恐縮です
と、基本的な単位の変換を復習しておけば、計算するしかなくても、恐くないですよね!
私たちが変換方法を復習するのに1hかかっても、プログラムにしてしまえば、1sもかからないと思いますから(*/m\*)

>ご提示下さったソースは変数に置き換えるという事ですかね。

/* mes d3timer() /*/ ms = d3timer() mes ms //*/
上記は意味がほぼ同じなので、置き換えが可能ですが・・・

//* ; dから考えると分かりにくい・・・ d = d3timer() / 5184000000 h = d3timer() / 3600000 \ 24 ; ズレます m = d3timer() / 60000 \ 60 ; もっとズレます s = d3timer() / 1000 \ 60 ; もっともっとズレます ms = d3timer() \ 1000 ; もっともっともっとズレます mes strf("%d : %02d : %02d : %02d : %03d",d,h,m,s,ms) /*/ ; msから考えるとわかりやすくないですか?お山みたいで美しい・・・ time = d3timer() ms = time \ 1000 ; ms = time / 1 \ 1000 s = time / 1000 \ 60 m = time / 60000 \ 60 h = time / 3600000 \ 24 ; d = time / 5184000000 \ 1 d = time / 5184000000 mes strf("%d : %02d : %02d : %02d : %03d",d,h,m,s,ms) //*/
上記は意味が違うので、「置き換える」ことはできません。置き換えることができるのは、意味が同じときです。
d3timer()をその都度呼び出すのと、変数に保持しておくのは、コードの意味が違うので、「置き換える」という表現に違和感を抱きます。
ちなみに、「ズレます」とは文字のことではなくて、時間のことですからね!(*/o\*)
PS:作ってみると、d3timer()を連続で呼び出したとき、同じ値が返ってくることがあるようです。どうやらwindowsに設定されている「分解能」とやらが関係してくるような。HSPレベルでは1行1行の命令の時間差はあまり気にしなくてもよさそうですね!心配しすぎてすみません・・・。


今更ですが・・・

ms=strmid(bb,strlen(aa),strlen(bb))
このコードが書かれた背景を想像したところ、感動しました。きっと考えに考えて、試行錯誤の末に出来たのでしょう。
きっと努力家です。
マニュアルやプログラミングの本、サンプルスクリプトなどを読むと、いろんなテクニックや良いコード、分かりやすい書き方を覚えられると思います(*'o'*)



ffAddoner

リンク

2021/7/29(Thu) 11:32:55|NO.93354


#include "d3m.hsp" *init repeat if( rap_count >15 ): stop *inkey stick ky if ky=32: gosub *rap ; enter *calc if( rap_count > 0 ){ now = d3timer() first_line = strf("%15dms", now - base); 一行目はスタートからの経過時間 }else{ first_line = "スタートを待っています" } *view redraw 0 color 0,0,0: boxf: color 200,200,200: pos 0,0 mes first_line repeat rap_count ; 各ラップタイム(ms)を表示 if( cnt > 0 ){ mes strf( "#%02d: %10dms [rap: %5dms]", cnt, rap_record(cnt)-base, rap_record(cnt) - rap_record(cnt-1) ) } else { mes strf( "#%02d: %10dms", cnt, rap_record(cnt)-base ) } loop redraw 1 await 16 loop *rap rap_record( rap_count ) = d3timer() ; キーが押された直後の時間を保存しておく base = rap_record( 0 ) ; ifで初回だけ代入してもいいけど・・・ ; rap_record(0)がbaseと分かっていればbase変数は用意しなくても可 ; ただ、後々読み返したときに、rap_record(0)って何だっけ?となりがち・・・ ; base・・・あぁ、何かの基準ね! ; 名前は分かりやすさが一番です(*'m`*) rap_count++ return



ffAddoner

リンク

2021/7/29(Thu) 11:54:39|NO.93355


mes '0'
テンキーとは、外付けテンキーのこと、でしょうか・・・
一体型キーボードはどちらもメインキーボードのようです・・・?
プログラミングって、一つ一つつまずいたところを調べて、トライですよね。
それでは失礼します。



usage

リンク

2021/7/29(Thu) 17:24:11|NO.93359

コレちょっと分かりにくですよね。
windowsの仕組みから話さないと理解が難しいと思うのですが、簡単に把握する方法として

mes iparam

などで、キー割り込みが発生したタイミングのキーコードを確認してみてください。
表示される値がそのボタンの番号です。
わからない時はその変数の中身を覗いてみるのが早いですよ。
(私もそうしてます)

ちなみにgetkeyだとキー情報が連続して変数に代入されますので、押した瞬間だけの判定が必要になるかもですね。
精度の件を気にされないならawaitで時間待ちしてる中でgetkeyでも良いと思います。

>ffAddonerさん
超分かりやすい時間の説明ですね。
ソースも綺麗で、私が雑すぎました。

おっしゃる通りで、後で読んで分かるコードとトライアンドエラーですよね。
「昨日のコードは、他人のコード」と昔に先輩から言われたのを思い出しました。



ffAddoner

リンク

2021/7/29(Thu) 19:33:20|NO.93361


;1d = 24*60h = 24*60*60m = 24*60*60*60s = 24*60*60*60*1000ms ; 24が入ると暗算できず・・・恐縮です 1d = 24h = 24*60m = 24*60*60s = 24*60*60*1000ms
間違えてしまい、恐縮です・・・。失礼しますミp*'ヘ')q



usagi

リンク

2021/7/30(Fri) 03:31:42|NO.93365

>大富豪さん
私10キーを勘違いしてたかもです。
たぶん wparam の方がやりたいことかも。。。 iparamだと"文字"に反応する感じなので48〜になります。
キーボードの右側に付いているやつは wparam だと"キー"なのでgetkey と同じになりますね。
getkeyがご都合がよければ、onkeyのジャンプ先でgetkey使ってから処理でもよいと思います。
(先に時間は記憶してから)

※あと、私ラップじゃなくてスプリット記憶してましたね。。。すみません。 修正しました。

#include "d3m.hsp" #module #defcfunc hms int t ; 時分秒表示用 h = (t/36000000) : m = (t/60000)\60 s = (t/1000)\60 : ms = t\1000 return strf("%02d:%02d:%02d.%03d",h,m,s,ms) #global onkey gosub *INTERRUPT_KEY #enum STATE_STOP = 0 #enum STATE_START state = STATE_STOP screen 0,400,800,0,100,100: title "Digital stopwatch": font "",48,1 repeat if state = STATE_START { nowTime = oldTime + d3timer() - startTime } redraw 0 color 0,0,0: boxf pos 0,0: color 240,100,150: font "",28,1 if state = STATE_START: mes "Enter: STOP \nNum0: SPLIT&LAP" if state = STATE_STOP : mes "Enter: START\nNum0: RESET" color 100,150,240: font "",48,1 mes hms(nowTime) repeat count ;↓修正 color 100,100,100: font "",18,1 mes strf("%02d Slpit: %s - Lap:%s",cnt,hms(splits.cnt),hms(laps.cnt)) loop redraw 1 await 16 loop *INTERRUPT_KEY time = d3timer() getkey keyNumpadZero, 96: getkey keyZero, 48 ;修正 getkey keyEnter, 13: getkey keyESC, 27 ;修正 ;wparam を見てもよい if keyEnter { ;修正 if state = STATE_STOP { startTime = time state = STATE_START } else:if state = STATE_START { oldTime += time - startTime state = STATE_STOP } } if keyNumpadZero | keyZero { ;修正 "テンキー0"か"メインキーボード0" if state = STATE_START { splits.count = oldTime + time - startTime ;修正 laps.count = splits.(count) - splits.(count-(count>0)) ;修正 count++ } else:if state = STATE_STOP { nowTime = 0 oldTime = 0 count = 0 ;修正 dim laps,10 dim splits,10 ;修正 } } if keyESC : end ;修正 return



大富豪

リンク

2021/7/30(Fri) 08:21:02|NO.93370

>ffAddoner様、>usagi様
 ご返答頂き誠にありがとうございます。
 ソースの仕組みやコマンド(?)の理解に
 時間が掛かっている状況でして・・・@@;

■await:
たしか”1秒間あたりのPC処理速度”がどうのと
見た事があったのですが、ちょっと頭を整理します^^;

■起動時(F5/実行ファイルから)の時間のズレ:
PCに負荷が掛かっていない時はいいのですが、
負荷が重いとソースのウインドウが表示された時点で、
既に1秒以上経過していたりします。
ソースが動きだした時点でd3timer()は動いているが、
表示担当者がまだ寝ているという事かもですね。

■d3timer()→固定数:
"PCタイムの呼び出しを何度もしているので、
wait-timeによっては秒[s]単位が変わっていない。
だから最初に値を固定する”
→承知しました。

■キーコード:
iparamなどいろんなコードの取得方法があるんですね・・・。
→勉強します。

---------------
%02d などの表記方法はC言語の関係ですよね(たぶん)。
#付のコマンドや見慣れないコマンドなど、
理解していない部分も多いですが;

思ったプログラムが違和感なくスムーズに動き出すと気持ちがいいですね^^
まずはソースの意味や仕組みを紐解きながら勉強させて頂きます、
お二方とも大変ありがとうございます。



大富豪

リンク

2021/7/30(Fri) 20:28:21|NO.93383

お世話になっております。

お二方のソースを元に応用をしているのですが、
#付コマンドや、%**d(C言語?)などを使った事が無いので
応用にだいぶ・・・(困難な状況です;)

それでusagiさんのNo.93365のソースを元にアレンジを進めましたが、
以下の条件で動作させたいのですが行き詰っている状況です。
ご対応をお願いできますでしょうか。

【1】テンキーの1,2,3,4 (5,6...)でラップを取る。

※押す順番は関係なく、どのキーを押した時のラップタイムなのかを表示し、
計測終了後に数値を取り出せるようにする。

;---キーコードを追加しました。
getkey keyNumpadTwo, 98 ;10keyの 2
getkey keyNumpadThree, 99 ;10keyの 3
getkey keyNumpadFour, 100 ;10keyの 4
(5,6,7......)

;---上記の変数を追加しました。
if keyNumpadZero | keyNumpadTwo | keyNumpadThree | keyNumpadFour{

;--- なんのキーを押したのか変数を追加しました。
if keyNumpadZero=1:keyin=1
if keyNumpadTwo=1:keyin=2
if keyNumpadThree=1:keyin=3
if keyNumpadFour=1:keyin=4

指定したキーでのLAP動作は簡単だと思うのですが・・・


;---末尾に上記の表示を追加しました。
mes strf("%02d Slpit: %s - Lap:%s",cnt,hms(splits.cnt),hms(laps.cnt))+" : keyIN="+keyin+""

※repeat count
ラップ回数分のループで表示している(?)んですかね、
変数の扱いが分からず行き詰っています...。

→その都度のタイムを変数に代入したいのですが可能でしょうか。

(例)
キーイン一回目(4)でLAP1 = time1,key4
キーイン一回目(1)でLAP2 = time2,key1
キーイン一回目(3)でLAP3 = time3,key3
キーイン一回目(2)でLAP4 = time4,key2
とか。

[順番は関係なく4つのキー全てでカウントされたらタイマー停止]


※計測終了後に改めて、
計測結果が代入された変数を使って表示したいです。
(mes "第一位は "+key4+"です " とか)


【2】上記のキーひとつに対して1度だけ記録を取る。
(1度押したキーをもう一度押した場合は何も反応しないようにする)


【3】上記のキーを全て押した時点でメインのタイマーを停止する。
現在エンターで一旦停止しますが、
(4個目のキーを押した時点で自動停止)

4→1→3→2→STOP
1→2→4→3→STOP
(....など順番は関係なく)


【4】それぞれのラップで押されたキー情報を、
あとで取り出して表示できるようにする。

ラップを記録した時点で、
Lap1=**:**** key=2
Lap2=**:**** key=1
Lap3=**:**** key=3
Lap4=**:**** key=4

---------------------------
大変お手数とは思いますが、
何卒宜しくお願いします。



大富豪

リンク

2021/7/30(Fri) 23:55:16|NO.93392

度々申し訳ありません。

かなりの時間プログラムと格闘しております・・・^^;
無駄な部分も多いかもしれませんが、
自力でなんとかなりそうです。

大変お騒がせして申し訳御座いませんでした。



usagi

リンク

2021/7/31(Sat) 00:13:29|NO.93393

>大富豪さん
何となくやりたい事理解できました。
私の例がストップウォッチを想定していたので、書き直した方が早いかもしれないですね。お待ちくださいませ。
※ #付きや%**dは使わないでやってみます。

私のはキー入力と時間の精度に言及したものなので、
ffAddonerさんのサンプルの方が見やすくて分かりやすいかもですよ。
(私は読み解けなかったので、リコーデとかすごいなぁーと思いました)

>#付コマンド
プリプロセッサと呼ばれるもので、今回は定数を指定するものと新しい命令を追加すものを使いました。
この辺りに説明があります。
http://www.onionsoft.net/hsp/v33/doclib/hspprog.htm#PREPROCESSOR

※命令の使い回しと、定数設定を楽する為に使いました。

>%**d
F1のマニュアルだと情報がたりないので、
このサイトがすごく丁寧に説明してくれてます。
http://lhsp.s206.xrea.com/command/strf.html

※文字の表記を楽する為に使いました。

>ラップ回数分のループで表示している(?)んですかね、
その通りでございます。



大富豪

リンク

2021/7/31(Sat) 00:47:44|NO.93395

>usagi 様
ありがとうございます and 大変申し訳ありません

※概略でも最初から明記するべきでしたが、
 やってるうちに色々な欲が出て来まして・・・。
 誠に申し訳ございません。

おおもとの時間(dimtimer)から取り出す方法を少し変更しながら
かれこれ10時間以上は格闘してますが・・・気絶寸前です@@;

>ラップ回数分のループ表示
だと個別LAPの固定数の抽出が”たぶん”出来ない感じだとは思うのですが、
変動している変数を固定化して記憶したり、
時間計算の部分をあれやこれや調整すると、
たぶんうまく行きそうな感じがしている状態ですね。

ただし記述量がかな〜り増えるので、
いかに無駄をなくして効率よく動かすかが、
経験の違いなんでしょうね;

>#付コマンド / >%**d
なんとなく意味合いは分かるのですが、
そのメリットや使うコツなどがよく分からない状態でして;
なんとなく上級者になるほどよく使っている気がします。



usagi

リンク

2021/7/31(Sat) 03:28:58|NO.93396

どうぞ。なるべくコメント多くしてみました。

#include "d3m.hsp" screen 0: title "テンキー押し時間ランキング" ;------------------------------------------------- ; タイトル画面 *GAME_TITLE ; 処理 getkey keyEnter, 13 if keyEnter: goto *GAME_INIT ; 描画 redraw 0 color: boxf pos 0,0: color 200,200,200 mes "Enter でスタート" redraw 1 await 16 goto *GAME_TITLE ;------------------------------------------------- ; ゲーム初期化 *GAME_INIT numpadNum = 9 ; テンキーの数 (4~9に変えてみて下さい) dim numpadLap, numpadNum; テンキーの数分ラップを保存する変数を初期化 dim sortedLap, numpadNum; 後で順位を表示用 onkey gosub *INTERRUPT_KEY startTime = d3timer() ; ゲームを始める直前の時間 ; ↓このまますぐゲームメインへ ;------------------------------------------------- ; ゲームメイン *GAME_MAIN ; 処理 ; テンキーが全部押されているかチェック > 【3】上記のキーを全て押した時点でメインのタイマーを停止する。 check = 0 repeat numpadNum if numpadLap.cnt > 0: check++ loop if check = numpadNum: goto *GAME_RANKING ; 全部押されていたらランキングへ ; 描画 redraw 0 color: boxf pos 0,0: color 200,200,200 ; 時間表示 t = d3timer() - startTime gosub *CALC_TIME mes text ; ラップ表示 mes "\nLap" repeat numpadNum t = numpadLap.cnt gosub *CALC_TIME mes "テンキー"+(cnt+1)+" -> "+text loop redraw 1 await 16 goto *GAME_MAIN ; 分秒表示 (%**d 系を使わないで)大富豪さんの様にstrmidで文字列から切り出す *CALC_TIME ; ここにジャンプする前に表示したい時間を t に代入しておくこと text に文字を保存 m = "0" +str( (t/60000)\60 ) ; 分 s = "0" +str( (t/1000)\60 ) ; 秒 ms ="00"+str( t\1000 ) ; ミリ秒 text = strmid(m,-1,2)+":"+strmid(s,-1,2)+":"+strmid(ms,-1,3) return ; キー入力割り込みジャンプ *INTERRUPT_KEY time = d3timer() ; ボタンを押したすぐ後の時間を一時記憶 num = wparam - 97 ; キーコードに合わせ押したテンキー番号を計算(メインキーボードを使う場合は49から) if num>=0 & num<numpadNum { ; 1から9が押されたら >【1】テンキーの1,2,3,4 (5,6...)でラップを取る if numpadLap.num == 0 { ; そしてまだ押されてなかったら > 【2】上記のキーひとつに対して1度だけ記録を取る。 numpadLap.num = time - startTime; 時間を記憶 } } return ;------------------------------------------------ ; ランキング表示 *GAME_RANKING ;>【4】それぞれのラップで押されたキー情報を、あとで取り出して表示できるようにする。(順位を表示したいとの事) repeat numpadNum sortedLap.cnt = numpadLap.cnt loop sortval sortedLap, 0 ; 小さい順で並び替え ; 順々にランキング表示 redraw 1 color: boxf: pos 0,0: color 200,200,200 repeat numpadNum sortget index, cnt t = numpadLap.index gosub *CALC_TIME mes "第"+(cnt+1)+"位はKey"+(index+1)+"です。->"+text wait 50 loop mes "エンターで終了" ; 終了待ち repeat getkey keyEnter, 13 if keyEnter: goto *GAME_END await 16 loop goto *GAME_RANKING ;------------------------------------------------ ; ゲームエンド *GAME_END end ; 繰り返す場合は(goto *GAME_TITLE)

>そのメリットや使うコツなどがよく分からない状態でして;
この例だといたるところに*CALC_TIMEへのジャンプがありますが、
それを一つの命令として使いやすいように分離し管理しやすくしているが前回のhms(t)です。

%**d系は strmidでしている所のように、数字を文字列に変換する所を
フォーマットを指定して変換できるので、面倒臭くない利点があります。

無理に使う必要はないのでこれらをメリット(楽だなぁ)と感じたら使えばよいかと思います。
ソースが1000行10000行と増えてきたら便利に感じるかもしれません。



大富豪

リンク

2021/7/31(Sat) 11:29:12|NO.93397

>usagi 様
なんと素晴らしい・・・。
丁寧に解説して頂き、
誠にありがとうございます。

自力で7割ほど出来てはいるのですが、
usagiさんのスクリプトの3〜4倍くらいになりそうです^^;
そこらへんが上級者との大きな違いなんでしょうね。

定義の方法やどこでどう変数を使うかとか、
numpadLap.cnt / sortedLap.cnt
***.cntのループとの関連(?)の使い方で、
大きな違いが出るんだと思います。

毎度ですが、
そのまま丸ごとスクリプトを使って完了、ではなく
まずは中身の理解から始めます。

ffAddonerさんのコメントもヒントになりましたし、
大変勉強になりました。

誠にありがとうございました。



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