Sprites in Raycasting
Billybob

I need to know the techniques behind rendering sprites in a raycaster(ie. badies). I'm going to look at some source code soon, but I'm posting here to see if I can get an accual explaination instead of blindly following some source code, heh.

BTW I want a technique that is flexible, speed is nice, but flexibility it cool :)

23yrold3yrold

We need a Raycasting forum ...

Well, I would just draw back to front. Make sure you keep track of the distance from the player to the "baddy" though; that way you can make sure you don't draw the enemy over a wall (you're probably already keeping track of distance to wall for every pixel column, so this is easy). Use the same system you use for walls when drawing; draw a slice at a time and make all the slices the same size so the enemy doesn't become distorted.

Should be easy enough :)

Billybob

Ok, so I just translate the center of all visible baddies and draw them, eh? But how do I know how wide to draw them, same translation? Also, will a baddie have any slant to the top/bottem of it cause it is always facing you(billboard) or does it slant. If it doesn't slant then I don't have to draw it slice by slice, just a simple blit >8)

Carrus85

Edit, um... I guess I accidently posted to the wrong post, sorry...

Billybob

Yea, I already know that translation equation like the back of my hand, heh. Good ole similar triangles

EDIT Response to your edit....Oh... EDIT

Carrus85

I'm dumb!... that post was intended for the drawing a guiding arrow post...

Korval
Quote:

We need a Raycasting forum

I've been wondering something about the prevelance of this "raycasting" technique (I really hate that name, as it sounds too much like a real rendering technique, raytracing) around here lately.

Why?

In terms of presenting a 3D world, a scan converter is, not only much better at it, but (when hardware-accelerated) faster as well. It is also more artistically free. You aren't stuck with Doom-like creations; you can make much more interesting, dynamic environments.

So, if you're interested in doing something vaguely 3-dimensional, why not go all the way?

23yrold3yrold
Quote:

In terms of presenting a 3D world, a scan converter is, not only much better at it, but (when hardware-accelerated) faster as well.

Is that the thing TH made?

Quote:

Why?

Easy and fun? ;)

Thomas Harte
Quote:

In terms of presenting a 3D world, a scan converter is, not only much better at it, but (when hardware-accelerated) faster as well.

As I'm sure you know already:

But a raycaster is a scan converter - it just so happens that the walls are converted to vertical rather than horizontal scanlines, which means that, per pixel, you can use affine scaling and still get correct perspective, and by thinking slightly more in trig than in linear algebra you can save several more calculations.

Quote:

Is that the thing TH made?

It was, I guess, but it was using trig. Nevertheless, everything is changing now that I've moved on to the platform I actually want to target - low end mobile phones. I've switched to a style much more like ray casting (but still with portals) which has the advantage of being very good at guessing which wall a particular ray will hit first time, and very good at guessing which wall it must have hit if not.

mbcaster.jpg

That version is not yet fully optimised.

To the original poster: is your raycaster simple Wolfenstein style, same height walls? If so what you effectively do is keep a 1d z-buffer. Keep a record of the heights of every sliver, convert your sprite to screen co-ordinates and draw (as a first implementation) sliver by sliver only where the sprite slivers are larger than the wall slivers.

aybabtu

William: In wolfenstein, doom, and just about every other raycaster, the objects aren't drawn at an angle to the viewer, you always only get the same picture! The same goes for the enemies, except they have pre-made 4 sides.

I'm at the objects step in my raycaster, too. I belive that the only thing I need to do is get the angle from the object to the player:

............................ Line from P-O is the
............................ distance from Player
........_................... to object
.........-_....O............ Line coming out from
...........-_.b.\........... player (made of 
.............-_..\.......... hyphens & underscores
...............-_.\......... ) is the players 
.................-P......... angle.
............................

I need to find angle 'b' in that picture (the angle between the object and the player. I have, the angle of the player, and the distance to the object. I must have to use the inverse of one of the trig functions...?
Otherwise, I've got scaling done! Then, when I go to draw the objects, I'll draw each vertical strip of them, then check the values in my view[320] array and only draw if there isn't a distance in that line closer to the player. That's the easy part. I just gotta get that angle!

Korval said:

(I really hate that name, as it sounds too much like a real rendering technique, raytracing)

Heeey, man...don't bash it! Come over to the dark side...the raycasted side. Leave all your "real rendering techniques" behind...::)

23, in response to raycasting critisism said:

Easy and fun? ;)

Yeah! Plus, if you like old games like DOOM and Wolfenstein 3D (I do!8-)), it's real cool to make one that looks like that! Also, it's good for a guy who's only been through geometry in school (also me!).;)::):-/;D

Thomas: That's cool!8-)

Thomas Harte
Quote:

I need to find angle 'b' in that picture (the angle between the object and the player. I have, the angle of the player, and the distance to the object. I must have to use the inverse of one of the trig functions...?

You could, if you wanted to do it the trig way, use atan2 and then subtract the angle your viewer is actually rotated at.

Alternatively, and probably more speedily, you could use some linear algebra. Use the dot product to project the vector from the viewer to the enemy into screen space, adjust that for your FOV (multiply x by z multiplied by some scalar) then do a standard issue perspective transformation.

Quote:

Thomas: That's cool!

You can get a full Doom port for the Nokia series 60 line with bilinear filtering... but we don't all want one of those ugly things.

aybabtu

I'm making some headway (very little) over on my other thread:P (Getting an angle...sorry...)...I've got the angle, (I think!), and now I need to draw the sprite!

Carrus85

True, 3d hardware has come a long way in increasing the speed at which you can draw 3d objects, but it also came for a price: complexity. No offense, but open-gl really bugs me because you have to enter like 35 lines of code to make one stupid triangle popup on the screen. Not only that, raycasters are more hardware independant, because they don't depend on a platform that has opengl accel.

True, they could always implement an opengl accelerated renderer that the user could choose from, I guess...

aybabtu

I tried following the "NeHe tutorials" on OpenGL, but I didn't want to type in all that code! It was like 10 billion (okay, maybe I'm exagerrating a little) pages of code! Just for the first program! I'm totally with you there, Carrus!:D

MiquelFire

Um... how much of them 35 lines are for setting up the hardware for your program (like the install_* functions in Allegro)?

aybabtu

There isn't any...it's all OpenGL and windows crap.:P::)

MiquelFire
FF8 fan said:

it's all OpenGL and windows crap

The windows crap is the same as the install_* functions in Allegro (and the set_gfx_mode() as well) ::)

aybabtu

Okay...but there's like 15 lines of it...hardly any of which (to teh WinAPI n00b) is understandable. Nyah.:P

23yrold3yrold

The Windows crap is overhead that you should be keeping on hand for whatever purpose so you don't have to retype it. NeHe hands out that base code for a reason, y'know ::)

aybabtu

What...ever...
This is too OT.

Korval
Quote:

No offense, but open-gl really bugs me because you have to enter like 35 lines of code to make one stupid triangle popup on the screen.

And how many lines does it take to write a ray-caster that is decently well-optimized? I'm pretty sure it's more than 35.

Quote:

Okay...but there's like 15 lines of it...hardly any of which (to teh WinAPI n00b) is understandable. Nyah.

You aren't supposed to understand it. Just recognize that it is required to produce a window. You copy and paste it as needed. You can use Allegro just fine without fully understand what all the initialization functions are.

Quote:

I need to know the techniques behind rendering sprites in a raycaster(ie. badies).

Stretch-blit. That's the long and short of it. You stretch-blit the sprite such that it appears to be on the ground and remains, perspective-wise, at a particular height.

X-G

Quote:

open-gl really bugs me because you have to enter like 35 lines of code to make one stupid triangle popup on the screen.

Ever tried D3D? :P
You won't get away with 35 lines - try 350. :P

aybabtu

Yes! Going along witht the original post, visit the "Getting an angle" thread, go all the way to the last post where I have done it!! With lots of help from 23yrold3yrold! I attached a screenshot.

Trezker
23 said:

We need a raycasting forum

I agree, if this keeps up...
But I think a better idea is to write a "monthly" article on the subject in pixelate.

aybabtu

Me=8-)
aybabtu eyes his sig
;D

Oooh! I have a teensy problem...it seems that my object drawing method fails for I think 180 degrees! Objects disappear! Look:
{"name":"wolf.gif","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/567fd195c6b6f49ac04e82d333248f2c.gif","w":320,"h":320,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/567fd195c6b6f49ac04e82d333248f2c"}wolf.gif
There's supposed to be 3 barrels there. The one on the far left does appear, but you have to turn a bit to the left! It should be visible in this shot, if I move about 5 degrees to the left, it shows up... WTF? ???

I know it's not the right forum:-X, but here's my code:

/*
 int odistance=distancefrom player to object
 float oangle is angle between player and object
 int odisplayx=where to draw on screen
 int obj_x,objy=object's coordinates
 */
odistance=(int)(DIV_VIEW/sqrt((obj_x<i>-px)*(obj_x<i>-px)+(obj_y<i>-py)*(obj_y<i>-py)));
   oangle=RAD_TO_DEG(atan2(obj_y<i>-py,obj_x<i>-px))-pa;
   if(oangle<0) oangle+=359;
   if(oangle>359) oangle-=359;
   odisplayx=(int)(oangle/0.1875)+(SCREEN_W/2);
   stretch_sprite(front,object[0],odisplayx-odistance/2,100-odistance/2,odistance,odistance);

Billybob

What in the world has my thread become! I'm dumb!. Uhhh, stop dis-ing OpenGL, cause that is what I'm using for my next "3D" project >8)

First off, thanks for all the help, I think what I thought was correct and what you are telling me is making me think that what I thought about being correct in thinking what I thought was good. Get that? Got that? Good.

My engine is not like Doom or Wolfenstien, it is an Advanced Raycaster much like the rex3D engine, but still a raycaster, just slightly different.

I guess I'm off to go work up some code for rendering sprites :) Thanks for the help.

-------------NEW POST-------------------------

Let me run this math by ya and make sure its good.

X is the offset of the sprite's center from the center of the screen.
P is distance to projection plane.
a is Angle between camera and sprite relative to the camera's viewing angle.

X = P * tan a

and of course I can get the height scale of the sprite via my translation function used on the walls and I can use the ratio of the translated height and the real height to figure out how wide to draw the sprite.

All that sound OK? It better be. 8-)

Thomas Harte

Quoted code:

odistance=(int)(DIV_VIEW/sqrt((obj_x<i>-px)*(obj_x<i>-px)+(obj_y<i>-py)*(obj_y<i>-py)));
oangle=RAD_TO_DEG(atan2(obj_y<i>-py,obj_x<i>-px))-pa;
if(oangle<0) oangle+=359;
if(oangle>359) oangle-=359;
odisplayx=(int)(oangle/0.1875)+(SCREEN_W/2);
stretch_sprite(front,object[0],odisplayx-odistance/2,100-odistance/2,odistance,odistance);

I have various observations. First of all, I think you actually want this:

if(oangle<0) oangle+=360;
if(oangle>359) oangle-=360;

e.g. the angle '360' is not the same as the angle '1'.

odistance=(int)(DIV_VIEW/sqrt((obj_x<i>-px)*(obj_x<i>-px)+(obj_y<i>-py)*(obj_y<i>-py)));
oangle=RAD_TO_DEG(atan2(obj_y<i>-py,obj_x<i>-px))-pa;
if(oangle<0) oangle+=360;
if(oangle>359) oangle-=360;

So, odistance is the perspective projected size of a square tile in pixels, oangle is the angle between the centre of the view and the object.

odisplayx=(int)(oangle/0.1875)+(SCREEN_W/2);

You've picked oangle to be always positive, so your objects are always on the right hand side of the screen here. It strikes me that you might instead want the following:

odistance=(int)(DIV_VIEW/sqrt((obj_x<i>-px)*(obj_x<i>-px)+(obj_y<i>-py)*(obj_y<i>-py)));
oangle=RAD_TO_DEG(atan2(obj_y<i>-py,obj_x<i>-px))-pa;
while(oangle<-180) oangle+=360;
while(oangle>=180) oangle-=360;
odisplayx=(int)(oangle/0.1875)+(SCREEN_W/2);
stretch_sprite(front,object[0],odisplayx-odistance/2,100-odistance/2,odistance,odistance);

i.e. you restrict your angle to the range [-180,179] rather than [0, 359]. You might be able to use 'if' rather than 'while', I'll let you think about that one!

Quote:

Let me run this math by ya and make sure its good.

X is the offset of the sprite's center from the center of the screen.
P is distance to projection plane.
a is Angle between camera and sprite relative to the camera's viewing angle.

X = P * tan a

I'm confused by P. If you've calculated distance from viewer to object and called this P then in your right angled triangle, you have one angle, and the hypotenuse and want to get the side opposite the angle, so you 'sin angle = opposite / hypotenuse'. Conversely if you want the side adjoining you use cos.

If you have the adjoining side, which I guess you mean is P, then yeah:

tan A = X / P
=> P * tan A = X

Although I reiterate my claim from earlier in this thread that adding objects in a trigonometric manner is silly and processor expensive.

aybabtu

Yay!;D I attached a screenshot...
Thank's Thomas!

X-G

Do you have to keep attaching .pcx files? You can't view them inline. It's annoying. At least make them .bmp ... :P

23yrold3yrold

BMP is too big. PNG/GIF is teh win!!

Thomas Fjellstrom

Use png's ;) much better on the bandwidth.

X-G

I said at least, since he's likely generating these screenshots via Allegro, which can't save gif/png without extra libs.

23yrold3yrold

Yeah, but everyone should have a program for converting BMP's to a multitude of file formats ...

X-G

In case he doesn't, I just want to express that even .bmp is better than .pcx, since .bmp can be viewed inline.

aybabtu

I do have a program, but it's 'new' and takes over a minute to load up...it's so much easier for me (:P) to do it this way...but, from now on...I'll convert them to GIFs.:)

Billybob

ewwww, CODE, I'm dumb!. Theories for me. I eat theories for breakfast, and sometimes for lunch. Well, I'm going to make my entity engine, and then I'll work on the sprite rendering code. If I run into problems with my theories then I'll check out code, heh.

EDIT
BTW, here is my theory. Use the variables as described in past post.

http://www.cljy.com/~billy/Sprite Theory.JPG

Thread #283342. Printed from Allegro.cc