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) andThickCircle
(outline). -
Arc
(filled) andThickArc
(outline).
-
-
Color
for the primitives. -
Text
to draw with a vector font. -
Bitmap
andBitmapSection
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.
-
Gloss’s rendering of
- Skip OpenGL and dive into GPU programming with Starting with Vulkan.
- Go world-wide with a related library in a browser.