Chapter 01無料公開

ebitenとの出会いと、Hello Ebiten!

raa0121
raa0121
2020.12.18に更新

はじめに

この本では、私が engo で約12時間で作った東方風シューティングゲームの素体を、
ebiten に3時間で移植した際に感じたこと、行った工夫などを書いていきます。

また、東方風シューティングゲームを作るにあたって、シューティングゲーム作成入門 ~bituse~
を参考にさせていただきました。ありがとうございます。

また、この本を読むのに、engo についての知識は不要です。engo 特有の話が出てきた場合は、逐次かんたんに説明を入れる予定です。

engo から ebiten へ

ebiten に移植しようと考えた頃には、敵の弾と操作キャラとの当たり判定 まで、実装されていました。

当時の私のコードには、3つの問題点がありました。

  1. いきあたりばったりの設計で、コードがぐちゃぐちゃ
  2. engo 特有のお作法に振り回されてて、コードがぐちゃぐちゃ
  3. シーン遷移を作ってなかったので、タイトル画面や会話画面を入れるのが面倒

そんな中、vim-jpSlack に #tech-gamedev というチャンネルができ、
ebiten の作者さんである、Hajime Hoshi さんに ebiten を布教され、移植することを決意しました。

Hello Ebiten!

まずは、ebiten にこんにちわしてみましょう。
内容は、https://ebiten.org/tour/hello_world.html とほぼ一緒です。

package main

import (
  "github.com/hajimehoshi/ebiten"
  "github.com/hajimehoshi/ebiten/ebitenutil"
  "log"
)

const (
    screenWidth  = 640
    screenHeight = 480
)

type Game struct {}

func (g *Game) Update(screen *ebiten.Image) error {
    return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
    ebitenutil.DebugPrint(screen, "Hello Ebiten!")
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return screenWidth, screenHeight
}

func main() {
    ebiten.SetWindowSize(screenWidth, screenHeight)
    ebiten.SetWindowTitle("Hello Ebiten!")

    if err := ebiten.RunGame(&Game{}); err != nil {
        log.Fatal(err)
    }
}

動かすと、以下のような画面が表示されます。
Hello Ebiten!

さて、上のコードを軽く解説します。
まずは、main() から

    if err := ebiten.RunGame(&Game{}); err != nil {
        log.Fatal(err)
    }

ebiten.RunGame() では、Update(*ebiten.Image) errorDraw(*ebiten.Image)Layout(int, int) (int, int) を実装した struct のポインタを渡すことで、実行することができます。

func (g *Game) Update(screen *ebiten.Image) error {
    return nil
}

Update(*ebiten.Image) error は毎フレーム更新される内容を記述します。
今回は、何もしないので、nil を返します。

func (g *Game) Draw(screen *ebiten.Image) {
    ebitenutil.DebugPrint(screen, "Hello Ebiten!")
}

Draw(*ebiten.Image) では、画面に描画するものを記述します。
今回は、ebitenutil パッケージにある、 DebugPrint を使って、Hello Ebiten! を描画しています。

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return screenWidth, screenHeight
}

Layout(int, int) (int, int) では、ゲームの内部的なレイアウトを設定できます。
今回はスクリーンのサイズと一緒にしていますが、小さい値を設定することで、ズームして表示することができます。

次章について

次章では、シーンの実装とプレイヤーの実装を解説します。(近日公開予定です)