2017/09/21(木) [n年前の日記]
#1 [pi3d][python][raspberrypi] pi3dでキーボード入力をチェックするあたりがなんとかなったかも
pi3dでキーボード入力をチェックすると、「タッ……タタタタ」となったり、同時押しが検出できなかったりした件について。pi3d.InputEvents を使って、少しはマシになるような処理を書いてみたり。
一応、Windows、Ubuntu Linux 、Raspberry Pi Zero W上で、同じように動くことを確認できた。と言っても、Windowsはpygameを、Linux と Raspberry Pi は pi3d.InputEvents を使うように処理を分けてあるけど。
以下は、Raspberry Pi Zero W 上で撮ったスクリーンショット。ホントは動画で見せないと動きが伝わらないけど、デスクトップを動画としてキャプチャする方法が分からない…。でもまあ、とりあえず、画面が出てることぐらいの証拠にはなる…かな…。ちなみにキャプチャには、 _raspi2png を使った。
以下は、Ubuntu Linux 16.04 実機上で動かした際の様子を動画でキャプチャ。キャプチャには、 _SimpleScreenRecorder を使った。
「タッ……タタタタ」な動きになってないこと、及び、斜め移動ができてる=キーの同時押しを検出できてることぐらいは伝わるかなと。
一応、Windows、Ubuntu Linux 、Raspberry Pi Zero W上で、同じように動くことを確認できた。と言っても、Windowsはpygameを、Linux と Raspberry Pi は pi3d.InputEvents を使うように処理を分けてあるけど。
以下は、Raspberry Pi Zero W 上で撮ったスクリーンショット。ホントは動画で見せないと動きが伝わらないけど、デスクトップを動画としてキャプチャする方法が分からない…。でもまあ、とりあえず、画面が出てることぐらいの証拠にはなる…かな…。ちなみにキャプチャには、 _raspi2png を使った。
以下は、Ubuntu Linux 16.04 実機上で動かした際の様子を動画でキャプチャ。キャプチャには、 _SimpleScreenRecorder を使った。
「タッ……タタタタ」な動きになってないこと、及び、斜め移動ができてる=キーの同時押しを検出できてることぐらいは伝わるかなと。
◎ ソース。 :
以下、WASDキーかカーソルキーで、スプライトを動かすだけのスクリプト。ESCで終了。
_get_keyboard3.py
_airplane_01_64x64.png
少し説明しておくと…。
pi3d を import して pi3d.Display.create() で初期化をすると、pi3d.USE_PYGAME という変数に値が設定される。pygame を使ってたら True、使ってなかったら False。
なので、その変数を見て、pygame を使ってたら pygame でキーボード情報を取得。pygame を使ってなかったら pi3d.InputEvents でキーボード情報を取得するようなクラスを作成した。
上記のソースでは、KeyboardStatusクラスの中で、pygameを利用するクラスと、pi3d.InputEvents を利用するクラスの2つを用意して、pi3d.USE_PYGAME を見てどちらかを選んでる。
_get_keyboard3.py
_airplane_01_64x64.png
u""" pi3d input keyboard with pygame or InputEvents sample. Sample script to get keyboard input. Move the sprite up, down, left and right with WASD key or cursor key. use pygame.key.get_pressed / pi3d.InputEvents. Press ESC key to exit. Windows10 x64 + Python 2.7.12 32bit + pi3d 2.21 + pygame 1.9.3 Author : mieki256 License : CC0 """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import pi3d import pygame class KeyboardStatus(object): u"""Keyboard status.""" # referenc : # pi3d/event/Keys.py # https://www.pygame.org/docs/ref/key.html keys_list = { "KEY_ESC": pygame.K_ESCAPE, "KEY_A": pygame.K_a, "KEY_B": pygame.K_b, "KEY_C": pygame.K_c, "KEY_D": pygame.K_d, "KEY_E": pygame.K_e, "KEY_F": pygame.K_f, "KEY_G": pygame.K_g, "KEY_H": pygame.K_h, "KEY_I": pygame.K_i, "KEY_J": pygame.K_j, "KEY_K": pygame.K_k, "KEY_L": pygame.K_l, "KEY_M": pygame.K_m, "KEY_N": pygame.K_n, "KEY_O": pygame.K_o, "KEY_P": pygame.K_p, "KEY_Q": pygame.K_q, "KEY_R": pygame.K_r, "KEY_S": pygame.K_s, "KEY_T": pygame.K_t, "KEY_U": pygame.K_u, "KEY_V": pygame.K_v, "KEY_W": pygame.K_w, "KEY_X": pygame.K_x, "KEY_Y": pygame.K_y, "KEY_Z": pygame.K_z, "KEY_0": pygame.K_0, "KEY_1": pygame.K_1, "KEY_2": pygame.K_2, "KEY_3": pygame.K_3, "KEY_4": pygame.K_4, "KEY_5": pygame.K_5, "KEY_6": pygame.K_6, "KEY_7": pygame.K_7, "KEY_8": pygame.K_8, "KEY_9": pygame.K_9, "KEY_UP": pygame.K_UP, "KEY_DOWN": pygame.K_DOWN, "KEY_LEFT": pygame.K_LEFT, "KEY_RIGHT": pygame.K_RIGHT, "KEY_SPACE": pygame.K_SPACE } class PygameKeyStatus(object): u"""Keyboard status with pygame.""" def __init__(self): """Init.""" pygame.init() def update(self): """Update.""" pygame.event.pump() self.keys = pygame.key.get_pressed() pygame.event.clear() def key_pressed(self, key_str): """Get key press state. @param key_str key kind string @return True or False """ return self.keys[KeyboardStatus.keys_list[key_str]] def close(self): """Close.""" pygame.quit() class Pi3dInputKeyState(object): """Keyboard status width pi3d.InputEvents.""" def __init__(self): """Init.""" self.inputs = pi3d.InputEvents() def update(self): """Update.""" self.inputs.do_input_events() def key_pressed(self, key_str): """Get key press state. @param key_str key kind string @return True or False """ return (self.inputs.key_state(key_str) != 0) def close(self): """Close.""" pass def __init__(self): """Init.""" self.keyboard = pi3d.Keyboard() if pi3d.USE_PYGAME: self.state = KeyboardStatus.PygameKeyStatus() else: self.state = KeyboardStatus.Pi3dInputKeyState() def update(self): """Update.""" self.pikey = self.keyboard.read() self.state.update() def key_pressed(self, key_str): """Key press check. @param key_str key kind @return True or False """ return self.state.key_pressed(key_str) def esckey_pressed(self): """ESC key press check. @return True or False """ return (self.pikey == 27 or self.key_pressed("KEY_ESC")) def close(self): u"""Close.""" self.keyboard.close() self.state.close() display = pi3d.Display.create(w=640, h=480, frames_per_second=60) shader = pi3d.Shader("uv_flat") camera = pi3d.Camera(is_3d=False) x, y, z = 0.0, 0.0, 20.0 tex = pi3d.Texture("airplane_01_64x64.png", mipmap=False) spr = pi3d.ImageSprite(tex, shader, w=64, h=64, x=x, y=y, z=z) display.add_sprites(spr) inputs = KeyboardStatus() while display.loop_running(): inputs.update() spd = 6.0 if inputs.key_pressed("KEY_W") or inputs.key_pressed("KEY_UP"): spr.translateY(spd) if inputs.key_pressed("KEY_S") or inputs.key_pressed("KEY_DOWN"): spr.translateY(-spd) if inputs.key_pressed("KEY_A") or inputs.key_pressed("KEY_LEFT"): spr.translateX(-spd) if inputs.key_pressed("KEY_D") or inputs.key_pressed("KEY_RIGHT"): spr.translateX(spd) if inputs.esckey_pressed(): inputs.close() display.destroy() break
少し説明しておくと…。
pi3d を import して pi3d.Display.create() で初期化をすると、pi3d.USE_PYGAME という変数に値が設定される。pygame を使ってたら True、使ってなかったら False。
なので、その変数を見て、pygame を使ってたら pygame でキーボード情報を取得。pygame を使ってなかったら pi3d.InputEvents でキーボード情報を取得するようなクラスを作成した。
上記のソースでは、KeyboardStatusクラスの中で、pygameを利用するクラスと、pi3d.InputEvents を利用するクラスの2つを用意して、pi3d.USE_PYGAME を見てどちらかを選んでる。
◎ 問題点。 :
pygameを利用した場合はコレと言って問題はないのだけど。pi3d.InputEvents を利用した場合は少々問題があって。OSの、キーボード入力やマウス入力を、全部奪ってしまうっぽいのだよな…。なので、以下のような怖い状態に。
であるから、何かしらのキーを押せばスクリプトが終了するような処理を、必ず、絶対、メインループに入れておかないといけない。それをうっかり忘れてスクリプトを動かしたが最後、デスクトップの操作が一切できなくなるので、電源コンセントを引っこ抜いて強制終了、てなことになる。
てな怖さを考えると…。pi3d が pygame を使えない状態にしてしまう Raspberry Pi上では仕方ないとしても、せめて Linux上で動かすときは、pygame を使って動くスクリプトを書いたほうがいいのでは、と思えたりもして。
ちなみに、pygame を使いたい場合は、pi3d.Display.create() に use_pygame=True を渡せばいい。
_pi3d Package - pi3d 2.21 documentation
pi3d は、現状、以下のような処理をしてる模様。
- Ctrl + C を押してもスクリプトが止まってくれない。
- マウスを動かしてもマウスカーソルが動かないから、ウインドウの閉じるボタンを押せない。
であるから、何かしらのキーを押せばスクリプトが終了するような処理を、必ず、絶対、メインループに入れておかないといけない。それをうっかり忘れてスクリプトを動かしたが最後、デスクトップの操作が一切できなくなるので、電源コンセントを引っこ抜いて強制終了、てなことになる。
てな怖さを考えると…。pi3d が pygame を使えない状態にしてしまう Raspberry Pi上では仕方ないとしても、せめて Linux上で動かすときは、pygame を使って動くスクリプトを書いたほうがいいのでは、と思えたりもして。
ちなみに、pygame を使いたい場合は、pi3d.Display.create() に use_pygame=True を渡せばいい。
_pi3d Package - pi3d 2.21 documentation
pi3d は、現状、以下のような処理をしてる模様。
- Windows上で動かす場合は、何も指定しなくても pygame が有効になる。
- Raspberry Pi上で動かす場合は、指定しても pygame が無効になる。
- Linux上で動かす場合は、指定によって pygame の有効/無効が変わる。
[ ツッコむ ]
以上です。