As is well known Wolfenstein 3D is a 2D game, which uses simple raycasting to figure out the distance from the player to the wall's in front of her. As a small hobby project I set out to recreate this. Since my levels (like the original) are bound to a strict grid we don't actually have to do a "real" ray-caster. But can instead just calculate the distance to next tile-border the ray will pass through, and immediately jump there.
This should have been easy, but due to a number of bad missteps on my parts (mostly involving trying to decide my move based on if my angle was pointing left-right or up-down) it took way to long to figure out the proper equations.
In the end it was as simple as:
(define (find-next-wall x y a callback) (let ((dx-ampl (mod (* -1 (sgn (cos a)) (decimals x)) 1)) (dy-ampl (mod (* -1 (sgn (sin a)) (decimals y)) 1))) ;; Try moving to vertical wall (let* ((dx (* 1.01 dx-ampl (sgn (cos a)))) (dy (* dx (tan a)))) (if (<= (abs dy) dy-ampl) (callback (+ x dx) (+ y dy)) ;; if that failed, try horizontal wall instead (let* ((dy (* 1.01 dy-ampl (sgn (sin a)))) (dx (* dy (cot a)))) (callback (+ x dx) (+ y dy)))))))
Along with a trivial decimal-truncation and array reference to check if a given square contains a wall or not. The end result looks rather ok, except some fish-eye effect and bad color blending.