Edited at

ebiten でキーが押された初回のみを判定する

More than 1 year has passed since last update.


2018/03/03 更新

表題の機能が ebiten/inpututil に実装されましたので、この記事のようなコードを自前実装する必要はなくなりました。

今後は inpututil を使いましょう。


ebiten にはキーボードが押下されているかを判定する IsKeyPressed関数 がありますが、この関数は押下されている間は常に true を返します。

大抵は問題ないかもしれませんが、場合によっては不便になることがあります。

例えば2D格闘ゲームを作ろうとしたとき、押下時に常に true が返ると、ボタンを押しっぱなしにするだけで百烈張り手やエレクトリックサンダーが出せてしまいます。

やはりこういった必殺技は、ボタン連打操作で発生するようにしたいです。

そこで、ボタンを押下した初回のみ true を返す関数を実装してみます。


ソースコード

type BaseSprite struct {

Images []*ebiten.Image // アニメーションさせる画像の配列
ImageNum int // 総イメージ数
CurrentNum int // 現在何枚目の画像が表示されているか
Position Position // 現在表示されている位置
count int // フレーム数のカウンター
keyPressed map[ebiten.Key]bool // 現在なんのキーが押されているか
}

func NewSprite(images []*ebiten.Image) *BaseSprite {
return &BaseSprite{
Images: images,
ImageNum: len(images),
keyPressed: make(map[ebiten.Key]bool),
}
}

// IsKeyPressed は指定したキーが現在押下されているか判断し返す
func (s *BaseSprite) IsKeyPressed(key ebiten.Key) bool {
pressed := ebiten.IsKeyPressed(key)
if pressed {
s.keyPressed[key] = true
}
return pressed
}

// IsKeyReleased は指定されたキーが現在押下されていないか判断し返す
func (s *BaseSprite) IsKeyReleased(key ebiten.Key) bool {
// キーは押されていると記録されていたが, 実際にはキーは押されていない -> キーがリリースされた
if s.keyPressed[key] && !ebiten.IsKeyPressed(key) {
s.keyPressed[key] = false
return true
}
return false
}

// IsKeyPressedOneTime はキーが押下された初回のみ true を返す
func (s *BaseSprite) IsKeyPressedOneTime(key ebiten.Key) bool {
pressed := s.keyPressed[key]
// キーが押下されているが, リリースはされていない -> キーが押されっぱなし
if pressed && !s.IsKeyReleased(key) {
return false
}
return s.IsKeyPressed(key)
}

keyPressed map[ebiten.Key]bool のような map を作って現在押下されているキーの状態を保存します。

保存した状態を、自作の IsKeyPressedIsKeyReleased のような関数から参照し、現在のキーの状態を取得できるようにします。

キーが押下さているか、押下されていないか、という2つの状態が判断できるようになれば、あとは IsKeyPressedOneTime のように押下時のみ true を返す関数が作れるようになります。


まとめ

簡単に作れるかと思ったら、意外とややこしかった。