diff --git a/engine/camera.go b/engine/camera.go index 11ccd76..8c911ec 100644 --- a/engine/camera.go +++ b/engine/camera.go @@ -16,10 +16,12 @@ type Camera struct { //Rotation float64 // radians Zoom float64 // unitless + Filter ebiten.Filter // Apply to game? + game *Game } -func (c *Camera) Draw(screen *ebiten.Image, geom ebiten.GeoM) { +func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { // If the camera bounds are smaller than the screen dimensions, that // places a lower bound on zoom. // If the configured centre still puts the camera out of bounds, move it. @@ -51,14 +53,16 @@ func (c *Camera) Draw(screen *ebiten.Image, geom ebiten.GeoM) { // Apply camera controls to geom. // 1. Move c.Centre to the origin - geom.Translate(-float64(centre.X), -float64(centre.Y)) + opts.GeoM.Translate(-float64(centre.X), -float64(centre.Y)) // 2. Zoom and rotate - geom.Scale(zoom, zoom) + opts.GeoM.Scale(zoom, zoom) //geom.Rotate(c.Rotation) // 3. Move the origin to the centre of screen space. - geom.Translate(sw2, sh2) + opts.GeoM.Translate(sw2, sh2) - c.Scene.Draw(screen, geom) + opts.Filter = c.Filter + + c.Scene.Draw(screen, opts) } func (c *Camera) Update() error { return c.Scene.Update() } diff --git a/engine/debug.go b/engine/debug.go index 9fd8a12..bdf857e 100644 --- a/engine/debug.go +++ b/engine/debug.go @@ -23,7 +23,7 @@ type PerfDisplay struct { Hidden bool } -func (p PerfDisplay) Draw(screen *ebiten.Image, _ ebiten.GeoM) { +func (p PerfDisplay) Draw(screen *ebiten.Image, _ ebiten.DrawImageOptions) { if p.Hidden { return } diff --git a/engine/fill.go b/engine/fill.go index 130f680..9dfc8e4 100644 --- a/engine/fill.go +++ b/engine/fill.go @@ -14,9 +14,9 @@ type Fill struct { ZPos } -func (f *Fill) Draw(screen *ebiten.Image, _ ebiten.GeoM) { +func (f *Fill) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { if f.Hidden { return } - screen.Fill(f.Color) + screen.Fill(opts.ColorM.Apply(f.Color)) } diff --git a/engine/game.go b/engine/game.go index 8ddbb49..57179fc 100644 --- a/engine/game.go +++ b/engine/game.go @@ -21,7 +21,7 @@ type Game struct { // Draw draws the entire thing, with no geometric transform. func (g *Game) Draw(screen *ebiten.Image) { - g.Scene.Draw(screen, ebiten.GeoM{}) + g.Scene.Draw(screen, ebiten.DrawImageOptions{}) } // Layout returns the configured screen width/height. diff --git a/engine/interface.go b/engine/interface.go index 74bbb12..470a1eb 100644 --- a/engine/interface.go +++ b/engine/interface.go @@ -15,7 +15,7 @@ type Collider interface { // Each component is responsible for calling Draw on its child components // (so that hiding the parent can hide the children, etc). type Drawer interface { - Draw(screen *ebiten.Image, geom ebiten.GeoM) + Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) } // Identifier components have a sense of self. This makes it easier for diff --git a/engine/scene.go b/engine/scene.go index dcadbcb..09546e9 100644 --- a/engine/scene.go +++ b/engine/scene.go @@ -22,13 +22,13 @@ type Scene struct { } // Draw draws all components in order. -func (s *Scene) Draw(screen *ebiten.Image, geom ebiten.GeoM) { +func (s *Scene) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { if s.Hidden { return } for _, i := range s.Components { if d, ok := i.(Drawer); ok { - d.Draw(screen, geom) + d.Draw(screen, opts) } } } diff --git a/engine/sprite.go b/engine/sprite.go index 8f6d496..d77d82c 100644 --- a/engine/sprite.go +++ b/engine/sprite.go @@ -24,21 +24,22 @@ type Sprite struct { anim *Anim } -func (s *Sprite) Draw(screen *ebiten.Image, geom ebiten.GeoM) { +func (s *Sprite) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { if s.Hidden { return } - var op ebiten.DrawImageOptions dp := s.Pos.Add(s.FrameOffset) - op.GeoM.Translate(float64(dp.X), float64(dp.Y)) - op.GeoM.Concat(geom) + var geom ebiten.GeoM + geom.Translate(float64(dp.X), float64(dp.Y)) + geom.Concat(opts.GeoM) + opts.GeoM = geom frame := s.anim.CurrentFrame() src := s.Src.Image() w, _ := src.Size() sp := image.Pt((frame*s.FrameSize.X)%w, ((frame*s.FrameSize.X)/w)*s.FrameSize.Y) - screen.DrawImage(src.SubImage(image.Rectangle{sp, sp.Add(s.FrameSize)}).(*ebiten.Image), &op) + screen.DrawImage(src.SubImage(image.Rectangle{sp, sp.Add(s.FrameSize)}).(*ebiten.Image), &opts) } func (s *Sprite) Scan() []interface{} { return []interface{}{&s.Actor} } diff --git a/engine/tiles.go b/engine/tiles.go index a4af391..e69c1f4 100644 --- a/engine/tiles.go +++ b/engine/tiles.go @@ -52,25 +52,28 @@ func (t *Tilemap) CollidesWith(r image.Rectangle) bool { } // Draw draws the tilemap. -func (t *Tilemap) Draw(screen *ebiten.Image, geom ebiten.GeoM) { +func (t *Tilemap) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { if t.Hidden { return } src := t.Src.Image() w, _ := src.Size() + og := opts.GeoM + var geom ebiten.GeoM for j, row := range t.Map { for i, tile := range row { if tile == nil { continue } - var op ebiten.DrawImageOptions - op.GeoM.Translate(float64(i*t.TileSize), float64(j*t.TileSize)) - op.GeoM.Concat(geom) + geom.Reset() + geom.Translate(float64(i*t.TileSize), float64(j*t.TileSize)) + geom.Concat(og) + opts.GeoM = geom s := tile.TileIndex() * t.TileSize sx, sy := s%w, (s/w)*t.TileSize src := src.SubImage(image.Rect(sx, sy, sx+t.TileSize, sy+t.TileSize)).(*ebiten.Image) - screen.DrawImage(src, &op) + screen.DrawImage(src, &opts) } } }