# Monthly Update On A Haskell Game Engine

**URL:** <https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515>\
**Category:** Show and Tell\
**Created:** [January 1, 2023, 6:24pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515 "2023-01-01T18:24:21Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [January 1, 2023, 6:24pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/1 "2023-01-01T18:24:21Z")

</div>

Hey all, I’ve been working the past month or two in a game engine 🙂 (called `Ghengin`)

This post is not yet a release – I’m still far enough from a version 0.1.0.  
However, I’ve come a long way and I’d like to share a few pictures of my progress. Here’s the latest screenshot:

 ![devlog1](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/5/57fa8a0cb156ada1e66702fc337c43f022b26370.jpeg)

I hope to, soon enough, write a more substantial explanation of the engine’s technical challenges and overall design decisions so far; and on the game developer’s facing side of the engine.

A few key points regarding the main libraries it currently depends on (besides core ones like vector, containers, time, …):

- The renderer is written using the [great bindings to the Vulkan API](https://hackage.haskell.org/package/vulkan)
- The shaders are crucial in the overall design, and a lot of code depends on their definition (e.g. preparing render pipelines, allocating descriptor sets and textures, everything materials related …). The shaders are written using [FIR](https://gitlab.com/sheaf/fir), an amazing shader language embedded in Haskell!
- The entity management, scene graph and render queue are done/created through the [apecs](https://hackage.haskell.org/package/apecs-0.9.4) entity component system.
- Vectors and matrices are from [geomancy](https://hackage.haskell.org/package/geomancy-0.2.4.1)
- [GLFW-b](https://hackage.haskell.org/package/GLFW-b) for window management and user input (used as the window backend for vulkan)
- The [dear-imgui bindings](https://hackage.haskell.org/package/dear-imgui) for the GUI
- [JuicyPixels](https://hackage.haskell.org/package/JuicyPixels-3.3.8) for loading textures

A cool note on FIR: the shader’s “interfaces” are defined at the type level, and that type information is used to validate the game-developer-defined-materials, i.e. if you define materials incompatible with your shaders, the program will fail at compile time

The game itself is based on Sebastian Lague’s series [Procedural Planets](https://www.youtube.com/playlist?list=PLFt_AvWsXl0cONs3T0By4puYy6GM22ko8).

The showcase:

The very first achievement was rendering a triangle:

 ![61A65936-7807-4139-B902-90F495E57EB4_1_102_o](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/a/a0e00b089be920ffa99a3606bd6210bce9eee755.jpeg)

Then I rendered a simple cube and was able to rotate it with a simple model transform matrix:

 ![9025FAEF-2D5C-4EF4-BB3B-B4FA69169DD4_1_102_o](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/8/883af437f512a4f8c2a1860dba5f7a704b9b1be3.jpeg)

Later I got a perspective camera which could move around the world. I was generating spheres at this point and the colors show that I was getting closer to generating the normals right too.

 ![0DAECE59-A590-4893-9979-F3815376EC9B_1_201_a](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/e/e2c039c0e0916e20cda36505162b9e2a9bbc2f2e.jpeg)

I managed to integrate dear-imgui into the renderer at this point, and later on fixed a dreaded [off by one error](https://github.com/haskell-game/dear-imgui.hs/pull/166) which kept making the GUI behave funny and crash. I was also experimenting with simple diffuse lighting here.

 ![1972E8AA-6CF8-46C8-B9D5-99BEE9A9AE39_1_105_c](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/a/ac912004e59c813640f0ef661c84b09c06166337.jpeg)

With the GUI in place, I started focusing on developing planets by generating single sphere and modifying the height value of each point on the sphere by noise value: generating terrain and mountains.

 ![D3CA5318-2FAC-4BB3-A594-C942884266DB_1_102_o](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/d/dcba5f627d71b0faee1e9cdba596fdbe766e067d.jpeg)

After the terrain generation I spent some long weeks on the internals of the renderer before achieving more visual results with the exception of the following color-based-on-height-relative-to-min-and-max-heights planet:

 ![E002F230-2B90-4A11-831A-7B3A878EDD08_1_102_o](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/d/d74fddaf7528e8cc484e3f6fa3969aa3b4762f90.jpeg)

Those weeks were spent in internal technical challenges which I hope to describe on a subsequent post with the resulting design and implementation (and hopefully avoid to some extent the arduous process of understanding and reaching a design and implementation).

This week, with the material system working great for a first iteration, I spent finally some more time on the procedural planets: I added specular highlights to the lighting model (using the blinn-phong model) and added a (gradient based) texture to the planet that is sampled according to the height of each point in the planet. The result is a nicely lit planet with colors depending on the height (lower height = blue for water, middle = green for grass, higher = brown for mountains)

 ![devlog1](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/5/57fa8a0cb156ada1e66702fc337c43f022b26370.jpeg)

PS: I don’t expect it to be useful without a proper explanation, but the development is going on @ [GitHub - alt-romes/ghengin: Ghengin: A vulkan-based, shader-centric, type-heavy, Haskell game engine](https://github.com/alt-romes/ghengin). The next feature which is almost done is a gradient editor in the GUI.

Here’s a quick look at the Main module of the procedural planets game.

```hs
initG :: Ghengin World ()
initG = do

  -- Planet settings used to generate the planet and which are edited through the UI
  ps <- makeSettings @PlanetSettings
  (planetMesh,minmax) <- newPlanet ps

  -- Load the planet gradient texture
  sampler <- createSampler FILTER_NEAREST SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
  tex <- texture "assets/planet_gradient.png" sampler

  -- Create the render pipeline based on the shader definition
  planetPipeline <- makeRenderPipeline Shader.shaderPipeline

  -- Create a material which will be validated against the render pipeline at compile time
  m1 <- material (Texture2DBinding tex . StaticBinding (vec3 1 0 0) . StaticBinding minmax) planetPipeline

  -- Create a render packet with the mesh, material, and pipeline.
  -- All entities with a RenderPacket component are rendered according to it.
  let p1 = renderPacket planetMesh m1 planetPipeline

  -- Define our scene graph
  sceneGraph do

    -- A planet entity, with the planet render packet and a transform
    e1 <- newEntity ( p1, Transform (vec3 0 0 0) (vec3 1 1 1) (vec3 0 (pi/2) 0) )

    -- A camera
    newEntity ( Camera (Perspective (radians 65) 0.1 100) ViewTransform
              , Transform (vec3 0 0 0) (vec3 1 1 1) (vec3 0 0 0))

    -- The planet UI component based on the `ps` settings
    newEntityUI "Planet" $ makeComponents ps (e1,tex)

  pure ()

updateG :: () -> DeltaTime -> Ghengin World Bool
updateG () dt = do

  -- Every frame we update the first person camera with the user inputs and the planet's rotation
  cmapM $ \(_ :: Camera, tr :: Transform) -> updateFirstPersonCameraTransform dt tr
  cmap $ \(_ :: RenderPacket, tr :: Transform) -> (tr{rotation = withVec3 tr.rotation (\x y z -> vec3 x (y+0.5*dt) z) } :: Transform)

  pure False

main :: IO ()
main = do
  -- Run the game with this init, update and end function
  ghengin w initG undefined updateG endG

```

If you are curious about the full source of the planets game, beware of dragons 🙂. It is not ready as a learning resource whatsoever.

---

<div class="post-metadata">

**Author:** ![Bahpi](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/bahpi/32/2619_2.png) [@Bahpi](https://discourse.haskell.org/u/Bahpi)\
**Post date:** [January 1, 2023, 11:26pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/2 "2023-01-01T23:26:21Z")

</div>

Awesome work! Excited to see your progress 😀

---

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [January 1, 2023, 11:38pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/3 "2023-01-01T23:38:07Z")

</div>

Short update:

The gradient color picker is done and it’s now possible to pick in-game the planet color based on height 🙂

 ![Screenshot 2023-01-01 at 23.42.02](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/a/a5b90072a0337f8129111c8f43a649b0e52f60d9.png)

 ![Screenshot 2023-01-01 at 23.36.57](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/f/fd0e7b91c95c798b55379f24d37c7887f113a914.png)

---

<div class="post-metadata">

**Author:** ![Lsmor](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lsmor/32/3302_2.png) [@Lsmor](https://discourse.haskell.org/u/Lsmor)\
**Post date:** [January 2, 2023, 10:53am UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/4 "2023-01-02T10:53:11Z")

</div>

This looks awesome!! I’d really like to see more game written in Haskell. Not trying to discourage you, but have you checked the [kleid](https://gitlab.com/keid) project? It seems like both project can benefit each other, or maybe join forces…

---

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [January 2, 2023, 11:21am UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/5 "2023-01-02T11:21:41Z")

</div>

I haven’t tried keid myself but I am aware of it and have chatted a bit with the author @wiz on some occasions (concretely when fixing the dear-imgui bug and understanding matrix major modes in geomancy).

I started writing an engine because I wanted to, despite knowing about keid. Although comparing them now is fun – they have surely diverged in design decisions.

In due time, in a nice README, I’ll write what I can about related work such as keid.

---

<div class="post-metadata">

**Author:** ![wiz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/wiz/32/2408_2.png) [@wiz](https://discourse.haskell.org/u/wiz)\
**Post date:** [January 4, 2023, 12:50pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/6 "2023-01-04T12:50:00Z")

</div>

Keid has a goal that runs a bit contrary to what @romes wanted, namely being the “skip over all the internals and generic implementation details” framework.

Quite a few here really want to know just how the sausage was made and start from the level zero. Which, for the Vulkan API, is way down there than the thing OpenGL is based on.

Being a framework, Keid is closer to [Hickory](https://github.com/asivitz/Hickory/), I think. But I have only a cursory glance of it by now.

---

<div class="post-metadata">

**Author:** ![Lsmor](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lsmor/32/3302_2.png) [@Lsmor](https://discourse.haskell.org/u/Lsmor)\
**Post date:** [January 4, 2023, 1:34pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/7 "2023-01-04T13:34:09Z")

</div>

Great! another game engine I wasn’t aware about hahaha.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/nomeata/32/1188_2.png) [@nomeata](https://discourse.haskell.org/u/nomeata)\
**Post date:** [January 4, 2023, 3:35pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/8 "2023-01-04T15:35:47Z")

</div>

If one can name more Haskell game frameworks than Haskell games, what would that tell us? 😉

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [January 4, 2023, 3:40pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/9 "2023-01-04T15:40:18Z")

</div>

There’s a bunch of games listed on haskell-game.dev: [Games – Haskell GameDev](https://haskell-game.dev/games.html) and a bunch more (older ones) on the Haskell wiki: [Applications and libraries/Games - HaskellWiki](https://wiki.haskell.org/Applications_and_libraries/Games).

---

<div class="post-metadata">

**Author:** ![wiz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/wiz/32/2408_2.png) [@wiz](https://discourse.haskell.org/u/wiz)\
**Post date:** [March 25, 2023, 2:34pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/10 "2023-03-25T14:34:05Z")

</div>

Apparently we’ve missed a february update 😅

I’m still busy with incorporating all the stuff that came out after game jams and improving upon the newly discovered warts. Almost flipped the version to 2.0, but despite the initial impulse decided to proceed with 1.8.  
New release would lean even more on `ResourceT` so most of the breakage is due to blowing off useless resource management cruft.  
Another thing that I’m busy improving right now is introducing GHC.Generics and Higher-Kinded Data trick for pipelines with multiple instance buffers to remove even more boilerplate. Not particularly important for the pipelines already shipped, but should speed up introducing new custom pipelines.  
Tile pipeline got some game jam love and now compatible with Tiled rotation and mirroring flags. And new buffer-to-image helpers make dynamic tile maps a breeze.

Taken by inspiration I finally got to implementing KTX2 texture format that allows native Zstd compression and native Vulkan formats. And the loading can be even faster with less memory usage on CPU and GPU both. Basically PNG-sized textured without sRGB pain.

---

<div class="post-metadata">

**Author:** ![wiz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/wiz/32/2408_2.png) [@wiz](https://discourse.haskell.org/u/wiz)\
**Post date:** [April 26, 2023, 8:55pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/11 "2023-04-26T20:55:29Z")

</div>

The next major engine release is [finally out](https://keid.haskell-game.dev/Updates/2023-04-07.html) and I like it so far.

I’ve been experimenting with `apecs` [stores](https://gitlab.com/dpwiz/vecpack/-/tree/main/bench/Worlds) and found it is very difficult to improve upon the `IntMap`. Also the `apecs` itself is a thing of beauty.

SDL2 got a [new release](https://hackage.haskell.org/package/sdl2-2.5.5.0/changelog) and is now able to render textured/colored polygons without diving into OpenGL.

And now I got back to this year’s january jam ~~game~~ project about tiles, units, orders and stuff.  
The current focus is _unreasonable effectiveness of SDFs_ while preparing for navigation mesh generation. Perhaps I should wrap it up somewhere and start emergency preparations for LD53 coming this week-end.

As always, the meta-focus is on procedural generation since I have no studio behind me and have to use all the force multipliers I can.

 ![Screenshot from 2023-04-26 22-05-59](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/2/216f9646e0cd63bbfeb5cc0a6b01a7025953eb6e.png)

---

<div class="post-metadata">

**Author:** ![wiz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/wiz/32/2408_2.png) [@wiz](https://discourse.haskell.org/u/wiz)\
**Post date:** [May 31, 2023, 8:50pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/12 "2023-05-31T20:50:12Z")

</div>

What started as a weekend jam ended as a month-long death march, nothing new here 😅

What _is_ new, though…

- [tilesetter-codec](https://gitlab.com/dpwiz/tilesetter-codec) – A project file reader for [Tilesetter](https://www.tilesetter.org/), which is an **epic** tileset editor/generator/database. I really recommend it. Add your tiles, plop them together and it will guide you in making all the necessary transitions (and even generate you some starters). The codec package is only a reader (as usual), but its tests have a code generator example. Which I used to export a huge 4-terrain LUT (actually a `case`), together with weighted tile alternatives.
- The tileset (its hot parts) derived from a public domain image dump of that [Dune2 miscarried clone](https://lostgarden.home.blog/2005/03/27/game-post-mortem-hard-vacuum/). I love the style and it is varied enough to be extended and reused elsewhere.
- [schematosis](https://gitlab.com/dpwiz/schematosis) – A (very, _very_ WIP) library to work with sparse trees using `Free` wrapper over branching functor, sampling SDFs to them, and then contouring (only squares are marching for now, but also bilinear and (broken) dual). I tried to used contours to generate navigation meshes, but due time pressure ended up just A\*-ing over the rendered tile map.
- [gl-block](https://hackage.haskell.org/package/gl-block) – A library to generate `Storable` instances generically, according to packed/std140/std430 layout rules.

And, finally, the ld52 demo/workbench [slid](https://gitlab.com/dpwiz/ld52/-/merge_requests/1/diffs) into ld53 and now presents something like an RTS backbone, featuring:

- Random map generation (from SDFs, yeah) and rendering.
- Minimap preview.
- Unit/group selection and ordering around. Only moving for now, but with a queue.
- Unit spritesheets with directions (and a mini-tool to cut and place them).
- Building mode with placement preview.
- Async path-finding around rough terrain and placed buildings.
- Async visibility shroud updates.
- `reactive-banana` for event handling, `apecs` for units.

 ![Screenshot from 2023-05-31 23-47-41](https://us1.discourse-cdn.com/flex002/uploads/haskell/original/2X/3/3b33d1aaacd87894eb20f7e4ab48a9351910f62e.png)

It’s all very rare, but I really need a break. After all the work put into it, there’s so much more groundwork to do. I will finish the UI story and proceed with cleaning/fixing/polishing/extending stuff.

(And, technically, I’m in time to make it the monthly update of May 😜)

---

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [May 31, 2023, 9:07pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/13 "2023-05-31T21:07:47Z")

</div>

Incredible work @wiz !! I’m absolutely in awe of it, congrats!  
(As for me, I’ll definitely definitely be using `gl-block` – sounds like a life saver)

---

<div class="post-metadata">

**Author:** ![wiz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/wiz/32/2408_2.png) [@wiz](https://discourse.haskell.org/u/wiz)\
**Post date:** [September 10, 2023, 8:01pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/14 "2023-09-10T20:01:09Z")

</div>

Hackdate 20230910, captain’s log 😅

> **[2023-09-10](https://keid.haskell-game.dev/Updates/2023-09-10.html)**
>
> Picking up a new GHC and spinning off geomancy-layout and gl-block.

Thinking about doing something really, really small this time for LD54 compo.

---

<div class="post-metadata">

**Author:** ![Ambrose](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ambrose/32/5672_2.png) [@Ambrose](https://discourse.haskell.org/u/Ambrose)\
**Post date:** [September 10, 2023, 8:11pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/15 "2023-09-10T20:11:16Z")

</div>

> [@wiz](#):
>
> Thinking about doing something really, really small this time for LD54 compo.

Famous last words 😆

---

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [September 10, 2023, 8:20pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/16 "2023-09-10T20:20:25Z")

</div>

My progress on the game dev front is on hold, but I’ll be hopefully finishing my thesis until the end of the month and have time for it afterwards

Going to have to sit this Ludum Dare out, unfortunately!

---

<div class="post-metadata">

**Author:** ![Abhinavpatel00](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/abhinavpatel00/32/4780_2.png) [@Abhinavpatel00](https://discourse.haskell.org/u/Abhinavpatel00)\
**Post date:** [November 16, 2024, 3:35am UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/17 "2024-11-16T03:35:41Z")

</div>

hey is this game engine open source i would love to contribute if needed

---

<div class="post-metadata">

**Author:** ![romes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/romes/32/2912_2.png) [@romes](https://discourse.haskell.org/u/romes)\
**Post date:** [November 22, 2024, 6:04pm UTC](https://discourse.haskell.org/t/monthly-update-on-a-haskell-game-engine/5515/18 "2024-11-22T18:04:49Z")

</div>

Hi @Abhinavpatel00, the engine is indeed open source (there’s a link somewhere in the original post), but at the moment it would be somewhat hard to contribute as I haven’t had tons of time to play with it, and my great vision for the next steps is stuck in my head ;). I’ll let everyone know when something usable is ready. Thanks for the interest
