zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs

commit f97d14019dbf309cf7ff7f26ccec4d50fdf30a34
parent f21a57f5ebf9bd6ac58d74bc61c91e3f8aad0ff7
Author: bsandro <brian.drosan@gmail.com>
Date:   Sun,  3 Oct 2021 21:48:21 +0300

precache tiles position and transformation matrix

Diffstat:
Agamemap.go | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain.go | 118+++----------------------------------------------------------------------------
2 files changed, 152 insertions(+), 114 deletions(-)

diff --git a/gamemap.go b/gamemap.go @@ -0,0 +1,148 @@ +package main + +import ( + "encoding/json" + "errors" + "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/ebitenutil" + "image" + _ "image/png" + "os" +) + +const ( + flipHoriz uint32 = 0b10000000000000000000000000000000 + flipVert uint32 = 0b01000000000000000000000000000000 + flipDiag uint32 = 0b00100000000000000000000000000000 +) + +type Tileset struct { + FirstGid uint32 `json:firstgid` + Image string `json:image` + Name string `json:name` + TileWidth uint32 `json:tilewidth` + TileHeight uint32 `json:tileheight` + Columns uint32 `json:columns` + + Atlas *ebiten.Image +} + +type Tile struct { + FlipHor, FlipVer, FlipDiag bool + Options *ebiten.DrawImageOptions + Image *ebiten.Image + Gid uint32 +} + +type Layer struct { + Type string `json:type` + Id int `json:id` + Data []uint32 `json:data` + Height int `json:height` + Width int `json:width` + X int `json:x` + Y int `json:y` + + Tiles []Tile +} + +type Gamemap struct { + Height uint32 `json:height` + Width uint32 `json:width` + Layers []*Layer `json:layers` + Tilesets []*Tileset `json:tilesets` +} + +func (l *Layer) Init(gamemap *Gamemap) error { + for i, t := range l.Data { + if t > 0 { + var tile Tile + tile.FlipHor = ((t & flipHoriz) >> 31) == 1 + tile.FlipVer = ((t & flipVert) >> 30) == 1 + tile.FlipDiag = ((t & flipDiag) >> 29) == 1 + t &= ^(flipHoriz | flipVert | flipDiag) // cleanup flags + tileset := gamemap.findTileset(t) + if tileset == nil { + return errors.New("Invalid tile gid: " + string(t)) + } + t_width := tileset.TileWidth + t_height := tileset.TileHeight + tile.Gid = t - tileset.FirstGid + tile.Options = &ebiten.DrawImageOptions{} + tile.Options.GeoM.Translate(-float64(t_width)/2, -float64(t_height)/2) + if tile.FlipDiag { + ret := ebiten.GeoM{} + ret.SetElement(0, 0, tile.Options.GeoM.Element(1, 0)) + ret.SetElement(0, 1, tile.Options.GeoM.Element(1, 1)) + ret.SetElement(0, 2, tile.Options.GeoM.Element(1, 2)) + ret.SetElement(1, 0, tile.Options.GeoM.Element(0, 0)) + ret.SetElement(1, 1, tile.Options.GeoM.Element(0, 1)) + ret.SetElement(1, 2, tile.Options.GeoM.Element(0, 2)) + tile.Options.GeoM = ret + } + if tile.FlipHor { + tile.Options.GeoM.Scale(-1, 1) + } + if tile.FlipVer { + tile.Options.GeoM.Scale(1, -1) + } + tile.Options.GeoM.Translate(float64((uint32(i)%gamemap.Width)*t_width), float64((uint32(i)/gamemap.Width)*t_height)) + sx := int((tile.Gid % tileset.Columns) * t_width) + sy := int((tile.Gid / tileset.Columns) * t_height) + tile.Image = tileset.Atlas.SubImage(image.Rect(sx, sy, sx+int(t_width), sy+int(t_height))).(*ebiten.Image) + l.Tiles = append(l.Tiles, tile) + } + } + + return nil +} + +func (t *Tileset) Init() error { + var err error + + t.Atlas, _, err = ebitenutil.NewImageFromFile(t.Image) + if err != nil { + return err + } + + return nil +} + +func (m *Gamemap) Init(filename string) error { + data, err := os.ReadFile(filename) + if err != nil { + return err + } + err = json.Unmarshal(data, m) + if err != nil { + return err + } + + for _, tileset := range m.Tilesets { + if err := tileset.Init(); err != nil { + return err + } + } + + for _, layer := range m.Layers { + if layer.Type == "tilelayer" { + if err := layer.Init(m); err != nil { + return err + } + } + } + + return nil +} + +func (m *Gamemap) findTileset(gid uint32) *Tileset { + var ret *Tileset = nil + for _, tileset := range m.Tilesets { + if gid >= tileset.FirstGid { + if (ret != nil && ret.FirstGid < tileset.FirstGid) || ret == nil { + ret = tileset + } + } + } + return ret +} diff --git a/main.go b/main.go @@ -1,81 +1,24 @@ package main import ( - "encoding/json" "errors" "fmt" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" - "image" _ "image/png" "log" - "os" ) const ( - flipHoriz uint32 = 0b10000000000000000000000000000000 - flipVert uint32 = 0b01000000000000000000000000000000 - flipDiag uint32 = 0b00100000000000000000000000000000 - screenW = 1024 - screenH = 768 + screenW = 1024 + screenH = 768 ) -type Tileset struct { - FirstGid uint32 `json:firstgid` - Image string `json:image` - Name string `json:name` - TileWidth int `json:tilewidth` - TileHeight int `json:tileheight` - Columns int `json:columns` - - Atlas *ebiten.Image -} - -type Gamemap struct { - Height int `json:height` - Width int `json:width` - Layers []struct { - Type string `json:type` - Id int `json:id` - Data []uint32 `json:data` - Height int `json:height` - Width int `json:width` - X int `json:x` - Y int `json:y` - } `json:layers` - Tilesets []*Tileset `json:tilesets` -} - type Game struct { Inited bool Map *Gamemap } -func (t *Tileset) Init() error { - var err error - t.Atlas, _, err = ebitenutil.NewImageFromFile(t.Image) - return err -} - -func (m *Gamemap) Init(filename string) error { - data, err := os.ReadFile(filename) - if err != nil { - return err - } - err = json.Unmarshal(data, m) - if err != nil { - return err - } - - for _, tileset := range m.Tilesets { - if err := tileset.Init(); err != nil { - return err - } - } - - return nil -} - func (g *Game) Init() error { if g.Inited { return errors.New("Game is already initialized") @@ -91,67 +34,14 @@ func (g *Game) Init() error { return nil } -func init() { - -} - -func (m *Gamemap) findTileset(gid uint32) *Tileset { - var ret *Tileset = nil - for _, tileset := range m.Tilesets { - if gid >= tileset.FirstGid { - if (ret != nil && ret.FirstGid < tileset.FirstGid) || ret == nil { - ret = tileset - } - } - } - return ret -} - func (g *Game) Update() error { return nil } func (g *Game) Draw(screen *ebiten.Image) { for _, layer := range g.Map.Layers { - if layer.Type == "tilelayer" { - for i, t := range layer.Data { - if t > 0 { - is_flipped_hor := (t & flipHoriz) >> 31 - is_flipped_ver := (t & flipVert) >> 30 - is_flipped_diag := (t & flipDiag) >> 29 - t &= ^(flipHoriz | flipVert | flipDiag) // cleanup flags - tileset := g.Map.findTileset(t) - if tileset == nil { - log.Fatal("Invalid tile gid:", t) - } - t_width := tileset.TileWidth - t_height := tileset.TileHeight - t1 := int(t - tileset.FirstGid) - op := &ebiten.DrawImageOptions{} - op.GeoM.Translate(-float64(t_width)/2, -float64(t_height)/2) - if is_flipped_diag == 1 { - ret := ebiten.GeoM{} - ret.SetElement(0, 0, op.GeoM.Element(1, 0)) - ret.SetElement(0, 1, op.GeoM.Element(1, 1)) - ret.SetElement(0, 2, op.GeoM.Element(1, 2)) - ret.SetElement(1, 0, op.GeoM.Element(0, 0)) - ret.SetElement(1, 1, op.GeoM.Element(0, 1)) - ret.SetElement(1, 2, op.GeoM.Element(0, 2)) - op.GeoM = ret - } - if is_flipped_hor == 1 { - op.GeoM.Scale(-1, 1) - } - if is_flipped_ver == 1 { - op.GeoM.Scale(1, -1) - } - op.GeoM.Translate(float64((i%g.Map.Width)*t_width), float64((i/g.Map.Width)*t_height)) - sx := (t1 % tileset.Columns) * t_width - sy := (t1 / tileset.Columns) * t_height - var tile *ebiten.Image = tileset.Atlas.SubImage(image.Rect(sx, sy, sx+t_width, sy+t_height)).(*ebiten.Image) - screen.DrawImage(tile, op) - } - } + for _, t := range layer.Tiles { + screen.DrawImage(t.Image, t.Options) } } ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.CurrentTPS()))