Sunday, June 11, 2017

The Oak Renderable Interface

This post will serve as a tutorial through the render package, Oak's largest built in package and the basis for drawing elements to a window.

// A Renderable is anything which can
// be drawn at a given draw layer, undrawn,
// and set in a particular position.
//
// Basic Implementing struct: Sprite
type Renderable interface {
// As the engine currently exists,
// the buffer which is passed into draw
// is always the same. This leads to
// several parts of the engine being
// reliant on shiny/screen when they
// could call out to somewhere else to
// determine what they are drawn onto.
//
// On the other hand, this allows manually
// duplicating renderables onto multiple
// buffers, but in certain implementations
// (i.e Animation) would have unintended
// consequences.
Draw(buff draw.Image)
DrawOffset(buff draw.Image, xOff, yOff float64)
// Basic Implementing struct: Point
ShiftX(x float64)
GetX() float64
ShiftY(y float64)
GetY() float64
SetPos(x, y float64)
GetDims() (int, int)
// Basic Implementing struct: Layered
GetLayer() int
SetLayer(l int)
UnDraw()
// Utilities
String() string
// Physics
physics.Attachable
}
view raw renderable.go hosted with ❤ by GitHub


To draw arbitrary objects to a window, Oak uses the Renderable type, which in short is any type that can be drawn, has a position, has an order for when it should be drawn with respect to other Renderables (a layer), and can be Un-drawn. Particles, as written about a few posts past, are themselves renderables and are in a subpackage of the render package.

Most Renderables are also Modifiables:

// A Modification takes in an image buffer and returns a new image buffer
type Modification func(image.Image) *image.RGBA
// A Modifiable is a Renderable that has functions to change its
// underlying image.
// This may be replaced with the gift library down the line
type Modifiable interface {
Renderable
GetRGBA() *image.RGBA
Modify(...Modification) Modifiable
Copy() Modifiable
}
view raw modifiable.go hosted with ❤ by GitHub


So while Oak has a number of built in Modifications involving color modification, scaling, and shape changing, users of the library can build their own Modifications using this signature, and the result will be compatible with most built in Oak types.

Users can also write their own Renderable or Modifiable types, an example being the radar in Agent Blue (although this is 10 months old, and API improvements have made it easier to do some things the radar is doing).

Oak currently has nine Renderable types outside of particles:

  • Sprite: the most basic Renderable, a sprite is just an *image.RGBA with a position. There are plenty of ways to construct a Sprite-- lines, boxes, gradients, noise, and of course loaded image files are all built into the engine.  
  • Text: anything that implements the fmt.Stringer interface can be turned into a piece of text that can be assigned Font settings on the fly.
  • Animation: a sequence of positions on a Sheet animating at some frame rate.
  • Sequence: an animation that does not use an underlying sprite sheet, but a list of renderables instead. 
  • Composite: a list of other Renderables to be drawn as one unit.
  • Compound: a map of Renderables that can be switched between at will, where only one is drawn at any point in time. This is useful for characters that can have one of any number of animations active, like attacking versus moving. 
  • Polygon: a list of points drawn as a 2d shape.
  • Reverting: a Modifiable that can be modified multiple times, but remembers what it used to look like. This is used for applying temporary effects.
  • ScrollBox: a box which wraps around some set of Renderables and draws them inside a small viewport. This viewport can scroll horizontally and vertically, and the renderables inside the ScrollBox can be set to reappear after they've shifted some amount. 
Look for tutorials on using each of these types once Oak is released publicly.

It's worth noting that all of these types are implicitly 2D, and this is at least in part because we don't want to target 3D drawing or 3D games until we've got the current API stable and performant. I have experimented with making 3D Renderables in Oak, and that work can be seen here.

No comments:

Post a Comment