aboutsummaryrefslogtreecommitdiff
path: root/camera.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-06-06 20:59:12 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-06-06 20:59:12 +0200
commitd9a54f1319cc9dcc2861cecc9edfde14cf039c5b (patch)
tree74df791d6eda0ffe6c09cb32e5ffd76c4849cbac /camera.go
parent18592fd9f520a33ab307e496b995c1a7bf284893 (diff)
Add examples catalog with subcommand dispatch
- Extract game engine from package main to engine/ library package - Create examples/ package with registry, Entry type, and BuilderDeps - Register default world as an example (moved from main()) - Add combat example: two teams of units facing each other - Rewrite main.go as thin dispatch: go run . example [name] - Update README with examples catalog one-liner
Diffstat (limited to 'camera.go')
-rw-r--r--camera.go174
1 files changed, 0 insertions, 174 deletions
diff --git a/camera.go b/camera.go
deleted file mode 100644
index 9118117..0000000
--- a/camera.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package main
-
-import (
- "math"
-
- "age_of_empires/physics"
-
- "github.com/hajimehoshi/ebiten/v2"
- "github.com/hajimehoshi/ebiten/v2/inpututil"
-)
-
-const (
- ScreenWidth = 960
- ScreenHeight = 640
- WorldWidth = 3200
- WorldHeight = 2400
-
- cameraZoomMin = 0.25
- cameraZoomMax = 3.0
- cameraZoomStep = 0.10
- cameraScrollSpeed = 400.0
- cameraDrag = 8.0
-)
-
-type Camera struct {
- X, Y float64
- Zoom float64
-
- vx, vy float64
-
- dragActive bool
- dragStartScreenX, dragStartScreenY int
- dragStartCamX, dragStartCamY float64
-}
-
-func (c *Camera) WorldToScreen(p physics.Point) (float64, float64) {
- sx := (float64(p.X)-c.X)*c.Zoom + ScreenWidth/2
- sy := (float64(p.Y)-c.Y)*c.Zoom + ScreenHeight/2
- return sx, sy
-}
-
-func (c *Camera) ScreenToWorld(sx, sy int) physics.Point {
- zoom := c.Zoom
- if zoom == 0 {
- zoom = 1
- }
- wx := float64(sx-ScreenWidth/2)/zoom + c.X
- wy := float64(sy-ScreenHeight/2)/zoom + c.Y
- return physics.Point{X: int(math.Round(wx)), Y: int(math.Round(wy))}
-}
-
-func (c *Camera) GeoM() ebiten.GeoM {
- var m ebiten.GeoM
- m.Translate(-c.X, -c.Y)
- m.Scale(c.Zoom, c.Zoom)
- m.Translate(ScreenWidth/2, ScreenHeight/2)
- return m
-}
-
-func (c *Camera) clampToBounds() {
- halfW := (ScreenWidth / 2.0) / c.Zoom
- halfH := (ScreenHeight / 2.0) / c.Zoom
-
- minX, maxX := halfW, float64(WorldWidth)-halfW
- if minX > maxX {
- minX = WorldWidth / 2
- maxX = WorldWidth / 2
- }
- minY, maxY := halfH, float64(WorldHeight)-halfH
- if minY > maxY {
- minY = WorldHeight / 2
- maxY = WorldHeight / 2
- }
-
- if c.X < minX {
- c.X = minX
- if c.vx < 0 {
- c.vx = 0
- }
- }
- if c.X > maxX {
- c.X = maxX
- if c.vx > 0 {
- c.vx = 0
- }
- }
- if c.Y < minY {
- c.Y = minY
- if c.vy < 0 {
- c.vy = 0
- }
- }
- if c.Y > maxY {
- c.Y = maxY
- if c.vy > 0 {
- c.vy = 0
- }
- }
-}
-
-func (c *Camera) Update(dt float64) {
- zoom := c.Zoom
- if zoom == 0 {
- zoom = 1
- }
-
- // Scroll wheel zoom toward cursor
- _, wy := ebiten.Wheel()
- if wy != 0 {
- mx, my := ebiten.CursorPosition()
- // cursor world pos before zoom
- wx0 := float64(mx-ScreenWidth/2)/zoom + c.X
- wy0 := float64(my-ScreenHeight/2)/zoom + c.Y
-
- newZoom := math.Max(cameraZoomMin, math.Min(cameraZoomMax, zoom+wy*cameraZoomStep))
- c.Zoom = newZoom
- zoom = newZoom
-
- // translate so cursor stays fixed
- wx1 := float64(mx-ScreenWidth/2)/zoom + c.X
- wy1 := float64(my-ScreenHeight/2)/zoom + c.Y
- c.X -= wx1 - wx0
- c.Y -= wy1 - wy0
- }
-
- // Middle-mouse drag
- mx, my := ebiten.CursorPosition()
- if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonMiddle) {
- c.dragActive = true
- c.dragStartScreenX = mx
- c.dragStartScreenY = my
- c.dragStartCamX = c.X
- c.dragStartCamY = c.Y
- }
- if c.dragActive {
- if ebiten.IsMouseButtonPressed(ebiten.MouseButtonMiddle) {
- c.X = c.dragStartCamX - float64(mx-c.dragStartScreenX)/zoom
- c.Y = c.dragStartCamY - float64(my-c.dragStartScreenY)/zoom
- } else {
- c.dragActive = false
- }
- }
-
- // Arrow key pan (velocity-based)
- dx, dy := 0.0, 0.0
- if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) {
- dx -= 1
- }
- if ebiten.IsKeyPressed(ebiten.KeyArrowRight) {
- dx += 1
- }
- if ebiten.IsKeyPressed(ebiten.KeyArrowUp) {
- dy -= 1
- }
- if ebiten.IsKeyPressed(ebiten.KeyArrowDown) {
- dy += 1
- }
- if dx != 0 && dy != 0 {
- inv := 1.0 / math.Sqrt2
- dx *= inv
- dy *= inv
- }
- c.vx += dx * cameraScrollSpeed
- c.vy += dy * cameraScrollSpeed
-
- // Apply velocity and exponential drag
- c.X += c.vx * dt
- c.Y += c.vy * dt
- decay := math.Exp(-cameraDrag * dt)
- c.vx *= decay
- c.vy *= decay
-
- c.clampToBounds()
-}