Skip to content
A tiny ray caster game rendered using raw SDL2, written in F#
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore replaced git ignore with more comprehensive file Mar 7, 2019
LICENSE added initial files Mar 7, 2019
Program.fs typos and formatting Mar 11, 2019
README.md
SDL.fs Errant semicolon removal Mar 11, 2019
SDL2.dll
map.txt
screencast.gif
tiny-ray-caster.fsproj
tiny-ray-caster.sln
walltext.png

README.md

tiny-ray-caster

A tiny ray caster game rendered using raw SDL2, written in F#:

This is an F# version of the excellent tutorial here by Dmitry V. Sokolov.

Why? Because I wanted to have a go using raw SDL2 from F# (not even using the SDL2-CS bindings from flibitijibibo).

Also, given that Dmitry's work is just 486 lines of C++, I was interested to see how a language almost on the other end of the high/low spectrum from C++ would do :)

Running and Building

This has been coded in .NET Core 2.2, using VS Community 2017 on Windows 10. You can run it either using VS, or via dotnet run on the command line.

I have not tested it on other platforms - the only likely point of incompatibility would be the SDL2 library: included is the SDL2.dll from 2.0.9 for 64 bit windows.

Alternative versions of SDL can be acquired from here

Learnings

Things I learned building this include:

  • the netbpm format (https://en.wikipedia.org/wiki/Netpbm_format)
    • to open/view ppm files, I had to install gimp on windows.
    • on linux/osx, it might be easier to install & use display in the terminal
    • ppm is an uncompressed image format, so is not generally recommended for images (which is probably why the support is so poor, plus its almost 40 years old)
    • Note: when I move to SDL, I removed the ppm code. Its in the history around this commit if you want to see it.
  • basic raycasting for wolfenstein 3D-esque rendering
    • the 'fish-eye' issue when rendering is something I learned more about (specifically how to solve it) from The Black Book by Fabien Sanglard. I recommend it.
    • I didn't include the monsters from Dmitry's demo - I was more interested in ray casting and SDL interop, to be honest. Maybe something to do in future.
    • As a performance improvement, the raycasting uses a more granular jump rate, then walks back to find the exact point once it finds a hit.
  • SDL2 Interop and Interop and general
    • My implementation is a combination of replicating what Dmitry did, with a conversion of the interop declarations by Flibit
    • I restricted to just what I need, so the SDL interop module is quite small. Where appropriate, I would declare flag-like constants as their raw value, generally derived by running SDL2-CS as a console app to get the value and then putting it here (e.g. SDL_PIXELFORMAT_ABGR8888 as 376840196u)
    • Event polling was complicated, and I ended up restricting to just the event I needed. The union hack in the SDL2-CS lib I couldn't get working with F# (ironic, since F# actually has unions)
    • Other reasons for not using SDL2-CS (i.e. other than the educational challenge) is that I only need a small subset of SDL2's signature, and SDL2-CS is not net standard (its Net Framework 4, as opposed to this project which is Net Core 2.2).
You can’t perform that action at this time.