Horologe - Mechanisms That Draw Themselves
A downloadable asset pack
A picture of a gear cannot mesh with another picture of a gear.
The clockwork shelf for GameMaker is static art. Horologe is the mechanism instead: wheels, pinions, escapements, dials and hands computed from real tooth counts and drawn in pure GML. There is no sprite, no spritesheet, no atlas and no texture page in this package. sprites/ does not exist.
12 machines · 8 tooth profiles · 10 crossing patterns · 8 escapements · 6 oscillators · 10 dials · 10 hands · 8 frames · 6 drives · 14 materials
A wheel is a number, and everything follows from it
pitch radius r = module * N / 2
circular pitch p = pi * module <- equal on both wheels of a mesh
angular pitch a = TAU / N
ratio to a mate -N_this / N_that
Change a wheel from 96 teeth to 60 and the teeth get coarser and the hand it drives runs faster, because the drawing and the ratio come out of the same number. That is the whole product.
The example worth looking at first
The longcase regulator's train is 96/12, 96/12, 90/12 with a 30-tooth escape wheel — real English counts. Nobody typed a speed anywhere. Those numbers alone produce a centre arbor turning exactly once per hour, an escape arbor turning exactly once per minute, and a beat of exactly 1.000 seconds, which is to say a seconds pendulum.
Change the 90 to an 80 and you get a shorter pendulum, a faster seconds hand, and a clock that still works. It is just a different clock.
The teeth actually interleave
Centre distance, ratio and phase are all computed from the two tooth counts. The driven wheel's phase is solved so that a tooth of the driver lands in a gap of the driven wheel at the line of centres — at every moment, not only at the start.
hrl_mesh_error() measures that at any time you name. It returns how far the driver's nearest tooth sits from the line of centres and how far the driven wheel's nearest gap sits from it, in arc length at the pitch circle, and the two must cancel. The bundled suite checks every mesh of every machine at twelve different moments.
It steps, because a real train does
A weight or a spring pulls all the time; the escapement lets the train forward one half tooth per beat and holds it the rest of the time. So there is exactly one quantised quantity — the time the train has been allowed to advance to — and every wheel is a pure function of it.
The seconds hand jumps. The pendulum, which reads the continuous time, sweeps. Both come out of the same number, so they cannot drift apart. That difference is most of what makes a mechanism read as a machine rather than as two animations playing near each other.
It drives your game, not just your screen
Every machine declares OUTPUTS: an arbor, and what one revolution of it means. A clock's centre arbor means sixty minutes. An orrery's earth arbor means one year. A counting machine's last arbor means a thousand of the first.
var _r = hrl_machine_read(mach);
if (_r.hours >= 6 && _r.hours < 18) world_is_daytime = true;
Your game reads a struct and never has to know what a pinion is.
Age is a transform, not a second set of art
Each of the fourteen materials is a five-stop perceptual ramp shaped by a finish program rather than a tint, so a steel wheel and a brass one shade differently as well as reading differently. Ageing pulls the ramp toward a tarnish target weighted by chroma, which is why near-neutral steel goes straight to brown instead of sweeping through violet on its way. One movement, five ages, no extra artwork.
Integration is five lines
mach = hrl_machine_new(0, 0, 12345); // kind, material, seed
hrl_machine_set_time(mach, 10, 9, 36);
// Step: SECONDS of game time, not frames.
hrl_machine_step(mach, delta_time / 1000000);
hrl_render_in_rect_tight(hrl_machine_parts(mach, true), mach.pal, x, y, 256, 256, undefined);
A runnable demo room ships with it. Open rm_hrl_demo, press Play, and step through all twelve machines and all fourteen materials with the arrow keys.
It is affordable to draw, and here is why
A wheel's shape is constant. Only its angle moves. So bake each component once with hrl_render_to_sprite and draw it with draw_sprite_ext at the angle the train solved: a twelve-wheel movement is twelve sprite draws per frame instead of thousands of primitives.
That is only honest because of a rule in the wheel builder. Baking a shape and then rotating the sprite rotates its shading too — the classic tell of a sprite pretending to be a lit object. Real wheelwork is snailed or radially grained, so its highlight is a function of radius rather than of world direction, and every wheel is built with n-fold symmetry about its arbor. The suite asserts that symmetry per crossing pattern by rebuilding each wheel at a one-pitch offset and comparing the part lists.
Compatibility
GameMaker Studio 2.3+ and GameMaker 2024.x. Built and verified against runtime 2024.14.4.268 (the current stable legacy runtime). Pure GML with no extensions, no DLLs and no external dependencies. Import with Tools → Import Local Package and select all.
Everything is namespaced hrl_ / HRL_. GML's global namespace is flat and a collision in your project would be a compile error pointing at a file you did not write; there are no unprefixed globals in this package.
Verification, stated honestly
GML cannot be unit-tested outside the engine — there is no headless runner and no mocking. So this package builds through Igor and runs its own suite inside the finished executable: 1,226 in-engine assertions, 0 failures, covering the corpus counts, every mesh of every machine at twelve moments, tooth counts read back out of the finished drawing, wheel symmetry per crossing pattern, the quantised train against the continuous oscillator, every material ramp and its ageing, and determinism.
Every image on this page was rendered by the package itself, through the same drawing code you get, in an Igor-built executable.
What that does not prove: a suite that computes numbers cannot see a picture. Every sheet was also opened and looked at, and several defects were found that way and only that way — a vertex-batch truncation that silently dropped part of a 96-tooth rim among them.
Raw, readable GML. Commented throughout. Minification would be a defect.
Also from CSAF, for GameMaker
Borough — settlements builds the places these mechanisms belong in. Both draw their subject in pure GML, so a town clock and the tower around it come from the same pipeline.
Affliction — status effects · Vestige — achievements · Bourse — markets · Repast — cooking · Livery — interface themes · Lode — minerals and ore · Welkin — skies and weather · Armoury — weapons
| Updated | 6 days ago |
| Published | 13 days ago |
| Status | Released |
| Category | Assets |
| Author | CSAF — Core Systems Asset Factory |
| Made with | GameMaker |
| Tags | 2D, Animation, clock, GameMaker, gears, Generator, gml, Procedural Generation, sourcecode, Steampunk |
| Languages | English |
| AI Disclosure | AI Assisted, Code, Graphics, Text |
Purchase
In order to download this asset pack you must purchase it at or above the minimum price of $14.99 USD. You will get access to the following files:












Leave a comment
Log in with itch.io to leave a comment.