Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

3D Raycasting Engine Problems

3 views
Skip to first unread message

Brent P. Newhall

unread,
Feb 4, 1997, 3:00:00 AM2/4/97
to

Hello, all! I thought I'd try my own raycasting engine from scratch
(nothing against Peter Cooper; I just think I'll learn more about it and
about optimizing it if I try to make one clean).

Anyway, I've got a simple grid-based level, but the player's position is
described with Cartesian coordinates *and an angle*. Each "ray" in the
raycasting takes that angle, and increments a radius variable in a
loop. The radius and angle are taken as polar coordinates and converted
to Cartesian, then that Cartesian position is checked to see if there's
a wall there.

Only problem is, it doesn't work. %-( I keep getting weird ending radii
for the rays and what's displayed on the screen looks like garbage. I
know I'm overlooking something childishly simple; could someone please
point me in the right direction? The code is below. Thanks very much!

And yes, it's written in QBASIC. :-) And no, there are no line-length
problems in the post, either.

Oh, incidentally, my plan for this code is a thinking-man's RPG. ;-)
Rather than focus on body count, this game will focus on puzzle-solving
(i.e., conversations, quests, etc.). If you've ever read "The Lord of
the Rings", then this is more like following Gandalf than following
Aragorn, if you know what I mean. Of course, nothing may come of this
at all based on how far I get with this code, but we'll see. :-)

Thanks again,

Brent P. Newhall
----------------------------------------------------------------
"No matter how brilliant a man may be, he will never engender
confidence in his subordinates and associates if he lacks simple
honesty and moral courage." -- J. Lawton Collins

---------- BEGIN CODE ----------
' Simple 3D Raycasting Program
' (Eventually an RPG, I hope)
' by Brent P. Newhall (Bre...@juno.com)
' Version 0.1.0

DEFINT A-Z
DIM level(1 TO 50, 1 TO 50) AS INTEGER
FOR wall = 1 TO 50 ' Create a wall around the level
level(1, wall) = 1
level(50, wall) = 1
level(wall, 1) = 1
level(wall, 50) = 1
NEXT wall
level(4, 3) = 2 ' Create another quickie wall for interest

quit = 0
PlayerAngle = 0
PlayerX = 15
PlayerY = 15

SCREEN 13

GOSUB DrawMainWindow
DO
GOSUB DoInput
LOOP UNTIL quit > 0
END

DoInput:
DO: i$ = INKEY$: LOOP UNTIL i$ <> "" ' Pause for input
IF i$ = CHR$(0) + "M" THEN ' [RIGHT]
PlayerAngle = PlayerAngle + 5
IF PlayerAngle > 360 THEN PlayerAngle = PlayerAngle - 360
GOSUB DrawMainWindow
ELSEIF i$ = CHR$(0) + "K" THEN ' [LEFT]
PlayerAngle = PlayerAngle - 5
IF PlayerAngle < 0 THEN PlayerAngle = PlayerAngle + 360
GOSUB DrawMainWindow
ELSEIF i$ = CHR$(27) THEN ' [ESC]
quit = 1
END IF
RETURN

DrawMainWindow:
LINE (0, 0)-(319, 199), 0, BF ' Clear screen fast
col = 0 ' Start at left-hand side of screen
FOR angle = PlayerAngle - 20 TO PlayerAngle + 20 STEP 2
hit = 0 ' Do a sweep from 20 to the left over to 20 to the right
radius = 0
WHILE hit = 0 AND radius < 195 ' Cast out ray
radius = radius + 1 ' \/ From polar to Cartesian coordinates
tempx! = radius * COS(angle) + PlayerX ' X posit
tempy! = radius * SIN(angle) + PlayerY ' Y posit
' I think my problem is centered around the code above;
' I don't think the converted polar coordinates are
' being normalized to level coordinates correctly.
hit = level(tempx! / 10, tempy! / 10) ' Have we hit a wall?
' (modified to fit in level)
'LOCATE 1, 20: PRINT tempx!;
'LOCATE 2, 20: PRINT tempy!;
'DO: LOOP UNTIL INKEY$ <> ""
WEND
row1 = radius / 2 ' For display
row2 = 199 - radius / 2 ' ditto
LINE (col, row1)-(col + 4, row2), hit, BF ' Draw this section
col = col + 5 ' Advance placeholder
'LOCATE 1, 30: PRINT radius;
'DO: LOOP UNTIL INKEY$ <> ""
NEXT angle
LOCATE 25, 10: PRINT PlayerAngle;
RETURN

Andrew L. Ayers

unread,
Feb 4, 1997, 3:00:00 AM2/4/97
to Brent P. Newhall

Brent P. Newhall wrote:
>
> Hello, all! I thought I'd try my own raycasting engine from scratch
> (nothing against Peter Cooper; I just think I'll learn more about it and
> about optimizing it if I try to make one clean).
>
> Anyway, I've got a simple grid-based level, but the player's position is
> described with Cartesian coordinates *and an angle*. Each "ray" in the
> raycasting takes that angle, and increments a radius variable in a
> loop. The radius and angle are taken as polar coordinates and converted
> to Cartesian, then that Cartesian position is checked to see if there's
> a wall there.
>
> Only problem is, it doesn't work. %-( I keep getting weird ending radii
> for the rays and what's displayed on the screen looks like garbage. I
> know I'm overlooking something childishly simple; could someone please
> point me in the right direction? The code is below. Thanks very much!

Simple ray casters work like this - a grid is developed, and stuff is
put into
it (just like you are doing). You also have a view direction and an X
and Y position
for the player. Now, you need to sweep the ray out X degrees (most use
60 degrees)
centered on the viewers FOV angle. So, say the viewer is looking at a 45
degree
angle. +/- 30 degrees for the 60 Degree FOV would be from 15-75 degrees.
So, sweep
out a ray for these angles, at a step rate for the horizontal resolution
of your
viewport (say 320, or 60/320 = .1875 degrees per X pixel). Now, for each
ray cast out
you need to cast out a LONG ray, say 1024 units or longer. Use a 2^n
power for this.
Now, by knowing the start and end points of the ray, you can then
determine the inter-
section of the H and V gridlines, and step along the gridlines by the
width of the
grid (most clones use 64 units). One you have hit a wall, you know the
distance and
can render that strip accordingly. One note: the distance to the strip
must be multiple
by the cosine of the angle, otherwise you get a fisheye effect. PC
didn't do this for his
engine, but since he only deals with 60 strips (one for each angle), it
isn't noticible.
Unfortunately, resolution suffers. Go for a 320 or more strip version.
It would be
worth it in the end.

I know this description is horrible, but it gives the basics. Check out
Thomas Gohels
engine in the ABC packets (November?) - It is based off of the 'C'
engine in TOTGPG.
With QuickBASIC or PB, this engine flys...

Peter Cooper

unread,
Feb 4, 1997, 3:00:00 AM2/4/97
to

Enter 'Son of Carmack'.. :) Nah, not really :)

>Hello, all! I thought I'd try my own raycasting engine from scratch
>(nothing against Peter Cooper; I just think I'll learn more about it and
>about optimizing it if I try to make one clean).

Thats good then :) hehe I've gone through your code and I have managed
to get it working fairly well on my machine with only a few line
changes... :) I'm not giving you all the code, thats what learning is
about.. hehe

>' Simple 3D Raycasting Program
>' (Eventually an RPG, I hope)
>' by Brent P. Newhall (Bre...@juno.com)
>' Version 0.1.0

> WHILE hit = 0 AND radius < 195 ' Cast out ray


> radius = radius + 1 ' \/ From polar to Cartesian coordinates
> tempx! = radius * COS(angle) + PlayerX ' X posit
> tempy! = radius * SIN(angle) + PlayerY ' Y posit
> ' I think my problem is centered around the code above;
> ' I don't think the converted polar coordinates are
> ' being normalized to level coordinates correctly.

You're partially correct. The main problem is those lines but not
because of polar to level coordinates.. COS and SIN use _radians_
whereas you are feeding it angles in degrees... So.. change lines to:

tempx! = radius * COS(angle * 0.017453) + PlayerX ' X posit
tempy! = radius * SIN(angle * 0.017453) + PlayerY ' Y posit

Also,

> WHILE hit = 0 AND radius < 195 ' Cast out ray

In that line change the < 195 bit to < 2000 or something. It will run a
bit slower but you will at least get the wall at the other side of the
room :)

To create a _tremendous_ speedup.. change the cos and sin lines to:

tempx! = radius * (COS(angle * 0.017453)*4) + PlayerX ' X posit
tempy! = radius * (SIN(angle * 0.017453)*4) + PlayerY ' Y posit

You're being too accurate, you can get away with a bit :) If you ever
need more detail put it down to 2 or 3 :)

> row1 = radius / 2 ' For display
> row2 = 199 - radius / 2 ' ditto

The way you are scaling down the walls is interesting.. Heres a way
which I put it to which works:

row1! = 100 - (50 / radius)
row2! = 100 + (50 / radius)

The row1 and row2 factors _have_ to go to ! in this case.. :)

> LINE (col, row1)-(col + 4, row2), hit, BF ' Draw this section

And of course add in the !s here too. Now try your program, it works
well.. :)

Oh yeh, one other problem, you're only allowing it a small field of
view.. 40 degrees I think.. Try this instead..

FOR angle = PlayerAngle - 40 TO PlayerAngle + 40 STEP 2

You will probably need to increase the X column by more each time now
though.. unless you change the STEP 2 to STEP 1... (which of course will
make it slower)

Cheers,
--
Peter Cooper

Brent P. Newhall

unread,
Feb 5, 1997, 3:00:00 AM2/5/97
to

Andrew L. Ayers wrote:

>
> Brent P. Newhall wrote:
> >
> > Hello, all! I thought I'd try my own raycasting engine from scratch
> > (nothing against Peter Cooper; I just think I'll learn more about it and
> > about optimizing it if I try to make one clean).
> >

I replied to this via e-mail, but Windows Inbox doesn't tell you if a
message has been posted to a newsgroup. :-(

IAE, I guess I should have been more specific. :-) I do know how to do
a raycasting engine, I'm just having some problems with the specifics of
my code.

Won't you pleeeeeeeeeeeease pleeeease help me? ;-)

Thanks,

Brent P. Newhall

Brent P. Newhall

unread,
Feb 6, 1997, 3:00:00 AM2/6/97
to

Peter Cooper wrote:
>
> Enter 'Son of Carmack'.. :) Nah, not really :)
>
> >Hello, all! I thought I'd try my own raycasting engine from scratch
> >(nothing against Peter Cooper; I just think I'll learn more about it and
> >about optimizing it if I try to make one clean).
>
> Thats good then :) hehe I've gone through your code and I have managed
> to get it working fairly well on my machine with only a few line
> changes... :) I'm not giving you all the code, thats what learning is
> about.. hehe

[snip a lot of really good help]

THANK YOU! I'll make the changes tonight, hopefully.

I've had three people send me 3D engines to show me how it works, which
is not at all what I wanted (which you can see if you read my post!), so
I really appreciate you just plain showing me what's wrong.

Again, my deepest thanks!

Brent P. Newhall
---------------------------------------------------------------
"Whether you believe you can do a thing or not, you are right."
-- Henry Ford

0 new messages