Moments of Inertia by Rachel Crawford

About     Archive     Categories     Tags     Feed     Projects     Magewinds     Warcry Card Creator    

Box2D Raycasting Engine Progress

I’ve been working on an old-fashioned raycast-rendering system that uses Box2D’s b2World::RayCast method to draw the world instead of casting rays against a grid the way Wolfenstein 3D does it.

Where I left off I’d just managed to get a limited generic system up and running. Every fixture (shape) in the b2World was rendered as a wall. Nothing could be partially transparent, nothing could appear behind anything else, there was no support for differently-coloured walls, and there were no sprites. In the intervening time I’ve enabled these capabilities.

Read more...

Raycasting in Box2D

Box2D debug draw output Raycast-render function output

In this case, ‘raycasting’ refers to an old-school rendering algorithm used in early ‘pseudo-3D’ games such as Wolfenstein 3D. This tutorial provides a good overview of how it’s normally implemented in its simplest form: for each column of pixels on the screen. The world is represented as a 2D grid of integers in which the number 0 is empty space and anything else is a wall. Each ray iterates over the grid until it intersects a wall, whereupon you use the distance from the camera to the wall to draw a vertical line of pixels on the screen. Simple! Then you can add more on top, like texturing the walls and floor, ‘sprites’ which aren’t on the grid and always face the camera, etc.

Grid-based raycasting example from 2015.

(Reminder that I tend to add mouse-over text to my images.)

What if you want the freedom to have walls that aren’t grid-aligned, though? It’s easy enough to write functions which test for intersection between line segments (rays) and arbitrary polygons and circles, but when the number of objects in your world grows large, unless you want to raycast against every object in your scene hundreds of times each frame, you’re going to want to sort those objects into some kind of spatial partition. This will take a fair bit of your time, energy and sanity.

The good news is that Box2D already sorts every fixture (shape) in its world into a spatial partition. This is great because it saves us the effort of doing so, and gives us access to all the other cool stuff Box2D does. The b2World::RayCast function is fast and easy to use - so why not try using it to render the Box2D world from a first-person perspective?

Download the demo program (Windows only) from here. Controls are in the readme that should be included in the .zip or on the readme on the front page of the GitHub repo where you can view all the source code.

Next I’m going to add sprites. I think I’ve figured out how to do it in my head and just need to put my thoughts into code. The nice thing is that I should be able to render sprites in the same pass as I render the walls – in my old grid-based raycaster the walls are rendered and the sprites are handled afterwards. On the other hand, to handle partially-transparent sprites (and walls) I’ll have to continue rays beyond their first intersection-point, which complicates things somewhat.

Texturing the walls is going to take more time to solve. On a grid it’s easy to figure out how far along the wall the ray intersection-point is, here not so much. I’m going to be doing a lot of head-scratching, and I fear the solution I come up with in the end will be sub-optimal. Won’t know until I try, though!

The images below demonstrate the difference made by calculating the ray direction and intersection-point distance in different ways. If I were going to explain this here I’d want to use some diagrams. Maybe later, huh?

Further reading:

The 108th issue of Computer Gaming World from July 1993, featuring this quote about the 7th Game Developer’s Conference, is pretty cool to read:

Batman V Superman

BATMAN: Stop it, Superman!
SUPERMAN: Stop what, Batman?
BATMAN: Antagonizing me!
SUPERMAN: In what way have I been antagonizing you?
BATMAN: Ever since we moved in together you’ve been passive-aggressively eating my groceries, leaving dishes in the sink, not taking the rubbish out, and more. You know I can’t stand mess! You must be doing it on purpose.
SUPERMAN: I’m too busy to do chores! I have to be out there, all the time, using my superpowers to save people. If you had superpowers, maybe you’d understand!
BATMAN: This time you’ve crossed the line! How dare you. Maybe if you didn’t have superpowers you’d have a little bit of perspective. I had to become a superhero. You just had it all handed to you on a plate!
SUPERMAN: Oh, unlike your family’s seemingly-infinite wealth?
BATMAN: My parents died!
SUPERMAN: My parents died, too!
BATMAN: …I guess we’re not so different after all.
SUPERMAN: Batman. Let’s make up and put this behind us.
BATMAN: Agreed. Best of friends, forever.
THE JOKER: Hello boys!
BATMAN: Joker! What happened to your face?
JOKER: Do you like it? Hmm? I thought you would, Batsy. But what about you, “Super Man”? Do I look… a little familiar?
SUPERMAN: Lex Luthor! You look like Lex Luther! How is this possible?
JOKER: Instead of leaving you to ponder this mystery I’m going to immediately give it all away! I injected Lexy’s DNA into my face and BLAM! New face, new me, newly-found villainous outlook on life, and a wonderfully eeevil scheme to take over the world and destroy you both!
SUPERMAN: Look out, Batman, he’s got a weapon that exploits your only weakness that the writer doesn’t read enough comics to know about!
BATMAN: …Kryptonite?
JOKER: Time to die, boys!
SUPERMAN: Laser eyes attack! PEW!
JOKER: Oh ho ho, you think that will work on me now, Supes? Don’t you remember that Lex Luthor’s DNA is immune to lasers?
SUPERMAN: Quick, Batman, use your large bank account!
BATMAN: The Joker can’t be bribed. He just burns all the money I send him.
SUPERMAN: There’s no way to stop him, then!
BOTH: Oh no!
JOKER: Ha ha ha!
BATMAN: Superman…
SUPERMAN: Batman…
BOTH: I love you.
WONDER WOMAN: Hello, I am here now as you saw in the trailers. Power pose!
JOKER: What?! A female? Is this some kind of SJW plot?
WONDER WOMAN: I use my special move, ‘Pop-Feminism’!
JOKER: I’m melting for some reason!
WONDER WOMAN: Goodbye, Joker. I guess you could say that this time it is you who has been joked.
JOKER: Argh!
BATMAN & SUPERMAN: Thanks, Wonder Woman! We thought that by combining our powers of Super and Bats we could take on any challenge, but in the end it turned out we were missing the most important power of all: Wonder!
WONDER WOMAN: And how!
  Wonder Woman turns to the camera with her mouth open. Hundreds of DC-universe characters pour out.
WONDER WOMAN: Feeling teased, nerds?

THE END

Tables, huh?

Oblivion

Beneath the Great Oak of Chorrol I approach member of the town watch. Apart from his Chorrol uniform, he is an exact copy of every other guardsman in the game. The gruff stare. The podgy face. The stubble. He tells me he is on duty but doesn’t stop me from launching into conversation - I suppose he’s aware that while I’m talking to him, everything else in the world, including lawbreakers, is frozen.

The conversation goes like this: I boast about some feat I’ve accomplished, then I admire his few positive features, then I crack a stinking joke, then I wrap up by attempting to coerce him into liking me more. Then I do it all again. I am speaking at such breakneck speed that he is barely able to respond before the next phrase is blasted from my mouth. From moment to moment his disposition towards me varies wildly, as I alternately offend and impress him.

At the back of my mind I wonder whether this counts as NPC torture. At the front of my mind I continue clicking away at the conversation wheel. You see, this is how I get better at talking to people.

Read more...