2017/09/15(金) [n年前の日記]
#1 [pi3d][python][raspberrypi] pi3dでキー入力を取得
2Dのリアルタイムゲームを作りたいならキーボード入力の取得ぐらいはできないと話にならないだろう、と思えてきたので、pi3dでキー入力を取得する方法について少し調べたのだけど。これが…ちょっとなかなか厳しい気配が…。
◎ フツーに取得。 :
pi3d_demos のサンプルを眺めながら、フツーに取得するソレを試してみたり。
_get_keyboard1.py
_airplane_01_64x64.png (CC0 License)
動いた。と思いきや、これはこれでかなり問題が。動きをよく見ると分かるけど…。キーを押すと、「タッ……タタタタタ」という感じの動きになってしまっている。
要するに、ブラウザやエディタ等で文字を打ち込む際に、キーのオートリピートが働いたりするけど、アレがそのまま入力されてる・取得されてしまっているわけで。
ゲームを作ろうとした場合、コレは非常にマズイ。インベーダーゲームですら、レバーを倒してから自機が「タッ……タタタタタ」なんて動いたりしないわけで。ということで、このやり方はマズイ。これじゃ使い物にならない。
_get_keyboard1.py
_airplane_01_64x64.png (CC0 License)
u""" pi3d input keyboard sample. キーボード入力を取得してみるサンプル。 WASDキーで上下左右に動かしてみる。 ESCキーで終了する。 Windows10 x64 + Python 2.7.12 32bit + pi3d 2.21 """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import pi3d # ウインドウ生成 display = pi3d.Display.create(w=640, h=480, frames_per_second=60) # シェーダーを生成。uv_flatは照明関係の計算をしない。 shader = pi3d.Shader("uv_flat") # カメラを平行投影に camera = pi3d.Camera(is_3d=False) # テクスチャを読み込み tex = pi3d.Texture("airplane_01_64x64.png", mipmap=False) # スプライトを生成 x, y, z = 0.0, 0.0, 20.0 spr = pi3d.ImageSprite(tex, shader, w=64, h=64, x=x, y=y, z=z) # スプライトをDisplayに登録 display.add_sprites(spr) # キーボード取得用クラスを生成 keys = pi3d.Keyboard() # メインループ while display.loop_running(): spd = 8.0 # キー入力で座標を変化させる k = keys.read() if k == ord("w"): spr.translateY(spd) # スプライトのy座標を変化 if k == ord("a"): spr.translateX(-spd) # スプライトのx座標を変化 if k == ord("s"): spr.translateY(-spd) if k == ord("d"): spr.translateX(spd) if k == 27: # ESCキーが押されたらループを抜けて終了 keys.close() display.destroy() break
動いた。と思いきや、これはこれでかなり問題が。動きをよく見ると分かるけど…。キーを押すと、「タッ……タタタタタ」という感じの動きになってしまっている。
要するに、ブラウザやエディタ等で文字を打ち込む際に、キーのオートリピートが働いたりするけど、アレがそのまま入力されてる・取得されてしまっているわけで。
ゲームを作ろうとした場合、コレは非常にマズイ。インベーダーゲームですら、レバーを倒してから自機が「タッ……タタタタタ」なんて動いたりしないわけで。ということで、このやり方はマズイ。これじゃ使い物にならない。
◎ TestEvents.pyが動かない。 :
_pi3dのFAQページ
によると、
_pi3d_demos の TestEvents.py
を実行するとキー入力やマウス入力、ジョイスティック入力を取得する様子を確認できるよ、と書いてある。
試してみたところ、Raspberry Pi Zero W 上では動作した。
ところが、Windows上で実行するとエラーが出る。
調べてみたところ、Windows版Pythonに、fcntl というモジュールは無いようで。fcntl は Linux版Pythonでしか使えないという…。
_python - fcntl substitute on Windows - Stack Overflow
上記フォーラムで、「fcntl.py というファイルを作って、中でこういう記述をすれば、とりあえずエラー回避はできるよ。機能としては一切働かないけどな」と書かれていたので試してみたのだけど。
「fcntlなんてモジュールはねえよ」と怒られなくなったものの。しかし今度は、「/proc/bus/input/devices なんてファイルもディレクトリもねえよ」と怒られるという。…うん。そのファイル、Linuxは持ってるけどWindowsが持ってるわけないんだよねえ…。
_epics/powermate-event - Epics Users JP
Linuxに接続された入力デバイスの状態は、そこで提示されるという仕組みで…。Windowsにはそんなの無いんだよ…。
ということで、Windows上でも動くようにと考えると、TestEvents.py のソレではダメっぽいなと。
試してみたところ、Raspberry Pi Zero W 上では動作した。
- キーを押した瞬間
- キーを離した瞬間
- オートリピートが働いてキー入力された瞬間
ところが、Windows上で実行するとエラーが出る。
> python TestEvents.py Traceback (most recent call last): File "TestEvents.py", line 6, in <module> from pi3d.event.Event import InputEvents, code_to_key File "C:\Python\Python27\lib\site-packages\pi3d\event\Event.py", line 4, in <module> from pi3d.event import EventHandler File "C:\Python\Python27\lib\site-packages\pi3d\event\EventHandler.py", line 4, in <module> from pi3d.event.EventStream import EventStream File "C:\Python\Python27\lib\site-packages\pi3d\event\EventStream.py", line 1, in <module> import fcntl ImportError: No module named fcntl
調べてみたところ、Windows版Pythonに、fcntl というモジュールは無いようで。fcntl は Linux版Pythonでしか使えないという…。
_python - fcntl substitute on Windows - Stack Overflow
上記フォーラムで、「fcntl.py というファイルを作って、中でこういう記述をすれば、とりあえずエラー回避はできるよ。機能としては一切働かないけどな」と書かれていたので試してみたのだけど。
> python TestEvents.py Traceback (most recent call last): File "TestEvents.py", line 30, in <module> inputs = InputEvents( key_handler_func, mouse_handler_func, joystick_handler_func, syn_handler_func, unhandled_handler_func) File "C:\Python\Python27\lib\site-packages\pi3d\event\Event.py", line 70, in __init__ keyboards = find_devices("kbd") File "C:\Python\Python27\lib\site-packages\pi3d\event\FindDevices.py", line 179, in find_devices with open("/proc/bus/input/devices", "r") as filehandle: IOError: [Errno 2] No such file or directory: '/proc/bus/input/devices'
「fcntlなんてモジュールはねえよ」と怒られなくなったものの。しかし今度は、「/proc/bus/input/devices なんてファイルもディレクトリもねえよ」と怒られるという。…うん。そのファイル、Linuxは持ってるけどWindowsが持ってるわけないんだよねえ…。
_epics/powermate-event - Epics Users JP
Linuxに接続された入力デバイスの状態は、そこで提示されるという仕組みで…。Windowsにはそんなの無いんだよ…。
ということで、Windows上でも動くようにと考えると、TestEvents.py のソレではダメっぽいなと。
◎ pi3d.Keyboard.PygameKeyboardをどうにかできれば。 :
_pi3d/Keyboard.py
を眺めた感じでは、Windows上でpi3dを動かした場合、pi3d.Keyboard() は pi3d.Keyboard.PygameKeyboard() を返すようで。ということは、pygame がキー入力をそれらしく取得できるなら、pi3d 上でもキー入力を取得できるように変更できそうな…。
しかしコレ、pi3d.Keyboard.PygameKeyboard() の read() を眺めていて気付いたけど、キーの同時押しを取得できないのでは…。リストの一番最初の値しか取得してなくて、他のキー入力は全部捨ててるよな…。
しかしコレ、pi3d.Keyboard.PygameKeyboard() の read() を眺めていて気付いたけど、キーの同時押しを取得できないのでは…。リストの一番最初の値しか取得してなくて、他のキー入力は全部捨ててるよな…。
[ ツッコむ ]
以上です。