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:
A | gamemap.go | | | 148 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | main.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()))