This project consists of raycasting demos built in JavaScript. The vector based example is a port of Lode Vandevenne's C++ raycaster to JavaScript/HTML5: Live Demo.
I've also included a euclidean angles example and a debugging version showing the overhead 2D view along side the rendered raycaster. These are meant to serve as a jumping off point for you to build a Wolfenstein 3D style raycasting game in the browser, or to learn about how raycasters work. In my opinion, the modern browser is a fantastic medium for this.
![rc1](https://private-user-images.githubusercontent.com/141867962/276059707-76cc2bf1-64bf-4e83-9025-2b43de7245d6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjU2MDE5ODQsIm5iZiI6MTcyNTYwMTY4NCwicGF0aCI6Ii8xNDE4Njc5NjIvMjc2MDU5NzA3LTc2Y2MyYmYxLTY0YmYtNGU4My05MDI1LTJiNDNkZTcyNDVkNi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwOTA2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDkwNlQwNTQ4MDRaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00NzQ0ZmY4NTNmNTRhMDJlZDE3OWYxZGU3NmU3YWJiODQ0NDJlYmI4ZWRkZmNjZTkzMTQ4NDgyNDMyMmM5ZDlhJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.wHuSMoggNrrdZ1DIvpCqsMmVFZN1jTi6eAF_L3pBke0)
I've set the maps to the same layout in each approach for comparison. All demos should look nearly identical when rendered. The vectors-based version uses less code and is a good choice for building off of, while the euclidean example uses angles intuitively and works in a similar way to many other raycasters.
By "euclidean" it is simply meant that we are using a player angle, field of view (fov) and iterating through that fov at different ray angles calcuated based on the player angle, fov and current ray number. We then use a series of trigonometric calculations to cast rays and determine the ultimate line height for each ray. This version uses one of the most common techniques for raycasting and is relatively intuitive when programming game logic by thinking in terms of the player's xy position and angle. Like other examples that use this technique, "fisheye" correction is needed before rendering, though this only amounts to multiplying the calculated distance by the cosine of the playerAngle - rayAngle.
This version primarily uses vectors in XY space rather than doing a series of trigonometric calculations. Though initially thinking in terms of fov and player angle can be intuitive, ultimately the same calculations can be accomplished more efficiently and with less code using a vector based approach. This version is ported from Lode Vandevenne's C++ tutorial into a JavaScript version. See his excellent tutorial here: https://lodev.org/cgtutor/raycasting.html
It can both be informative in learning about how raycasters work, as well as extremely useful for debugging to see the overhead 2D view that the raycaster builds it's semi 3D graphics from. I've included a debugging version here to show the two side-by-side. This can be very helpful for designing levels and testing. Because more rendering is needed to show both, you'll probably want to run this at a lower frame rate which can easily be changed in the section toward the bottom of the code by changing the value of the FPS variable.
![rc1](https://private-user-images.githubusercontent.com/141867962/276060046-8fd4b4ab-d9ae-4c8c-a518-27ea0091f56f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjU2MDE5ODQsIm5iZiI6MTcyNTYwMTY4NCwicGF0aCI6Ii8xNDE4Njc5NjIvMjc2MDYwMDQ2LThmZDRiNGFiLWQ5YWUtNGM4Yy1hNTE4LTI3ZWEwMDkxZjU2Zi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwOTA2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDkwNlQwNTQ4MDRaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lNmViM2M4YTQ1ZDBkOWUzOWI4YTRjMjEyZjY4YjdiN2NjYTNkMDVlMTZlNzU4ZjkxOGUxY2IxNGQ1MDU1ZDVmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.gqCddabj0RRLWY3waIcCj9FC9uQGZmzlfOe-_03mkxY)
These demos are meant as a jumping off point and include single color walls with some basic lighting. Using textured walls like in Wolfenstein 3D and other famous raycasters is fairly straightforward, as is creating ceilings and floors. For this, I'll point you to Lode Vandevenne's fantastic tutorial:
Adding Textures: https://lodev.org/cgtutor/raycasting.html#Textured_Raycaster
Floors and Ceilings: https://lodev.org/cgtutor/raycasting2.html
![rc4](https://private-user-images.githubusercontent.com/141867962/276060091-5ee239bf-d361-47d1-85b5-18fe368b7897.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjU2MDE5ODQsIm5iZiI6MTcyNTYwMTY4NCwicGF0aCI6Ii8xNDE4Njc5NjIvMjc2MDYwMDkxLTVlZTIzOWJmLWQzNjEtNDdkMS04NWI1LTE4ZmUzNjhiNzg5Ny5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwOTA2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDkwNlQwNTQ4MDRaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1hZjc2Njg1ZDQ5ZDY3MGEyNjJjZDY3MjIzNTZiYTRkMWE2NjBhZGY3NzdhNWFlMzg1YjMzNTQwMzc0YTg4OGQ1JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.GGNTiFQ7RlwyB2epvgwAwCbzuKngjPXvNNU-0E6U1TI)
Sprites representing items and enemies can easily be added as well. Items/weapons can often be rendered as a simple overlay after walls have been rendered. For some really nice Wolfenstein-style sprites to play around with, checkout these sprites from a GZDoom mod by user itsmeveronica: https://www.moddb.com/mods/volkograd-3d/images/makarov-reload-animation#imagebox. You can right-click and save the images, and then load them into the canvas. For details on code implementation, see this tutorial: https://lodev.org/cgtutor/raycasting3.html
Raycasters use a semi-3D graphics technique that takes advantage of the fact that there is no vertical movement or angling to greatly simplify the math and allow for level and game design strategies similar to 2D games while producing 3D looking graphics.
It is also possible to build full 3D graphics engines in JavaScript using software rendering where you explicitly calculate the 3D transformations and 3D→2D projections in the JavaScript code.
Of course, you can always create more advanced and modern graphics by using GPU-accelerated 3D rendering as many HTML5 3D libraries do. But spending some time to learn how 3D graphics work with software rendering can improve your understanding and allow you to create 3D scenes and games on systems that have no native 3D hardware. For a very simple example of 3D software rendering in JavaScript, see this Wireframe Demo (and the Code) which draws SVG polygons to the DOM to produce a rotating 3D cube.