Class: RGame::Engine::Camera
- Inherits:
-
Object
- Object
- RGame::Engine::Camera
- Defined in:
- lib/rgame/engine/camera.rb
Overview
A 2D camera: a point in the world to look at, plus the world bounds it may not show past. Pure; the offset it produces is applied as a draw-time transform, never baked into a node.
camera = Camera.new(world_width: map.pixel_width, world_height: map.pixel_height)
camera.center_on(player.abs_x, player.abs_y) # in update, every tick
camera.resolve(view_width, view_height) # at draw, for one viewport
camera.x, camera.y # the offset to translate by
Why the viewport size is an argument and not state
A camera used to be built with its viewport size and clamp against it in
center_on. That cannot survive split-screen: the same world is drawn
through several viewports whose rects come from the layout and change when
a player joins or the window resizes. Clamping has to happen against the
rect actually being drawn into, and the difference is visible rather than
theoretical — near a world edge, the same target sits at a different place
on screen in a half-width viewport than in a full-width one.
So center_on records intent and resolve computes the offset. Nothing
calls resolve by hand: the platform resolves each camera against the
viewport it is about to draw, which is what keeps the two from drifting.
The camera belongs to a player, not to a scene
A scene may have any number of viewers, so it cannot own "the" camera. RGame::Engine::Player owns one; a scene sets its world bounds when it loads a map, and a CameraFollow component in the world points it.
Instance Attribute Summary collapse
-
#target_x ⇒ Object
readonly
Returns the value of attribute target_x.
-
#target_y ⇒ Object
readonly
Returns the value of attribute target_y.
-
#world_height ⇒ Object
Returns the value of attribute world_height.
-
#world_width ⇒ Object
Returns the value of attribute world_width.
-
#x ⇒ Object
readonly
Returns the value of attribute x.
-
#y ⇒ Object
readonly
Returns the value of attribute y.
Instance Method Summary collapse
-
#center_on(world_x, world_y) ⇒ Object
Look at this world point.
-
#initialize(world_width: nil, world_height: nil) ⇒ Camera
constructor
world_width/world_heightbound what the camera may show. -
#resolve(view_width, view_height) ⇒ Object
Work out the draw offset for a viewport of this size, clamped so the view never shows past the world's edges.
Constructor Details
#initialize(world_width: nil, world_height: nil) ⇒ Camera
world_width / world_height bound what the camera may show. Left nil
the camera is unbounded and follows its target exactly — which is the
right default: a game that has not declared its world yet gets a camera
that visibly works, rather than one silently pinned to the origin.
41 42 43 44 45 46 47 48 |
# File 'lib/rgame/engine/camera.rb', line 41 def initialize(world_width: nil, world_height: nil) @world_width = world_width @world_height = world_height @target_x = 0.0 @target_y = 0.0 @x = 0.0 @y = 0.0 end |
Instance Attribute Details
#target_x ⇒ Object (readonly)
Returns the value of attribute target_x.
34 35 36 |
# File 'lib/rgame/engine/camera.rb', line 34 def target_x @target_x end |
#target_y ⇒ Object (readonly)
Returns the value of attribute target_y.
34 35 36 |
# File 'lib/rgame/engine/camera.rb', line 34 def target_y @target_y end |
#world_height ⇒ Object
Returns the value of attribute world_height.
35 36 37 |
# File 'lib/rgame/engine/camera.rb', line 35 def world_height @world_height end |
#world_width ⇒ Object
Returns the value of attribute world_width.
35 36 37 |
# File 'lib/rgame/engine/camera.rb', line 35 def world_width @world_width end |
#x ⇒ Object (readonly)
Returns the value of attribute x.
34 35 36 |
# File 'lib/rgame/engine/camera.rb', line 34 def x @x end |
#y ⇒ Object (readonly)
Returns the value of attribute y.
34 35 36 |
# File 'lib/rgame/engine/camera.rb', line 34 def y @y end |
Instance Method Details
#center_on(world_x, world_y) ⇒ Object
Look at this world point. Records the target; the offset is worked out by #resolve, which is the only place that knows how big the view is.
52 53 54 55 56 |
# File 'lib/rgame/engine/camera.rb', line 52 def center_on(world_x, world_y) @target_x = world_x @target_y = world_y self end |
#resolve(view_width, view_height) ⇒ Object
Work out the draw offset for a viewport of this size, clamped so the view never shows past the world's edges.
60 61 62 63 64 |
# File 'lib/rgame/engine/camera.rb', line 60 def resolve(view_width, view_height) @x = clamp(@target_x - (view_width / 2.0), @world_width, view_width) @y = clamp(@target_y - (view_height / 2.0), @world_height, view_height) self end |