豊橋市の鍼灸・指圧マッサージ小浜治療院

小浜治療院トップページ > 趣味に関して 目次 > Pygame その1

Pygame その1

Pygameをいじっていて、気づいたことがあるので書き留めておきます。

プログラムを組んで、いざ動かそうとすると、キー入力が速すぎて困りませんか?
1回押しただけなのに2つ以上反応する、みたいな。
キー入力の間隔が短い、間隔が速すぎる、等


解決策として提示されるのが
pygame.key.get_pressed()

pygame.event.get()
でキー入力を受け付けて、
その対処として pygame.key.set_repeat() をつかう。みたいな

以下のファイルを作ってみて、pygame.key.set_repeatの効果を確認してください。



import pygame
import sys

def main()
  global tmr

  pygame.init() #初期化
  screen = pygame.display.set_mode((300,400)) #邪魔にならない控えめなウインドウ

  clock = pygame.time.Clock()

  tmr = 0
  fps = 15 #毎秒のフレーム数
  #pygame.key.set_repeat(1000, 20) #この効果を見る

  while True:
    tmr = tmr + 1
    keys = pygame.key.get_pressed() #get_pressedで入力を監視している

    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
      if event.type == pygame.KEYDOWN:
        if event.type == pygame.K_LCTRL or event.type == pygame.K_RCTRL: #イベントハンドラで監視している
          print(str(tmr))

    if keys[pygame.K_SPACE] == 1: #get_pressedで入力を監視している
      print(str(tmr))

    pygame.display.update()
    clock.tick(fps)

if __name__ == "__main__":
  main()


まずはset_repeat()のところは#で無効化しておいてください。
とりあえず、実行すると(インデントがズレていたら、各自調節してください)スペースを押すか、CTRLキーを押すかでtmrが書き出されます。


get_pressed()の方、スペースキーは押している間ずっとtmrが書き出されます。
離すと止まります。
while True でループしている間、1周に1回get_pressedで監視しています。
なので、押している間、tmr が1周するごとに1反応します。
1周の周期はclock.tick(fps)で管理していますので、今回は1秒で15周、つまり15回押すことになります。
本人は短く押しているつもりでも2周に引っ掛かれば2回押したことになります。


KEYDOWNの方、CTRLキーはイベントハンドラで、1回押すと1回だけ反応します。
押しっぱなしでは連続入力を受け付けてくれません。
もう1回反応してもらうには、一度キーを放さなければならないのです。


では、set_repeat()の前の#を外して、set_repeat()の部分を有効にして実行してみましょう。
スペースキーの方は何の変化もありません。
押しっぱなしでも、短く押しても、get_pressed()は先ほどと変化なしです。
CTRLキーはどうでしょう。
短く押したら、先ほどと同じように1回しか反応しません。
しかし、押しっぱなしにしたら、連続入力を始めました。
これがpygame.key.set_repeat(1000, 20) の効果です。


pygame.key.set_repeat()はget.KEYDOWNのための関数です。
pygame.key.set_repeat()はget_pressedに影響を及ぼしません。
pygame.key.set_repeat(delay, interval)の1つ目の引数(delay)は最初の反応から2番目の反応までの待ち時間(ミリ秒)です。
pygame.key.set_repeat(delay, interval)の2つ目の引数(interval)は2番目の反応以降の待ち時間(ミリ秒)です。
なので、pygame.key.set_repeat(1000, 20)だと、
押しっぱなしにしたとき、1番目はすぐ反応します。1秒(1000ミリ秒)以上押しっぱなしにすると、2番目以降20ミリ秒間隔で反応します。
離したら最初の状態に戻ります。ということです。


これらはスペースキーを押したときは、tmrが1ずつ増加するのに対して、
ctrlキーの連続入力は同じtmrが何度も出てくる(ループ1周の内に何度も反応している)ことから分かります。


これらのことから、get_pressed()、 pygame.KEYDOWN 、key.set_repeat()をうまく使い分けてください。





残念ながら、2023年9月現在、get_pressed()で無駄な連続入力をスマートに回避する方法を私は知りません。
誰か教えて(涙)


皆さんの助けになれれば幸いです。

小浜治療院トップページに戻る