Devlog
I'm making MÁG, an isometric mage RPG, in Rock and Stone, my own language and engine.
-
Is simple actually good?
As I sit down to my Elektron Digitone 2 with the intention to compose something for my new game I just realized something. Not only have I not touched this machine in over 6 months…
-
Let's Write a 2D Platformer From Scratch
Game loop, tile rendering, raycast collisions and tweening, in plain canvas JavaScript. Written in 2018 for my old blog.
-
Leaving Rust gamedev after 3 years ↗
Three years and a shipped game later: why Rust wasn't the right tool for the way I make games.
-
Comfy, a 2D game engine in Rust ↗
The previous engine. Archived, still open source.
-
Urban Mage: five years from Ludum Dare ↗
Post-mortem: scope creep, three engines and a genre switch on the way from a jam game to Steam, with sales and wishlist numbers.
-
HexMage: encounter balancing in a hex arena ↗
Turn-based mage tactics on a C#/MonoGame engine. An MCTS AI plays it against itself, and evolutionary search balances the encounters. Code on GitHub: darthdeus/HexMage.NET.
-
My old blog ↗
Haskell (lenses, monad transformers), Bayesian ML (variational inference, Dirichlet models), algorithms.
Built with Rock and Stone
MÁG runs on my own engine, Stone, which is written in my own language, Rock. I've been making both for about two years now, and they actually work :) Rock compiles to LuaJIT (and tries really hard not to allocate) and to GLSL for shaders, and the whole game builds from scratch in a few seconds. I'm getting the compiler ready to open source, the engine comes after.
co fn lightning_impact_co_in(world: WorldState, pos: Vec2, space: SpaceId) -> Coroutine<Wait> {
spawn_flash(pos, 3.5, 0.6, color(.45, .65, 1, 1), 0.1, curve: 0.5, space: space)
yield wait_sec(0.1)
spawn_flash(pos, 16, 7, color(0.85, 0.92, 1, 1), 0.13, curve: 4, space: space)
spawn_bolt(v(pos, 6), v(pos, 0.1), life: 0.0, space: space)
// On CONTACT, not on the ground answer: the jolt is the arrival, and it has
// to land on the same frame as the flash or it reads as a second event.
world_camera_trauma(world, STRIKE_TRAUMA, pos, space)
yield wait_sec(0.05)
spawn_strike_shock(pos, space: space)
spawn_fracture(pos, n: 5, length: 2.0, space: space)
yield wait_sec(0.14)
spawn_flash(pos, 6, 1, color(0.55, 0.78, 1.0, 1), 0.6, curve: 2, space: space)
emit_spark_burst(pos, count: 22, force: 8.0, space: space)
}
The lightning strike from the screenshot. It's a coroutine, trimmed down a bit.