LoginSignup
1

More than 5 years have passed since last update.

ebiten で動的に sprite を生成する

Posted at

前回の続きです。
これまでは画面上に表示されるリソースがソースコードにハードコードされた状態だったので、入力に合わせて動的に Sprite を生成することを考えてみます。

題材はキャラクターからの飛び道具、マリオで言うファイアーボールです。

Spriteの生成

Spriteの生成自体は、ボタン入力などに合わせて NewSprite な関数を呼び出し、動的に struct を生成すればよさそうです。
ただし、Spriteを生成した後はなんらかの方法で破棄することを考えなければメモリ上の用の済んだSpriteが保持され続け、あまりよろしくありません。
GoはGCが載っている言語なので、用の済んだSpriteは参照を外してGCに改修されるようにすれば良さそうです(多分。ちょっと理解が曖昧)。

ソースコード

package sprite

import (
    "image"

    "github.com/hajimehoshi/ebiten"
    "github.com/zenwerk/go-pixelman3/utils"
)

const (
    ball_img = `--+++--
-+++++-
-+++++-
--+++--`
    ballSpeed    = 4
    screenWidth  = 320
    screenHeight = 240
)

type Balls []*Ball

var (
    ballImg *ebiten.Image
)

func init() {
    tmpImage := image.NewRGBA(image.Rect(0, 0, 7, 4))
    utils.CreateImageFromString(ball_img, tmpImage)
    ballImg, _ = ebiten.NewImage(7, 4, ebiten.FilterNearest)
    ballImg.ReplacePixels(tmpImage.Pix)
}

type Ball struct {
    BaseSprite
}

func NewBall(pos position) *Ball {
    ball := new(Ball)
    ball.Images = []*ebiten.Image{
        ballImg,
    }
    ball.ImageNum = len(ball.Images)
    ball.Position = pos
    return ball
}

func (bs *Balls) Move(viewport position) {
    balls := *bs

    for i := 0; i < len(balls); i++ {
        b := balls[i]
        b.Position.X += ballSpeed

        // 表示領域外に出たら配列から削除する
        if b.Position.X > (screenWidth-viewport.X) || b.Position.Y > (screenHeight-viewport.Y) || b.Position.X < 0 || b.Position.Y < 0 {
            balls = append(balls[:i], balls[i+1:]...)
            i--
        }
    }
    *bs = balls
}

Move関数で表示領域外に出たら、スライスから削除するようにしています。これで無駄なメモリを使用せずに済むと思います。
表示領域外の他にも、他のSpriteとの衝突などで同様の処理をしても良いでしょう。

実行結果

ball.gif

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1