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


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0507
エイカHSP3dishにて、起動累計時間をスリープなど除外して記録する方法があるのか?15解決


エイカ

リンク

2018/5/7(Mon) 23:08:33|NO.84288

どうも、お世話になっております

難しいスプリクトとかなしに
ゲームの類に、プレイタイムの記録を
スリープなどは除外して、累計時間を
記録する方法はあるのでしょうか?

gettimeでは、私の技術ではできそうになく
常に回る、メインループとかもないため
私の考えかたでは難しそうです

タイトル画面、各種ゲーム画面、設定画面
著作表示画面の各種ループに何かサブルーチンを噛ませて
やれそうではあるのですが
いい案が思いつかなくて(スリープとかがあると特に)

なにかいいやり方があれば教えてください。



この記事に返信する


エイカ

リンク

2018/5/7(Mon) 23:15:52|NO.84289

追記、ファイル記録設定的には
bsaveとサブルーチンを利用して、以下のような方法をとってます


;***************************** *戦歴セーブ if 機種名判定="Win":chdir カレント if 機種名判定="Win":chdir winセーブフォルダ名 rdata.1.0.0=プレイ時間 rdata.1.0.1=プレイ分 if 機種名判定!"and":bsave "mn-rdata.sav",rdata if 機種名判定="and":bsave "/mnt/sdcard/Android/data/"+andフォルダ+"/mnsave/mn-rdata.sav",rdata if 機種名判定="Win":chdir カレント if 機種名判定="Win":chdir "data" return ;*****************************



ソラ

リンク

2018/5/8(Tue) 11:57:19|NO.84290

累積時間はテキストファイルに保存するとして、
起動中はSetTimerで1秒ごとに割り込みを発生させて、その度に累積時間に+1秒、
ソフト終了時に累積時間をテキストファイルに保存。

でどうでしょうか。



ゆー

リンク

2018/5/8(Tue) 16:22:46|NO.84291

>ソラさん
SetTimer関数はWin32API(Windowsでしか使えない関数)ですのでhsp3dishでは使えませんよ。



Velgail

リンク

2018/5/8(Tue) 18:53:54|NO.84292

画面描画系を常時60fpsを維持するようにして、フレームカウンターで保存する
及びフレーム更新中に前後の差分時間を取り、明らかな異常値を除外して加算という手法が最も楽(なお描画系の実装に難易度が依存する)

かな。



ソラ

リンク

2018/5/8(Tue) 19:21:13|NO.84293

よく見たらHSP3dishで、ですか・・・見逃してました。
ご指摘ありがとうございます。



エイカ

リンク

2018/5/8(Tue) 23:31:39|NO.84294

ソラさん ゆーさん Velgailさん
アドバイスありがとうございます

ソラさんの言われてる方法も
Velgailさんの言われてる方法も
私には難しすぎて、使えれないと思います…
(そもそも、ソラさんの方法はdishでは無理みたいですが)

もう少し、他の方のご意見を待ってみます
ありがとうございました。



あらや

リンク

2018/5/9(Wed) 18:05:14|NO.84298

gettimeを使った秒数計測をやってみました。
若干精度が落ちますがそれほど厳密性は要らないだろうという希望的観測で
ミリ秒は無視しました。

時間だけならまだしも、実行中に年が変わる・月が変わる・日付をまたぐなどが絡むと
急激に面倒な処理になってしまうのが難点ですね。
特に各月の日数がバラバラなのがまた面倒なのと、うるう年がすごく邪魔に思えます。

そんな理由で少々長くなってしまいました。

dim monthdays, 13; // 各月の日数 monthdays = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31; // 開始日時を記録 startyear = gettime(0); // 年 startmonth = gettime(1); // 月 startday = gettime(3); // 日 starthour = gettime(4); // 時 startminute = gettime(5); // 分 startsecond = gettime(6); // 秒 // うるう年の確認 check_year = startyear; gosub *check_leap; // 開始年1月1日から開始月日までの日数………… startyeardays = 0; repeat startmonth - 1, 1 startyeardays += monthdays(cnt); if( cnt == 2 ) : startyeardays += leap; loop startyeardays += startday - 1; // 開始日0時0分0秒から開始時間までの秒数………… startdayseconds = starthour*3600 + startminute*60 + startsecond; *main redraw 0; color 255, 255, 255:boxf; color 0, 0, 0:pos 0, 0; gosub *count_time; mes strf("開始日時\t%d/%02d/%02d %02d:%02d:%02d", startyear, startmonth, startday, starthour, startminute, startsecond); mes strf("計測日時\t%d/%02d/%02d %02d:%02d:%02d", checkyear, checkmonth, checkday, checkhour, checkminute, checksecond); mes "経過秒 = "+passseconds+""; redraw 1; await 17; goto *main; *count_time // 計測日時を記録 checkyear = gettime(0); // 年 checkmonth = gettime(1); // 月 checkday = gettime(3); // 日 checkhour = gettime(4); // 時 checkminute = gettime(5); // 分 checksecond = gettime(6); // 秒 // 開始年1月1日から計測年1月1日までの日数………… SdayfToCdayf = 0; repeat checkyear - startyear, startyear check_year = cnt; gosub *check_leap; SdayfToCdayf += 365; SdayfToCdayf += leap; loop // うるう年の確認 check_year = checkyear; gosub *check_leap; // 計測年1月1日から計測月日までの日数………… checkyeardays = 0; repeat checkmonth - 1, 1 checkyeardays += monthdays(cnt); if( cnt == 2 ) : checkyeardays += leap; loop checkyeardays += checkday - 1; // +- = 経過日数 passdays = SdayfToCdayf + checkyeardays - startyeardays; // 経過日数を秒に換算………… STCseconds = passdays * 24 * 60 * 60; // 計測日0時0分0秒から計測時間までの秒数………… checkdayseconds = checkhour*3600 + checkminute*60 + checksecond; // +- = 経過秒数 passseconds = STCseconds + checkdayseconds - startdayseconds; return; // うるう年の確認 *check_leap /* うるう年の定義 ・4で割り切れる年はうるう年 ・100で割り切れる年はうるう年では無い ・400で割り切れる年はうるう年 */ if( (((check_year\4) == 0) && ((check_year\100) != 0)) || ((check_year\400) == 0) ) { leap = 1; } else { leap = 0; } return;


あまり考えなくてもいいであろう問題ですが
int型で秒を算出している関係上、2038年問題と同様の理由で
合計時間が約68年以上になるとオーバーフローします。

更に同じ理由で(まずありえないでしょうが)
アプリの開始日時から68年以上実行しっぱなしにするとオーバーフローします。



あらや

リンク

2018/5/9(Wed) 18:35:08|NO.84299

それと試していませんが、時間取得なら
getreq で SYSREQ_TIMER を指定する方が手っ取り早いかもしれないですね。



エイカ

リンク

2018/5/9(Wed) 18:49:35|NO.84300

あらやさん、ありがとうございます!

とりあえず、.hspに保存して実行してみました!
見やすくて、これなら何とか
私のスプリクトに組み込めそうです!

これで組み込めないようなら
私はプレイ時間記録を諦めるほうが良さそうなので
これにて解決とさせていただきます!

多分、組み込めると思います
(秒をプレイ時間に換算するぐらいは多分私でも出来ると思う…。)

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



cheperuphy

リンク

2018/5/9(Wed) 22:11:55|NO.84304

もう解決してしまったようですが、、、
繰り上がりを計算するのではなく、秒が更新された時に1秒経ったとみなすと
計算は楽です。
2秒経つ前に必ず呼び出さなくてはいけませんが。

*main redraw 0 color 255, 255, 255:boxf color 0, 0, 0:pos 0, 0 presec = sec sec = gettime(6) if presec != sec : passseconds ++ mes "経過秒 = "+passseconds+"" redraw 1 await 17 goto *main



エイカ

リンク

2018/5/9(Wed) 22:43:56|NO.84305

cheperuphyさん、ありがとうございます!

私のスプリクトでは、「2秒になる前にかならず通る」みたいな
組み方をしていないので、多分その方法では無理だと思います。

大幅なスプリクトの組み直しなどすれば別ですが。



あらや

リンク

2018/5/10(Thu) 21:09:41|NO.84308

もう見ていないかもしれませんが
念のためミリ秒も考慮した秒数計測も貼っておきます。

ミリ秒を小数(double型)にしたため
秒数では太陽の寿命が尽きてもオーバーフローしませんが、
算出の途中に使う日数の限界(約588万年)でオーバーフローします。

もしそれ以上の時間を計測することがあるのなら改造してください。

dim monthdays, 13; // 各月の日数 monthdays = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31; // 開始日時を記録 startyear = gettime(0); // 年 startmonth = gettime(1); // 月 startday = gettime(3); // 日 starthour = gettime(4); // 時 startminute = gettime(5); // 分 startsecond = gettime(6); // 秒 startmisecond = gettime(7); // ミリ秒 追加 // うるう年の確認 check_year = startyear; gosub *check_leap; // 開始年1月1日から開始月日までの日数………… startyeardays = 0; repeat startmonth - 1, 1 startyeardays += monthdays(cnt); if( cnt == 2 ) : startyeardays += leap; loop startyeardays += startday - 1; // 開始日0時0分0秒から開始時間までの秒数………… ;startdayseconds = starthour*3600 + startminute*60 + startsecond; startdayseconds = double(startmisecond)/1000.0 + starthour*3600 + startminute*60 + startsecond; // ミリ秒追加 *main redraw 0; color 255, 255, 255:boxf; color 0, 0, 0:pos 0, 0; gosub *count_time; mes strf("開始日時\t%d/%02d/%02d %02d:%02d:%02d", startyear, startmonth, startday, starthour, startminute, startsecond); mes strf("計測日時\t%d/%02d/%02d %02d:%02d:%02d", checkyear, checkmonth, checkday, checkhour, checkminute, checksecond); mes "経過秒 = "+passseconds+""; redraw 1; await 17; goto *main; *count_time // 計測日時を記録 checkyear = gettime(0); // 年 checkmonth = gettime(1); // 月 checkday = gettime(3); // 日 checkhour = gettime(4); // 時 checkminute = gettime(5); // 分 checksecond = gettime(6); // 秒 checkmisecond = gettime(7); // ミリ秒 追加 // 開始年1月1日から計測年1月1日までの日数………… SdayfToCdayf = 0; repeat checkyear - startyear, startyear check_year = cnt; gosub *check_leap; SdayfToCdayf += 365; SdayfToCdayf += leap; loop // うるう年の確認 check_year = checkyear; gosub *check_leap; // 計測年1月1日から計測月日までの日数………… checkyeardays = 0; repeat checkmonth - 1, 1 checkyeardays += monthdays(cnt); if( cnt == 2 ) : checkyeardays += leap; loop checkyeardays += checkday - 1; // +- = 経過日数 passdays = SdayfToCdayf + checkyeardays - startyeardays; // 経過日数を秒に換算………… ;STCseconds = passdays * 24 * 60 * 60; STCseconds = double(passdays) * 24 * 60 * 60; // ミリ秒用に変更 // 計測日0時0分0秒から計測時間までの秒数………… ;checkdayseconds = checkhour*3600 + checkminute*60 + checksecond; checkdayseconds = double(checkmisecond)/1000.0 + checkhour*3600 + checkminute*60 + checksecond; // ミリ秒追加 // +- = 経過秒数 passseconds = STCseconds + checkdayseconds - startdayseconds; return; // うるう年の確認 *check_leap /* うるう年の定義 ・4で割り切れる年はうるう年 ・100で割り切れる年はうるう年では無い ・400で割り切れる年はうるう年 */ if( (((check_year\4) == 0) && ((check_year\100) != 0)) || ((check_year\400) == 0) ) { leap = 1; } else { leap = 0; } return;



エイカ

リンク

2018/5/10(Thu) 23:24:08|NO.84309

あらやさん、ありがとうございます!
ミリ秒は多分配慮に入れないと思います

ところで、あらやさんさんが提示してくださったスプリクトは
「スリープなどは除外して、累計時間を記録」できる物なのでしょうか?

私の頭では理解できないのですが
例えば、戦闘開始時とターン開始時や戦闘終了時に
このスプリクトを組み込んで記録した場合
何処か途中でスリープした場合でも
次にこのスプリクトを実行した際には
スリープ時間を除外して、きちんと記録されるのでしょうか?
それとも、戦闘中やエフェクト表示などの全てのループに
この処理を組み込まないといけないのでしょうか?

自分でもよく説明できないのですが
助言、よろしくおねがいします。



あらや

リンク

2018/5/11(Fri) 00:24:09|NO.84310

スリープは特に考慮してないですね。

このソースは開始時間から計測時間までに何秒経過したかを算出するものです。

ちょっと昔の2D系RPGゲームなんかに例えると
最初にゲームのタイトル画面でロードを選択した瞬間を『開始時間』に設定し
セーブするときに『計測時間』の処理をを呼び出して
ロードした時間からセーブする時間までに何秒経過したかを算出するような感じです。

ですので、全てのループにこれを組み込む必要はありません。
逆に言うとスリープしようが、戦闘があろうがなかろうが、
ゲームとは関係ないオプション設定みたいなことをしていても
開始時間から計測時間までの全ての時間が合計で算出されます。

もしスリープ等を除いてというのであれば、
除外したい状態に入ったら一旦それまでの時間を計測して別の変数に入れておき
また計測したくなったら再度開始時間を更新しておくというような処理が必要です。

もしくは除外処理中はそれまでとは別の時間計測の処理を用意しておいて
何秒経過したかを記録しておいて
累計時間を保存するときに除外分は引いておくとかでしょうか。



そもそもなんですが、
HSP3dishにスリープ状態かどうかの判別が出来る命令とかありましたっけ?
それが無いとスリープは除外っていうのは無理かと思いますよ。

アプリの起動中はスリープを出来ないようにするみたいなことは
過去ログのどこかで見たことあるような気がしますが。。。



エイカ

リンク

2018/5/11(Fri) 01:20:11|NO.84311

あらやさん、アドバイスありがとうございます!

スリープを考慮できないとのこと
プレイ時間記録機能は諦めることにします

申し訳ないですが。



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