Files
golsky/cmd/camera.go

82 lines
1.7 KiB
Go
Raw Normal View History

// this comes from the camera example but I enhanced it a little bit
2025-11-13 21:30:44 +01:00
package cmd
2024-05-22 19:01:58 +02:00
import (
"fmt"
"math"
"github.com/hajimehoshi/ebiten/v2"
"golang.org/x/image/math/f64"
)
type Camera struct {
ViewPort f64.Vec2
Position f64.Vec2
ZoomFactor int
InitialZoomFactor int
InitialPosition f64.Vec2
ZoomOutFactor int
2024-05-22 19:01:58 +02:00
}
func (c *Camera) String() string {
return fmt.Sprintf(
"T: %.1f, S: %d",
c.Position, c.ZoomFactor,
)
}
func (c *Camera) viewportCenter() f64.Vec2 {
return f64.Vec2{
c.ViewPort[0] * 0.5,
c.ViewPort[1] * 0.5,
}
}
func (c *Camera) worldMatrix() ebiten.GeoM {
m := ebiten.GeoM{}
m.Translate(-c.Position[0], -c.Position[1])
viewportCenter := c.viewportCenter()
2024-05-22 19:01:58 +02:00
// We want to scale and rotate around center of image / screen
m.Translate(-viewportCenter[0], -viewportCenter[1])
2024-05-22 19:01:58 +02:00
m.Scale(
math.Pow(1.01, float64(c.ZoomFactor)),
math.Pow(1.01, float64(c.ZoomFactor)),
)
m.Translate(viewportCenter[0], viewportCenter[1])
2024-05-22 19:01:58 +02:00
return m
}
func (c *Camera) Render(world, screen *ebiten.Image) {
screen.DrawImage(world, &ebiten.DrawImageOptions{
GeoM: c.worldMatrix(),
})
}
func (c *Camera) ScreenToWorld(posX, posY int) (float64, float64) {
inverseMatrix := c.worldMatrix()
if inverseMatrix.IsInvertible() {
inverseMatrix.Invert()
return inverseMatrix.Apply(float64(posX), float64(posY))
} else {
// When scaling it can happened that matrix is not invertable
return math.NaN(), math.NaN()
}
}
func (c *Camera) Setup() {
c.Position[0] = c.InitialPosition[0]
c.Position[1] = c.InitialPosition[1]
c.ZoomFactor = c.InitialZoomFactor
}
2024-05-22 19:01:58 +02:00
func (c *Camera) Reset() {
c.Position[0] = c.InitialPosition[0]
c.Position[1] = c.InitialPosition[1]
c.ZoomFactor = c.ZoomOutFactor
2024-05-22 19:01:58 +02:00
}