この記事をおすすめしたい人
- JavaScriptで経過時間に合わせて処理を変えたい人
- JavaScriptで経過時間に合わせて周期的に処理を変えたい人
- つまりオレ
今回はJavaScriptで、経過時間によって変わる処理を考えていきたいと思います。
経過時間によって変わる処理って、例えば…どんなんだろ。
曜日ごとはDateクラスのgetDay()で評価すればいいので、それ以外だと、指定した日時から3日サイクルで処理を変えるとか、3時間ごとに処理を変えるとか、そういうケースでしょうか。
最後に、なぜ僕がこの手の処理をしたくなったのかと実装例も紹介します。
僕はNuxt.js上でしかJavaScriptが書けないので、別の開発環境の人は表記が微妙に違うんじゃないかと思うので、適宜読み替えてください。
経過時間で処理を変える方法
JavaScriptで日付を扱うのはDateオブジェクトです。
ここから経過時間を計算するとなると、
Dateオブジェクトって加算/減算できるのかな…。
とかなるんですが、調べるのがめんどくさかったので、単純にDateオブジェクトのgetTime()でUNIX時間(ミリ秒)を受け取り、それを減算して経過時間をミリ秒単位で取得してみます。
まず、準備として、Dateオブジェクトを使ってUNIX時間を得る場合、インスタンスの作成+getTime()と2工程あるので、可読性を上げるために先にこんな↓関数を用意しておきます。
date2time(date) {
return date.getTime()
}
引数でDateオブジェクトを受け取って、そのgetTime()の実行結果を返すだけ。
Nuxt.js上で実験しているので、一般的なJavaScriptとは表記が違うかもしれません。 その場合は適宜読み替えてください。
//経過時間の起点(例として2022年5月1日の0時)
const startTime = this.date2time(new Date(2022, 5-1, 1, 0, 0, 0))
//現在時刻
const currentTime = this.date2time(new Date())
//経過時間の計算(ミリ秒)
const elapsedTime = currentTime - startTime
Dateオブジェクトは月指定だけ何故か0~11になっているので、意図した月から-1するのを忘れないように。
なんで0スタートなんでしょうね。
これ↓と似たような事情なのかな。 いや、違うか。
記事を書いている現在、2022年5月3日の18時過ぎなので、経過時間は238,245,164ミリ秒となりました。 2日と18時間10分45秒なので合ってますね。
ここまでは不細工なやり方です!
今DateオブジェクトをMDNで調べ直してみると、めちゃくちゃ簡単に加算/減算が可能なようでした。
書き直すとこの↓ようになります。
//経過時間の起点(例として2022年5月1日の0時)
const startTime = new Date(2022, 5-1, 1, 0, 0, 0)
//現在時刻
const currentTime = new Date()
//経過時間の計算(ミリ秒)
const elapsedTime = currentTime - startTime
完全に不要な処理を挟んでしまってましたね。
書き直したコードで計算すると、経過時間は238,609,324ミリ秒で、2日18時間16分49秒。
当然、ちゃんと計算できてますね…。
あとは経過時間に対してどのように処理するかだけです。
経過時間をミリ秒で取得しているので、どの単位で評価するかによって、次のように経過時間を計算し直します。
//秒単位で評価する場合
const time = Math.floor(elapsedTime / (1000))
//分単位で評価する場合
const time = Math.floor(elapsedTime / (1000*60))
//時間単位で評価する場合
const time = Math.floor(elapsedTime / (1000*60*60))
//日単位で評価する場合
const time = Math.floor(elapsedTime / (1000*60*60*24))
単純に経過時間で処理する場合はここまでで終了です。
経過時間に対して周期的に処理を変える方法
ここからさらに経過時間に対して、周期的に処理を変える方法を考えます。
例えば、3時間ごとに表示を変えて、表示する内容が5パターンあって、それをループさせるような場合。
//表示するパターンを配列で用意
const views = ['パターン①','パターン②','パターン③','パターン④','パターン⑤']
//経過時間を時間単位で取得
let time = Math.floor(elapsedTime / (1000*60*60))
//3時間ごとに切り替えるので経過時間を3で割る
time = Math.floor(time / 3)
//今が配列内のどの要素を表示するタイミングか計算
const index = time % views.length
//計算結果の配列の要素を表示
console.log(views[index])
現在、66時間経過で22回目の表示変更。 5パターンを4週して、周期内3つ目を表示するので、出力結果は「パターン③」になります。
なぜ経過時間に対して周期的な処理をしたかったのか
いやねー…。
ちょっと友人からの頼みで、FINAL FANTASY Record Keeper(以下FFRK)というゲームをやることになったんですよ。
このゲーム、2014年9月にリリースされたようで、かれこれ8年近く?続いてるご長寿ガチャゲなんですけども、
近年まれに見るほどのクソUI!
…って、これはまたオレVIEWの方でやる予定。
で、このFFRKにラビリンスダンジョンとかいうのがあります。
ラビリンスダンジョンは日曜の0時を起点として、3日と12時間サイクルでドロップアイテムが更新されるようで、日曜0時、水曜12時、日曜0時…と変わっていきます。
ダンジョンによってサイクルが4か5パターンで周期的に変わっていくので、ダンジョン1は今3パターン目だけど、ダンジョン4は1パターン目みたいなズレが生じるようになっています。
このドロップで得られる装備がどうも各キャラの現状最強装備のようで、ガチャ回さずに強い装備が手に入るのが楽しくて、ちょこちょこ遊んでたわけなんですけども、この周期の情報を大手企業系サイトのアルテマさんで調べていたんですね。
で、みなさんご存じの通り、
僕は企業系ゲーム攻略サイトにとても厳しい人間でして。
あ、別記事で企業系ゲーム攻略サイトに実際にコンテンツをパクられた話をしていますが、アルテマさんのことではないので誤解なきよう。
それとは無関係に、ラビリンスダンジョンのページがもう…、
使いにくいのなんのって!!
おまけにどうも手作業で更新しているようで、休日挟むと更新が遅れたりしていました。
いや、なんで自動化してへんの?
ダンジョンごとのサイクルがズレるせいでヒューマンエラーが起きやすく、手作業が必要になるような不確定要素もないので、自動化した方が絶対に効率がいいです。 そもそもいったん自動化したら更新する手間も省けるし、期日に遅れることもないし、更新漏れも起きないです。
もしかすると末端のスタッフには動的コンテンツを作る権限がないとか、そもそもエンジニアがいないとかなんでしょうか。
まぁ、そんなわけで、
これ、自分でまとめ直した方が使いやすいんじゃね?
というのが今回の企画のスタートになります。
現在、今回の勉強内容をフル活用して作ったツールがローカルサーバで既に稼動しています。 メインの表示部分はアルテマさんの素材を流用してるのでお見せできないんですけど、周期の計算結果だけを試しに10サンプルくらい出力するとこんな↓感じになります。
持ちキャラがちょっと強くなってきて、自分でもデータ収集が出来るようになってきたので、データ取りが終わったらツールを公開しようかなーと考えてます。
友人の依頼からのスタートでしたが、
ひょんなことからいい勉強ができました。
以上、WordPressからお届けしました!