質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

11728閲覧

pythonでの時間制限の設け方

A_sio

総合スコア1

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/12/30 16:35

編集2021/01/01 15:34

前提・実現したいこと

私は、pyxelを利用してゲームを作りたいと考えています。

発生している問題・エラーメッセージ

ご質問したいのは、以下の処理についてです。
・ゲームクリア、ゲームオーバーと表示したx秒後にゲームを終了させる
・ゲーム開始時点からy分経過したら「タイムアップ」と表示し、表示したx秒後にゲームを終了する

以上2点について、datetimeやtimeをインポートする、ということのほかにどのようなことをすれば良いのかがわからず、肝心の文が書けずにいます。
上記の処理を行うためにどのような文を加えると良いのか、お教えいただけるとありがたいです。

補足情報(FW/ツールのバージョンなど)

プログラミングの経験が少なく、こちらのサイトを利用したこともなかったため、的外れな質問の仕方をしていたら申し訳ありません。どなたか回答よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A_kirisaki

2020/12/30 16:37

Python はインデントが命!「```」でソースコードの前後を囲ってください。そして正しくインデントを入れましょう(流石に読めん)。
A_sio

2020/12/31 04:42 編集

ご指摘ありがとうございます。ご不便をおかけし、大変申し訳ありません。 ご指摘いただきました通り、本文の編集を行いましたので、ご確認いただけますとありがたいです。 よろしくお願いいたします。
guest

回答2

0

ベストアンサー

pyxel.frame_count から経過時間を計算する

time() では、ラグ等の稀な条件下でバグの再現が困難になる場合、
時間よりも経過フレーム数から計算した方が都合が良いことも有ります。

pyxel.frame_count は、update が呼ばれる度に増加する数値です。

sched モジュールを使う

Python の標準ライブラリ イベントスケジューラ
pyxel.frame_count をベースに使う方法の紹介。

概要:
例えば「10秒後に実行したい処理A」「1分後に実行したい処理B」がある場合、
後に実行する処理Bの時間を毎回確認するのは無駄が多く、
直近に実行したい処理Aの時間確認のみで良いはずです。

実行する時間でソート済みのリスト(優先度付きのキュー)で管理し、
最初に実行する処理の時間のみを確認するようにします。

ちなみに、Pythonの標準モジュールに、
優先度付きキューのアルゴリズムを実装した heapq モジュールがあり、
それを用いたイベントスケジューラの実装の sched モジュールがあります。

質問に対する直接的な回答ではありませんが、
汎用的な指定時間後に実行の方法。

python

1 2from sched import scheduler 3import pyxel 4 5class Timer: 6 def __init__(self, fps=20): 7 self.fps = fps 8 self.scheduler = scheduler(self.tick) 9 10 def tick(self): 11 return pyxel.frame_count 12 13 def update(self): 14 self.scheduler.run(blocking=False) 15 16 def call_later(self, interval, func, priority=1): 17 self.scheduler.enter( 18 interval*self.fps, 19 priority, 20 func 21 ) 22 23 def call_soon(self, func): 24 self.call_later(0, func) 25 26 def set_interval(self, interval, func): 27 def callback(): 28 if not func(): 29 self.call_later(interval, callback) 30 self.call_later(interval, callback) 31 32 def start_generator(self, gen): 33 def _next(): 34 interval = next(gen, None) 35 if interval is not None: 36 self.call_later(interval, _next) 37 self.call_soon(_next) 38 39 40class App: 41 def __init__(self, fps=20): 42 pyxel.init(200, 200, fps=fps) 43 self.timer = Timer(fps=fps) 44 45 ## 指定時間後に実行 46 # 約15秒後に終了 47 self.timer.call_later(15, pyxel.quit) 48 49 ## JavaScript の setInterval の様に 50 # 一定間隔毎に実行 51 # 毎秒カウント 1..10 52 self.num = 0 53 def count(): 54 self.num += 1 55 return self.num >= 10 56 self.timer.set_interval(1, count) 57 58 ## ジェネレーターを使い時間制御 59 # 10秒後に開始し、5秒間数値をカウント 60 def count_gen(): 61 yield 10 # 10秒sleep 62 for num in range(5): 63 self.num = 10 + num 64 yield 1 # 1秒間隔 65 self.timer.start_generator(count_gen()) 66 67 def update(self): 68 self.timer.update() 69 70 def draw(self): 71 pyxel.cls(7) 72 pyxel.text(10, 10, str(self.num), 10) 73 74 75if __name__ == "__main__": 76 app = App() 77 pyxel.run(app.update, app.draw) 78

要点

  • scheduler のデフォルトの挙動では time を基準としてますが、

 frame_count に差し替える事もできます。

  • pyxel.run はイベントループを持ち、

 scheduler.run も独自のイベントループを持ちます。
そのまま使うと競合して、片方しか実行されない状態になる為
scheduler の方をブロッキングしないようにする。

  • フレーム数ではなく実時間ベースのタイマーにしたい場合は、

 fps 関連の部分を省いてください。

ライブラリの提供するタイマーを使う

pyxel については、ほぼ初見なので詳しくありませんが、
内部でSDLというライブラリを利用してるようなので、
SDLのタイマーをpyxel経由で呼び出せないか調べてみる。
→ ソースコードを検索した限りではなさそう。

※ 但し、SDLのタイマーはOSのスレッドを用いる為、
移植性の事を考えて、敢えて採用してないかもしれません。
提供されてない場合は難しくなるので、他の方法で実装した方が良いです。

投稿2020/12/31 01:36

teamikl

総合スコア8681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A_sio

2020/12/31 04:35

ご回答いただきありがとうございます。 ご回答を元にプログラムを編集し、4の※内の処理は行うことができました。 しかし、5の「3分経過したら「タイムアップ」と表示して終了」の処理をうまく行うことができませんでした。 具体的には、 ・self.numの数値は0のままで良いのか ・30秒前から(150秒経過後から)30,29とカウントする方法は上記(プログラム(変更後))であっているのか ・最後のelse self.num = 0:  の部分が上記のプログラムのまま実行すると「SyntaxError」というエラーになってしまうが、変更すべき  箇所がわからない 以上の3点について、解決方法をお教えいただけますと大変ありがたいです。 (もし他に、こちらが気づけていない変更すべき点があれば、併せてお教えいただけると助かります。) 何度もお手数をおかけしてしまい、申し訳ありません。 お手隙の際にお教えいただけますとありがたいです。よろしくお願いいたします。
teamikl

2020/12/31 05:49

self.num の部分は使い方のサンプルとして書いただけなので、 実際のプログラムで不要なら省いてください。 >30秒前から(150秒経過後から)30,29とカウントする方法は上記(プログラム(変更後))であっているのか カウントダウンなので逆順にした方が良さそうです range(30) -> range(30, 0, -1) >最後のelse self.num = 0: else は条件式を書くことが出来ないので、 elif です。
A_sio

2020/12/31 06:31

迅速なご対応ありがとうございます。 3つ目の項目、 「最後のelse self.num = 0: の部分が上記のプログラムのまま実行すると「SyntaxError」というエラーになってしまうが、変更すべき箇所がわからない」について、 お教えいただいた通りelifに変更したのですが、同じエラーが出てしまいました。 他にどこか変更すべきところがあるのでしょうか? 自分でも色々といじってみたのですが、解決できなかったので再度ご質問させていただきました。 何度もお手を煩わせてしまい、申し訳ありません。 「該当のソースコード(変更後)」を更新してありますので、お手隙の際にお教えいただけますとありがたいです。よろしくお願いいたします。
teamikl

2020/12/31 06:35 編集

もう一点見落としてました elif self.num = 0: は = がひとつなので代入文になってますね。 条件の比較が必要なので elif self.num == 0: とします。 もしくは、条件に当てはまらなかった場合として else: でもよいはずです。
teamikl

2020/12/31 06:38

元のコードはあまりみてなかったのですが、懸念のある点 elif で繋げると、最初に条件に一致したブロックしか実行されません。 他のブロックでは別条件の score を比較してるので、 もしそれぞれが独立したブロックなのであれば elif -> if に変更してください。
A_sio

2020/12/31 07:19

無事動きました。 ご丁寧に答えてくださり、本当にありがとうございました。
guest

0

ゲームを終了させる時間、タイムアップする時間、を予め現在時間から算出しておきます。
そして、updateなどの定期実行するところで、その時刻と現在時の差分を求めて、その時刻を過ぎているかどうかを判定します
それによりゲームを終了させるような処理を走らせるようにすればいいかと。

投稿2020/12/30 21:47

y_waiwai

総合スコア88024

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問