First Steps

4 minute read

77 Days Until I Can Walk

What. A. Day! I’m struggling to sit down and write this post because I would much rather continue poking code and ironing out bugs.

Visually, it doesn’t look like much has happened since yesterday. I have implemented some simple controls that let you move around the scene using w, s, a, d, and the arrow keys. As expected this turned up a few graphical glitches, but I anticipated that, so no big deal. There’s no collision detection, so you can walk clean through walls an into oblivion if you wish. The question today was whether or not I should deal with these glitches now. Ultimately I have decided not to, and here is why.

Implementing Fixed Point Arithmetic

One technique I really want to use in this project is fixed point arithmetic. I read about this in Larry L. Myers “Amazing 3-D Adventure Game Set”. Basically the idea is that floating point arithmetic is incredibly slow as compared with integer arithmetic (at least when running on a CPU). So what we can do is shift our floating point values by some fixed amount (say three decimal places), and represent our float as an int with the fractional part of the float being represented in the lower bits of the int.

You need to do a little bit of fudging with arithmetic in order to get the maths to work out, but in theory this will make all the trigonometry used in ray casting significantly faster. Plus it’s just a really cool technique to use!

I’m more or less following Myers to the letter here. He shifts by 16 bits, so I’m going to do the same. We’re working at such a low resolution that I don’t anticipate the corresponding loss of precision will be an issue.

I have a partially finished solution now in place, but the core ray cast algorithm is still using floating point values. Tomorrow I will try to switch over to fixed point arithmetic. At that stage it will make sense to start hunting down all the little graphical bugs, implementing collision detection etc.

A Solution For Lookup Tables

I mentioned in an earlier article that I wanted to generate static lookup tables for all values that could be pre-computed by the engine. Ideally these tables would be populated at compile time. However, this does not seem to be as straightforward in Rust as it is in C++.

I found a solution in this article by an engineer using the handle rustyoctopus. After reading the article, I decided to try the build script solution. This seemed to be rustyoctopus’ preferred approach, and I didn’t see any reason to disagree. The solution is simple.

We write a file, build.rs, which sits in the root directory of our project (next to Cargo.toml). Cargo will compile this file before the project, and will actually execute it as part of the build process. Therefore we can write some functions to generate our lookup tables, then serialize them out to a new source file which can be imported by the main project. Magic!

As cool as this is, I don’t completely love it as a solution. It does feel a little hacky, generating a .rs file by writing strings using fs::write. It really does seem like Rust should have better support for just creating these arrays within the main project. But the result works well, and I was pleasantly surprised to see that my text editor (Sublime Text) did not complain about missing or undefined values when I referenced these static arrays from within my main project. So cargo seems to have good support for this approach, it definitely works, and now I have the compile-time generated static lookup tables I was trying to create earlier this week.

Other Happenings

Tracking down bugs, implementing simple movement controls, and playing with FPA has led to a pretty sizable refactoring of my code. It’s still messy and all over the place. But it is a little better, and I can see what I’m going to do eventually to make it “good”.

In other relevant news, I found this series of articles by Lin Clark, a developer at Mozilla, discussing WebAssembly. I found these articles to be extremely useful, even if they are quite high level. The biggest question I had was, what is the overhead of calling WASM functions from JavaScript? Surely there is some amount of setup involved in moving between the two. This does indeed seem to be true, and in the sixth article Clark mentions “trampolining”, caused by the JIT compiler’s inability to handle WASM. Apparently it’s fine if you’re handing one big task over to a WASM file and then consuming the outputs, but if you are making loads of little calls, then your application can be as much as 100 times slower!

This is good for me to know, as the way I am currently handling user inputs is by calling WASM functions in response to user key-press events in JavaScript. Maybe I will need to come up with a better solution, although for the minute the engine seems to be running quite comfortably at 60 FPS.

I’ve “borrowed” the FPS timer from the Rust and WebAssembly book’s Game of Life implementation. I’ll keep it around for as long as makes sense.

Conclusion

So that’s it for today. The engine is now interactive if you’d like to go over and play with it for a bit. It doesn’t do much, but at least there are signs of progress.

See you tomorrow folks!