Chapter 38

入力を受け取ろう / Ebitengineの入力とinpututil

eihigh
eihigh
2025.01.31に更新

今回はEbitengineにおける入力の扱い方について説明します。minitenと違ってEbitengineならマウス・キーボード・ゲームパッド・タッチパネルなど幅広い入力を扱うことができます。そのすべての詳細に触れるのは大変なので、今回はよく使うものの解説と、残りはざっくりとした紹介にとどめます。

マウス

IsClicked のようにクリックしたかどうかを調べるには ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) を使います。

このプログラムはマウスの左ボタンが押されている間、画面に "Clicked!" と表示します。

func (g *game) Draw(screen *ebiten.Image) {
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		ebitenutil.DebugPrint(screen, "Clicked!")
	}
}

引数を ebiten.MouseButtonLeft から変えることで右ボタンや中ボタン(マウスホイール)のクリックを検知することもできます。

ちょうど押された判定

過去の記事では、押しっぱなしではなくその瞬間に押されたことを判定する方法を自分で実装しました。このパターンは頻出なので、Ebitengineでは inpututil というサブパッケージにて IsMouseButtonJustPressed という「ちょうど押されたか」を返す関数が用意されています。

例によってインポートパスの v2 が抜けがちなので、必ず github.com/hajimehoshi/ebiten/v2/inpututil をインポートしていることを確認しましょう。

このプログラムは、マウスの左ボタンが押された瞬間に "Clicked!" と表示します。長押ししている間は何も表示されません。

import (
	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/inpututil" // v2を忘れずに
)

// ...中略...

func (g *game) Draw(screen *ebiten.Image) {
	if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
		ebitenutil.DebugPrint(screen, "Clicked!")
	}
}

タッチ

miniten.IsClicked はマウスのクリックだけでなく、タッチパネルのタッチも検知できましたが、Ebitengineにはそのような「クリックもタッチも検出する関数」は存在しません。自分でマウス入力とタッチ入力を組み合わせましょう。

このプログラムは miniten.IsClicked の実装の中身です。

func IsClicked() bool {
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		return true
	}
	return len(ebiten.AppendTouchIDs(nil)) != 0
}

タッチは同時に複数箇所発生しうるので、ebiten.AppendTouchIDs はタッチパネルに触れている指を識別する番号のスライスを返します(例によってAppend系関数なので、引数のスライスに追記してくれるが、nilを渡せば新しいスライスを作ってくれる)。その返り値の要素数がゼロでなければ、タッチパネルに触れている指があることを意味するので、trueを返します。

タッチの座標

ebiten.AppendTouchIDs が返すIDを ebiten.TouchPosition に渡すことで、そのタッチの座標を取得できます。

マウスの座標

マウスの座標を取得するには ebiten.CursorPosition を使います。これを使ってマウスの座標を表示するプログラムがこちらです。fmt.Sprintln は、引数を画面に表示する代わりに、文字列として返す関数です。

func (g *game) Draw(screen *ebiten.Image) {
	s := fmt.Sprintln(ebiten.CursorPosition())
	ebitenutil.DebugPrint(screen, s)
}

キーボード

キー入力を検知するには ebiten.IsKeyPressed を使います。引数にはキー定数を渡します。例えば、ebiten.KeyA はキーボードのAキーを表します。どんなキーがあるかはドキュメントを参照してください。

func (g *game) Draw(screen *ebiten.Image) {
	if ebiten.IsKeyPressed(ebiten.KeyA) {
		ebitenutil.DebugPrint(screen, "A is pressed")
	}
}

キーボードもマウスと同様に、押された瞬間を検知する関数が用意されています。inpututil.IsKeyJustPressed です。

func (g *game) Draw(screen *ebiten.Image) {
	if inpututil.IsKeyJustPressed(ebiten.KeyA) {
		ebitenutil.DebugPrint(screen, "A is pressed")
	}
}

ゲームパッド

ゲームパッドはデバイスによって配置がまちまちだったり、抜き差しに対応する必要があったり、正しく対応するのはとにかく大変なので、詳しい解説は一旦ドキュメントおよびサンプルに譲ります。

テキスト入力

ebiten.AppendInputChars を使えば文字列の入力を簡易的に受け取ることは可能です。ただし、IME(日本語入力)には対応していません。IMEはサブパッケージのexp/textinputで対応が進んでいますが、完了はまだ先です。

その他の入力関数

その他の入力関数をざっくりと紹介します。

  • Wheel - マウスホイールの回転量を取得
  • Vibrate - デバイスを振動させる
  • DroppedFiles - ドラッグ&ドロップされたファイルをファイルシステムとして取得
  • KeyName - AZERTYキーボードなどのキー名と位置の対応を取得

まとめ

Ebitengineには様々な入力関数が用意されています。また、inpututil(例によって v2 を忘れずに)パッケージには、よくある入力の検知を簡単にする関数が用意されています。よく使う関数をもう一度おさらいしておきましょう。

  • マウス
    • ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft)
    • inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft)
  • タッチ
    • ebiten.AppendTouchIDs(nil)
    • ebiten.TouchPosition(id)
    • inpututil.AppendJustPressedTouchIDs(nil)
  • キーボード
    • ebiten.IsKeyPressed(ebiten.KeyA)
    • inpututil.IsKeyJustPressed(ebiten.KeyA)

というわけで、長い長い道のりでしたが、minitenの代わりにEbitengineを使える(のに加えて様々な演出もできる)まで到達しました!おめでとうございます!次からゲーム作りの本題に入っていきます。