Camera struct

Camera represents a simple 2D camera state.

Fields:

  • Position (math.Vec2)
  • Zoom (float32)
  • Rotation (float32)

Manager struct

Manager handles input bindings and state.

Fields:

  • keyBindings (map[string]string)
  • mouseBindings (map[int]string)
  • active (map[string]bool)
  • dragStart (math.Vec2)
  • dragEnd (math.Vec2)
  • dragging (bool)
  • lastPos (math.Vec2)
  • camera (Camera)

Methods:

BindKey

BindKey associates a keyboard key with an action.


Parameters:
  • action string
  • key string

Show/Hide Method Body
{ m.keyBindings[key] = action }

RebindKey

RebindKey changes the key mapped to an action.


Parameters:
  • action string
  • key string

Show/Hide Method Body
{
	for k, a := range m.keyBindings {
		if a == action {
			delete(m.keyBindings, k)
			break
		}
	}
	m.keyBindings[key] = action
}

BindMouse

BindMouse associates a mouse button with an action.


Parameters:
  • action string
  • button int

Show/Hide Method Body
{ m.mouseBindings[button] = action }

RebindMouse

RebindMouse changes the button mapped to an action.


Parameters:
  • action string
  • button int

Show/Hide Method Body
{
	for b, a := range m.mouseBindings {
		if a == action {
			delete(m.mouseBindings, b)
			break
		}
	}
	m.mouseBindings[button] = action
}

IsActive

IsActive reports whether an action is currently engaged.


Parameters:
  • action string

Returns:
  • bool

Show/Hide Method Body
{ return m.active[action] }

DragRect

DragRect returns the start and end of the current drag along with its state.


Returns:
  • start math.Vec2
  • end math.Vec2
  • dragging bool

Show/Hide Method Body
{
	return m.dragStart, m.dragEnd, m.dragging
}

Camera

Camera returns a copy of the current camera state.


Returns:
  • Camera

References:


Show/Hide Method Body
{ return m.camera }

Pan

Pan translates the camera by dx, dy.


Parameters:
  • dx float32
  • dy float32

Show/Hide Method Body
{
	m.camera.Position = m.camera.Position.Add(math.Vec2{dx, dy})
}

Zoom

Zoom adjusts the camera zoom level.


Parameters:
  • delta float32

Show/Hide Method Body
{ m.camera.Zoom += delta }

Rotate

Rotate adjusts the camera rotation.


Parameters:
  • delta float32

Show/Hide Method Body
{ m.camera.Rotation += delta }

handleKeyDown


Parameters:
  • key string

Show/Hide Method Body
{
	if action, ok := m.keyBindings[key]; ok {
		m.active[action] = true
	}
}

handleKeyUp


Parameters:
  • key string

Show/Hide Method Body
{
	if action, ok := m.keyBindings[key]; ok {
		delete(m.active, action)
	}
}

handleMouseDown


Parameters:
  • button int
  • x float32
  • y float32

Show/Hide Method Body
{
	if action, ok := m.mouseBindings[button]; ok {
		m.active[action] = true
	}
	if button == 0 {
		m.dragging = true
		m.dragStart = math.Vec2{x, y}
		m.dragEnd = m.dragStart
	}
	m.lastPos = math.Vec2{x, y}
}

handleMouseUp


Parameters:
  • button int
  • x float32
  • y float32

Show/Hide Method Body
{
	if action, ok := m.mouseBindings[button]; ok {
		delete(m.active, action)
	}
	if button == 0 {
		m.dragging = false
	}
	m.lastPos = math.Vec2{x, y}
}

handleMouseMove


Parameters:
  • x float32
  • y float32

Show/Hide Method Body
{
	pos := math.Vec2{x, y}
	if m.dragging {
		m.dragEnd = pos
	}
	dx := pos.X - m.lastPos.X
	dy := pos.Y - m.lastPos.Y
	if m.IsActive("pan") {
		m.Pan(dx, dy)
	}
	if m.IsActive("rotate") {
		m.Rotate(dx)
	}
	m.lastPos = pos
}

handleWheel


Parameters:
  • delta float32

Show/Hide Method Body
{ m.Zoom(-delta / 100) }

newManager function

Returns:

  • *Manager
Show/Hide Function Body
{
	return &Manager{
		keyBindings:   make(map[string]string),
		mouseBindings: make(map[int]string),
		active:        make(map[string]bool),
		camera:        Camera{Zoom: 1},
	}
}

New function

New creates a Manager and wires browser event listeners.

Returns:

  • *Manager
Show/Hide Function Body
{
	m := newManager()

	events.OnKeyDown(func(evt js.Value) {
		m.handleKeyDown(evt.Get("key").String())
	})
	events.OnKeyUp(func(evt js.Value) {
		m.handleKeyUp(evt.Get("key").String())
	})

	events.On("mousedown", js.Document(), func(evt js.Value) {
		m.handleMouseDown(evt.Get("button").Int(), float32(evt.Get("clientX").Float()), float32(evt.Get("clientY").Float()))
	})
	events.On("mouseup", js.Document(), func(evt js.Value) {
		m.handleMouseUp(evt.Get("button").Int(), float32(evt.Get("clientX").Float()), float32(evt.Get("clientY").Float()))
	})
	events.On("mousemove", js.Document(), func(evt js.Value) {
		m.handleMouseMove(float32(evt.Get("clientX").Float()), float32(evt.Get("clientY").Float()))
	})
	events.On("wheel", js.Document(), func(evt js.Value) {
		m.handleWheel(float32(evt.Get("deltaY").Float()))
	})

	return m
}

New function

New creates a Manager without wiring event listeners.

Returns:

  • *Manager
Show/Hide Function Body
{ return newManager() }

TestKeyBinding function

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	m := New()
	m.BindKey("jump", "Space")
	m.handleKeyDown("Space")
	if !m.IsActive("jump") {
		t.Fatalf("action not active on key down")
	}
	m.handleKeyUp("Space")
	if m.IsActive("jump") {
		t.Fatalf("action still active after key up")
	}
}

TestDragRect function

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	m := New()
	m.handleMouseDown(0, 10, 20)
	m.handleMouseMove(30, 40)
	start, end, dragging := m.DragRect()
	if !dragging {
		t.Fatalf("expected dragging state")
	}
	if start != (math.Vec2{10, 20}) || end != (math.Vec2{30, 40}) {
		t.Fatalf("unexpected drag rect %v %v", start, end)
	}
	m.handleMouseUp(0, 30, 40)
	_, _, dragging = m.DragRect()
	if dragging {
		t.Fatalf("drag state not cleared")
	}
}

TestCameraControls function

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	m := New()
	m.BindMouse("pan", 1)
	m.handleMouseDown(1, 0, 0)
	m.handleMouseMove(5, -5)
	cam := m.Camera()
	if cam.Position != (math.Vec2{5, -5}) {
		t.Fatalf("pan not applied, got %v", cam.Position)
	}
	m.handleWheel(-120)
	cam = m.Camera()
	if cam.Zoom <= 1 {
		t.Fatalf("zoom not applied, got %v", cam.Zoom)
	}
	m.BindMouse("rotate", 2)
	m.handleMouseDown(2, 0, 0)
	m.handleMouseMove(10, 0)
	cam = m.Camera()
	if cam.Rotation == 0 {
		t.Fatalf("rotation not applied")
	}
}

github.com/rfwlab/rfw/v1/math import

Import example:

import "github.com/rfwlab/rfw/v1/math"

github.com/rfwlab/rfw/v1/events import

Import example:

import "github.com/rfwlab/rfw/v1/events"

github.com/rfwlab/rfw/v1/js import

Import example:

import "github.com/rfwlab/rfw/v1/js"

Imported as:

js

testing import

Import example:

import "testing"

github.com/rfwlab/rfw/v1/math import

Import example:

import "github.com/rfwlab/rfw/v1/math"