Context
The frame Context object comes in numerous forms, but its purpose is to provide common data points and services, that are regularly required during game development.
Demo
Links
For this example, we'll also need a primitive whose bounds we can measure.
val boxSize = Size(100)
val boxShape: Shape.Box =
Shape
.Box(
Rectangle(Point.zero, boxSize),
Fill.LinearGradient(Point.zero, RGBA.Cyan, boxSize.toPoint, RGBA.Magenta),
Stroke(2, RGBA.White)
)
Context comes in three parts: Frame, services, and everything else. No matter which flavor of context object you have available, frame and services will always be present.
Frame
Frame information and helpers are light weight, stateless, immutable and referentially transparent values and utilities. Which means that you can safely reference them without adding much burden should you need to write unit tests.
Below are some examples.
context.frame.viewport
context.frame.dice.roll(6)
context.frame.dice.rollDouble
context.frame.dice.rollAlphaNumeric(16)
context.frame.input.mouse.position
context.frame.time.running
context.frame.time.delta
Services
Services on the other hand and stateful, side-effecting, and potentially expensive operations to be used with caution. That doesn't mean "don't use them", it just means they need a little more consideration.
Some services are shown below.
Random
Random differs from Dice in that it is zero based (Dice always have at least 1 side!), and it uses a stateful long running Random instance, meaning that it does give better random numbers at the cost of testing complexity.
context.services.random.nextInt
context.services.random.alphanumeric(16)
Boundary Locator
The boundary locator asks Indigo to calculate the bounding box of any visual primitive. Sometimes this is easy, sometimes it's expensive, depending on the primitive type. Text for example, requires the bounds calculation of every glyph, and then the total bounds of all the arranged glyphs.
context.services.bounds.find(boxShape)