Camera
The camera offsets all drawing operations, creating the illusion of a scrolling world.
Camera Function
p8.Camera(x, y) // Set camera offset
p8.Camera() // Reset to (0, 0)
When the camera is at (x, y), everything draws shifted by (-x, -y).
Following a Player
func (g *game) Draw() {
p8.Cls(0)
// Center camera on player
camX := g.playerX - 64 // Center of 128-pixel screen
camY := g.playerY - 64
p8.Camera(camX, camY)
// Draw world
p8.Map()
p8.Spr(1, g.playerX, g.playerY) // Use world coordinates
// Draw UI (reset camera first)
p8.Camera()
p8.Print("SCORE: " + fmt.Sprint(g.score), 2, 2, 7)
}
Camera Bounds
Keep the camera within map boundaries:
func (g *game) updateCamera() {
// Target camera position
camX := g.playerX - 64
camY := g.playerY - 64
// Clamp to map boundaries
mapWidth := 128 * 8 // 128 tiles × 8 pixels
mapHeight := 128 * 8
if camX < 0 { camX = 0 }
if camY < 0 { camY = 0 }
if camX > mapWidth - 128 { camX = mapWidth - 128 }
if camY > mapHeight - 128 { camY = mapHeight - 128 }
g.camX = camX
g.camY = camY
}
Smooth Camera
Add smoothing for a less jarring follow:
func (g *game) updateCamera() {
targetX := g.playerX - 64
targetY := g.playerY - 64
// Smooth interpolation (10% per frame)
g.camX += (targetX - g.camX) * 0.1
g.camY += (targetY - g.camY) * 0.1
}
Screen Shake
Add impact effects:
func (g *game) Draw() {
p8.Cls(0)
// Apply shake offset
shakeX := 0.0
shakeY := 0.0
if g.shakeFrames > 0 {
shakeX = float64(p8.Rnd(5)) - 2
shakeY = float64(p8.Rnd(5)) - 2
g.shakeFrames--
}
p8.Camera(g.camX + shakeX, g.camY + shakeY)
// ... draw world
}