2024-06-03 17:44:17 +02:00
|
|
|
// 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 {
|
2024-06-03 17:44:17 +02:00
|
|
|
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])
|
|
|
|
|
|
2024-06-03 17:44:17 +02:00
|
|
|
viewportCenter := c.viewportCenter()
|
|
|
|
|
|
2024-05-22 19:01:58 +02:00
|
|
|
// We want to scale and rotate around center of image / screen
|
2024-06-03 17:44:17 +02:00
|
|
|
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)),
|
|
|
|
|
)
|
|
|
|
|
|
2024-06-03 17:44:17 +02:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-03 17:44:17 +02:00
|
|
|
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() {
|
2024-06-03 17:44:17 +02:00
|
|
|
c.Position[0] = c.InitialPosition[0]
|
|
|
|
|
c.Position[1] = c.InitialPosition[1]
|
|
|
|
|
c.ZoomFactor = c.ZoomOutFactor
|
2024-05-22 19:01:58 +02:00
|
|
|
}
|