Starting with Gloss

Gloss provides multiple runners of different complexity, but they all converge on a single thing: a way to get a Picture to display on screen.

Most pure of them is display, it simply displays a static picture over a colored background. Most complex and powerful is playIO. And others are in-between, adding one aspect at a time:

  • Time step function
  • Custom state type
  • Input event step function
  • Ability to use IO

The package has all kinds of examples for you to try out.

Typical flow

Gloss is really easy to pick up and start showing moving things.

In no particular order:

  • Describe your state in a top-level “world” type.
    • Provide its initial value.
  • Add rendering function.
    • Avoid calculations. Even if you can, that doesn’t mean you should.
  • Add “passive” simulation step function.
    • World step function is just a composition of its parts.
    • You can trigger sounds here.
  • Add “active” event-handling function.
    • Strive to keep your handlers minimal. Store control state in the world and let the simulation handle reactions.
  • If you need to load resources, do it before launching off playIO.

That’s it, time to ship your game. Or add some features. Or get a [[topic/profiling|profiler]] report.

Elements provided

Gloss is all about building a scene - a value of type Picture.

A picture can be one of:

  • Blank, with nothing in it.
  • Some vector primitives:
    • Polygon strictly convex polygon filled with a solid color.
    • Line a line along an arbitrary path.
    • Circle (filled) and ThickCircle (outline).
    • Arc (filled) and ThickArc (outline).
  • Color for the primitives.
  • Text to draw with a vector font.
  • Bitmap and BitmapSection that can be used for sprites and atlases.
  • Transformations:
    • Translate
    • Rotate
    • Scale
  • And finally, more Pictures to put into transformations and coloring.

Without any transformations applied the Picture will be drawn in the middle of the screen, where the (0, 0) point lies.

Distance units are set in pixels and window size in FullScreen equals to pixel width and height. You can query those with getScreenSize.

Multiple scenes

Main loop functions provided don’t stop unless you close the window. You can, however, have multiple or even interlocking scenes by putting a scene state into the world type:

data World = World
  { scene :: Scene
  , ...
  }

data Scene
  = Intro
  | Game
  | Score

Then branch on it in every of the draw/tick/event functions where appropriate:

tick :: Float -> World -> IO World
tick dt World{..} = case scene of
  Intro -> Intro.tick dt
  Game  -> Game.tick dt
  Score -> Score.tick dt

Extensions

Out of the box it can only load .bmp files, but gloss-juicy adds .jpg and .png support without C dependencies.

SDL2 surfaces can be converted into gloss Picture with gloss-sdl2-surface. This opens up the way to have animated textures and big letters in nice TrueType fonts.

There are quite a few packages around on Hackage (sort by pub date).

Limitations

It is backed by OpenGL, but most of the functions and display context are unavailable. That means “immediate mode” and no shaders. Interfering with its draw function is unadvised.

Font rendering uses hardcoded proportional vector font from GLUT library. It is very limited in character set. You can’t take a measure of it and it is not monospaced. Forget aligning and [[topic/i18n|i18n]].

Bitmaps are converted to OpenGL textures privately and can be either transient (per-frame) or cached, without an ability to evict them. This can be a performance problem if you’re brave enough to use bitmap fonts.

And yet, it is certainly possible to make a real and complex game with fancy animations.

Where to go next?

  • Experiment with different world types
  • Visualize and animate arrays with gloss-raster.
  • Dive into OpenGL
    • Gloss’s rendering of Picture is packaged in gloss-rendering. You can inspect that to get a quickstart on OpenGL immediate mode rendering. You’ll get the looks, but it works good enough.
    • Use OpenGL bindings directly.
  • Skip OpenGL and dive into GPU programming with Starting with Vulkan.
  • Go world-wide with a related library in a browser.
Links to this page
#intro #2d #gloss