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() を眺めていて気付いたけど、キーの同時押しを取得できないのでは…。リストの一番最初の値しか取得してなくて、他のキー入力は全部捨ててるよな…。
[ ツッコむ ]
以上です。
