
Build your own old-school 3D shooter in a weekend - lobo42
https://github.com/ssloy/tinyraycaster
======
throwaway2016a
I think leaving the "old-school" out of the title doesn't do this justice.

My first thought was, with modern engines, or even raw OpenGL that isn't that
hard... I did it in a weekend for my "Advanced Computer Graphics" elective in
college using OpenGL and that was 2008. But this is kind of cool... it's more
of a tiny ray tracer and... well to borrow the title... old-school arcade
game.

~~~
3chelon
> it's more of a tiny ray tracer

It's a ray caster, where the rays are sent out from the camera to intersect
the map. With ray tracers, the rays are sent out from the light source, IIRC.

Your point on OpenGL is valid, but that just removes all the learning from it.
OpenGL does so much of the grunt work for you. This kind of old-school game
engine is a great learning experience.

~~~
outworlder
> With ray tracers, the rays are sent out from the light source, IIRC.

Are there _any_ implementations which send rays from the light source(aka.
forward ray tracing)? This is astoundingly inefficient, as most rays will not
intersect the camera.

I've never seen one, other than in brief academic discussions. What you can
use forward ray tracing for is to compute shadows.

~~~
Sohcahtoa82
I had considered making a ray tracer that worked that way, but with the slight
difference that rays didn't have to hit the camera, but would just have to hit
a point within line of sight of the camera. Obviously there would be massive
gaps between pixels, but I would fill it in with a Voronoi diagram [0], or
perhaps shaded with Delaunay Triangulation [1]. This renderer would be nothing
more than a toy or proof-of-concept, and not intended for real usage.

The classic FOSS ray tracer, POV-Ray, can actually do this. You can define a
light and define an object, and it will shoot rays from the light to the
object and trace each ray through refraction and reflection. With this, you
can simulate the way ripples in a pool concentrate light on the floor of the
pool [2] or bending and refracting [3], without manually calculating it and
adding extra light sources.

[0]
[https://en.wikipedia.org/wiki/Voronoi_diagram](https://en.wikipedia.org/wiki/Voronoi_diagram)

[1]
[https://en.wikipedia.org/wiki/Delaunay_triangulation](https://en.wikipedia.org/wiki/Delaunay_triangulation)

[2]
[http://www.antoniosiber.org/bruno_pauns_caustic_en.html](http://www.antoniosiber.org/bruno_pauns_caustic_en.html)

[3]
[http://www.povray.org/documentation/view/3.6.2/424/](http://www.povray.org/documentation/view/3.6.2/424/)

~~~
Arelius
Yeah, there are multiple techniques that do this sort of thing. Photon Mapping
and bidirectional path tracing are on ends of the spectrum

------
simias
The readme mentions it but I think it's worth pointing out that this is a very
particular (and quite dated) method for sort-of-3D rendering. It's the same
type of engine used in the original Wolfenstein.

It's definitely a lot of fun to implement (and I recommend trying if you've
never done it before) but it's very different and much more limited than what
we expect from a 3D engine nowadays.

~~~
msla
> the original Wolfenstein.

Well, the original Wolfenstein 3D, the third game in the series.

[https://en.wikipedia.org/wiki/Castle_Wolfenstein](https://en.wikipedia.org/wiki/Castle_Wolfenstein)

[https://en.wikipedia.org/wiki/Beyond_Castle_Wolfenstein](https://en.wikipedia.org/wiki/Beyond_Castle_Wolfenstein)

~~~
simias
Uh, I had never heard about these games before. I always thought Id created
the franchise. Thank you for that bit of videogame history.

~~~
msla
The first two games were top-down 2D stealth games. The third was a pseudo-3D
FPS. Most people picked up the series at the third installment, and the third
installment is what made it into history books as the First Popular FPS,
ignoring earlier FPSes which were Not Popular.

~~~
cwyers
To be clear, Castle Wolfenstein and its sequel were written by Silas Warner
and published by Muse Software, which went out of business in 1987 after going
through Chapter 7 bankruptcy. Because the trademark was lapsed, Id was able to
use the name for their game. But it wasn't a continuation of the original
games, more like a reboot by another team and publisher.

------
halfnibble
People are saying this is a "quite dated" method for creating a 3D game. Does
anyone have a tutorial on creating a 3D game in one weekend (or even 1 day?)
using modern tooling? It'd be cool to make a token 3D game with the kids. I'm
curious myself.

~~~
AnIdiotOnTheNet
This kind of engine is great as a starting place for programmers, I think, but
Unity is probably what you want for the kind of thing you're doing. There's
also Godot if you want to stay in Open Source land, but it probably isn't as
good and certainly doesn't have the same level of coverage in tutorials and
documentation.

Or there's the time-tested path to gamedev: modding existing games.

~~~
manyxcxi
Serious question: what games would you fine folks recommend to get my kids
started with modding? The oldest loves Minecraft, Zelda BoTW, and Smash Bros
on the switch.

I’ve built a Raspberry Pi Retropie NES clone and they’re all over super
bomberman, and old school Pokémon.

The last game I modded was OpenTTD before my kids were born.

~~~
gradys
Minecraft is the easiest to mod of those by far.

------
AnIdiotOnTheNet
I believe the sprites used in the video are taken directly from Andre
LaMothe's original Tricks of the Game Programming Gurus. I still have a copy.

~~~
jbverschoor
That was an awesome book

~~~
AnIdiotOnTheNet
Only programming book I ever read cover-to-cover.

~~~
gorb314
Oh yes! Good times! I still have my copy somewhere.

------
tombert
I need to dig up the code, but over the course of a week on the train rides to
and from work, I built a very simple ray-caster in Pico-8 on the Pocket Chip.
It was especially fun since I had figured out the math for it on my own
(which, in fairness, isn't terribly complex with even a high-school
understanding of Trigonometry).

I had enough fun with it that I think it might become my new "trying out a new
programming language" test, since it was easy enough to get done quickly, but
difficult enough to where I had to actually _learn_ the language.

------
Tempest1981
I'd kill for a dozen comments, esp. if a goal is to educate students. 498
lines would still be impressive.

~~~
robterrell
It's a neat trick of projection, and really easy to hack on and extend
yourself once you know the trick. Using your map of the space, cast a ray from
the camera position through every column of the display rectangle; using the
distance the ray travelled before intersecting the wall, you can calculate the
apparent height of the wall seen in that column of the display; so, in that
column, draw the wall that high. You can get fancier with textures for the
walls, varying the floor height, walls that can appear and disappear (i.e.
"doors"), and so on.

Better than my 10-second explanation:
[https://lodev.org/cgtutor/raycasting.html](https://lodev.org/cgtutor/raycasting.html)

~~~
AnIdiotOnTheNet
Note that the site has several more entries with extensions to that base
raycaster, which you can find in the index.

Interesting note about this technique: you get perspective correct texturing
for free. "Real" 3D rendering usually had to cope with affine texturing due to
performance costs until dedicated hardware for it came along.

------
csours
Ok, now I see why the headline was changed before. Having the words "school"
and "shooter" both in a headline really changes the mood.

~~~
porphyrogene
This reaching for controversy is absurd.

------
n-gauge
Here's a html / javascript version of simular:

[https://htmlgames.github.io/htmlgames/differences/gallery/in...](https://htmlgames.github.io/htmlgames/differences/gallery/index.html)

type something like lego into the search query and it renders pictures of lego
in the maze as well.

------
3chelon
Wow, this reminds me of writing a very similar engine in the mid 90s after
learning about ray-casting (and playing Doom of course). There was a very good
book which covered the whole process called "Tricks of the Game Programming
Gurus", which I would have killed for at the time!

------
dormando
I did most of one of these on an FPGA in verilog for fun:
[https://github.com/dormando/verilog-
raycaster](https://github.com/dormando/verilog-raycaster) \- took a _lot_
longer than a weekend :)

------
pan69
This is a great ray casting tutorial to get started:

[https://permadi.com/1996/05/ray-casting-tutorial-table-of-
co...](https://permadi.com/1996/05/ray-casting-tutorial-table-of-contents/)

------
glouwbug
I started something similar 2 years ago and I'm now actively pushing for a
release date 1-2 years from now.

[https://github.com/glouw/andvaranaut](https://github.com/glouw/andvaranaut)

------
rasz
Here is another Ray casting wold3d like tutorial :
[https://github.com/permadi-com/ray-
cast/tree/master/](https://github.com/permadi-com/ray-cast/tree/master/)

It has real legacy, was created in 1996! [https://permadi.com/1996/05/ray-
casting-tutorial-table-of-co...](https://permadi.com/1996/05/ray-casting-
tutorial-table-of-contents/)

------
thinkersilver
I remember writing this for my GCSE computer project in C. It didn't take me a
weekend though back then. This is a Wolf3D style game. It would be interesting
to illustrate the Doom engine that followed with the diagonal walls and
lighting effect.

I looked at this after doing GCSe project, finding it to hard and skipping to
a real 3D engine like quake because it was conceptually easier.

------
wgj
Maybe it's old hat for everyone else, but this is my first time looking at
Gitpod. (Link at the bottom of the project Readme.)

------
AppleCorp
There was a great 3D framework called Cocos3D that had a bunch of PowerVR
tools for working with 3D mobile development.

They had an example app that was a FPS made from scratch. The HUD was there,
enemies, weapons, environment.

There might be a Metal FPS base game available on GitHub, I can't remember
what it was called.

------
tibbon
I've been wanting to write a raycaster, as I've never done it before. Might
try doing it in a "slow" language like Ruby that I'm better at at first, and
then try it in C. I kinda suck at C these days, but it would be a good
transition into it again.

------
cabaalis
I'm way out of practice with C++. (It's been since like 2006.) Framebuffer
clear function appears to allocate a new vector.

Does std::vector automatically handle the memory releases? This is called
every frame, so I wanted to check here to see if I'm crazy or not.

~~~
dragontamer
> Does std::vector automatically handle the memory releases?

Yes. What is going on here is that "img" is being assigned. The "old vector"
will have its destructor called, which will call the destructor of all of its
elements by default.

\-------

I assume you're talking about this code:
[https://github.com/ssloy/tinyraycaster/blob/master/framebuff...](https://github.com/ssloy/tinyraycaster/blob/master/framebuffer.cpp)

    
    
        void FrameBuffer::clear(const uint32_t color) {
            img = std::vector<uint32_t>(w*h, color);
        }
    

Which seems inefficient to me. But it is correct code, even if it is
inefficient. There's no memory leak here, but the code probably would be way
more efficient if it were instead a simple memset.

    
    
        memset(&img[0], color, w*h*sizeof(uint32_t));
    

This memset is likely easier to understand, since it doesn't rely upon
destructors / constructors / assignment C++ Magic. And its more efficient to
boot. Vectors are guaranteed to be contiguous in memory, which is why it is
compatible with memset.

EDIT: Hmmm... the img is never initialized. You'd also have to do "img =
std::vector<uint32_t>(w*h, color);" somewhere.

\----------

The rectangle is also inefficient.

    
    
        for (size_t i=0; i<rect_w; i++) {
            for (size_t j=0; j<rect_h; j++) {
    

If i and j were reversed, the draw rectangle function would be more efficient.
As it is, "j" iterates in the wrong direction with regards to cache lines...

    
    
        // This would be faster!
        for (size_t j=0; j<rect_h; j++) {
            for (size_t i=0; i<rect_w; i++) {
    

Overall though, efficiency isn't a goal at all. Its designend to be a quickie
project to get things done as soon as possible. Thinking about all of these
details slows down development, so there's something to be said about "just
getting it done"

~~~
saagarjha
Instead of doing a memset, I'd recommend using std::fill (which will likely
call memset or another fast implementation behind the scenes): it makes it
clear what you are doing, and preempts questions of "is this legal to do"
(which it is, but only for POD data types).

~~~
marcianx
I'm far more inclined toward

    
    
      img.assign(w*h, color);
    

myself.

~~~
saagarjha
Normally I choose the methods in <algorithm> because they take an
ExecutionPolicy parameter, allowing me to make this code parallel if I wish,
but both are valid.

------
lizardwalk5
that title does not sound right. could old-school be removed? I feel like
"school" and "shooter" are somewhat misleading and potentially alarming
together. could it be something like build your own 3d shooter game? or does
this refer to first person shooter? I did not read the entire article so take
it with a grain of salt.

------
JustSomeNobody
I love his "tiny" repositories. So cool.

~~~
burk96
I know right? ssloy is on fire, one of the few non-organizations I follow on
Github. Does anyone else know some similar users that should get some more
love?

~~~
_dd_
I think this repo is nice to
[https://github.com/petershirley/raytracinginoneweekend](https://github.com/petershirley/raytracinginoneweekend)

------
atum47
That's really cool. I can't tell you how many times I started to make one and
stopped half way...

------
ddeokbokki
Thousands of french millenials getting hit by the nostalgia feels as they read
through the README.

------
jimnotgym
I know there is a performance issue, but does anyone know of any resources to
get a basic 3d shooter working in Python? It's just that my kids already know
some Python...

------
newshorts
Had to reread that headline a couple times...

------
yashksagar
i almost read that title wrong with the words School and Shooter in them

------
anigbrowl
While surely unintentional this headline is in incredibly poor taste.

------
markstos
Announcement oddly timed with the anniversary of the Parkland shooting.

~~~
oarabbus_
I hate to be morbid but it's not exactly difficult for any announcement to
coincide with the anniversary of a shooting.

------
tezza
Unity give away a complete 6DOF FPS with multiplayer.

All source and assets included

[https://unity.com/fps-sample](https://unity.com/fps-sample)

~~~
msla
Sometimes you want to make chili from scratch instead of going out to eat
Peking duck.

~~~
pjmlp
Yeah, but the recipe isn't the same as when the conquistadores discovered
America.

