Before I get into what progress I’ve made with CANINE, I’d like to start out with mentioning some stuff that I forgot about in the last post. I had learned something very important at the time, and I feel that I should spread the word so that this mistake is made less often: the C math library does not handle degrees. I had so many problems because of this, so many times, and I keep having it. The C standard math library takes and outputs radians. It’s not that its hard to convert from one or the other, degrees to radians is
d*M_PI/180 while radians to degrees is
d*180/M_PI, it’s just that the math books I’ve grown up on always handled degrees and rarely even mentioned radians. Turns out that’s pretty lame, because I’m constantly encountering radians in the word of applied mathematics. Yet again, OpenGL runs with degrees. What’s up with that?
The only other thing I think is worth mentioning is how to convert from Vandevenne’s direction vectors into an angle.
atan2(player_direction_y, player_direction_x) gives it to you in radians; take special note that
y comes first! Also, it’s useful to execute
gluPerspective(field_of_view_angle, display_width/display_height, 0.2, longest_dimension_in_level) on the projection matrix when rendering the 3-D objects. Vandevenne’s raycaster runs at a field of view angle of 66 degrees — and OpenGL, as I’ve said, does take degrees — and the longest level dimension is used to prevent parts of the game from being clipped by OpenGL’s z-buffer.
Now, back to the present.
It’s taken me a week to figure out how to, but I’ve finally got the sprites to render. In OpenGL terminology they’d be called “billboards,” polygons that always face you, like in Wolfenstein. All of the tutorials I found through Google failed and confused me. At one point I just grabbed Wolfenstein iOS’s source code to see how they did it, and I tried to implement the same technique. It didn’t work…at all. My engine’s implementation seems to be largely incompatible with theirs; not even our coordinate systems are compatible. (Mine’s better, by the way. =P)
Today, I deleted all of the billboard code that I had and started from scratch, clear-headed and focused. Guess what, I figured it out in half an hour. *facepalm*
The first thing I did was just trying to get the sprites to render as northern walls so that I could see them. They rendered all right, but in the wrong coordinates. *sigh* I forgot that my coordinate system is not 100% compatible with OpenGL’s. In order to convert from mine over I have to do
-map_width+y. Goody, now I have sprites in the right locations, sort of. As supposed to being in the middle of a tile like the should they’re aligned to the northern-most Y axis and they don’t even rotate.
This turned out to be a simple problem to solve. First off, centering it was as simple as adding 0.5 to the X coordinates. Next, Vandevenne’s usage of vectors for the player location made rotating it towards the player easy, and it’s even cleaner then Wolfenstein’s — probably faster, too! As opposed to dealing with sines and cosines, the polygon coordinates are as simple as:
x1 = x + (1 - player_direction_x) / 2;
y1 = y - 0.5 + player_direction_x / 2;
x2 = x + 1 - (1 - player_direction_y) / 2;
y2 = y - 0.5 - player_direction_x / 2;
Ka-bam! I’ve now implemented a completely functional billboard sprite system. Ah…it feels good. My modification of Vandevenne’s raycaster also let me cull out the invisible sprites by checking if they were standing on visible tiles. Satisfying.
Now for the YouTube-hosted video example. You might notice the walls have a brown edge at the top. I added those to make sure that they were rendering right-side up, and for some reason felt the reason to keep them for this video. Without further ado…
Argh, wait! Just as I started preparing the video I found a problem: in a ring of sprites, at certain angles some of them will only render part of themselves. It seems to be a problem with the transparent border around the other sprites or some such. A quick Google says that I might have to sort them and draw them in order, but I’ll save that for next time. I’ll still show you the video, though. Enjoy!