### Author Topic: Figuring out what's in front of you (RayCaster)  (Read 2161 times)

0 Members and 1 Guest are viewing this topic.

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Figuring out what's in front of you (RayCaster)
« on: January 18, 2015, 03:17:03 pm »
So, for my game, I'm trying to come up with a quick way to take a player's current location, and check a set distance, like say 20 units, away from them, and maybe like 10 units either direction at that distance (kind of like the field of vision), and determine what objects are in viewing range. I have a scaled sprite routine that I've figured out how to work, so now I just have to draw a tree, a house, a car, a few oil tanks, and a note. Once this bit is done, I'm ready to compile and test!

That being said, anyone any ideas? I have an 8.8 FP number for your current location and a 1-byte angle for your direction.
« Last Edit: January 27, 2015, 11:50:38 am by ACagliano »

#### Xeda112358

• they/them
• Moderator
• LV12 Extreme Poster (Next: 5000)
• Posts: 4657
• Rating: +718/-6
• Calc-u-lator, do doo doo do do do.
##### Re: Figuring out what's in front of you.
« Reply #1 on: January 18, 2015, 04:16:51 pm »
So do you have the coordinates of the objects?

#### chickendude

• Posts: 816
• Rating: +90/-1
##### Re: Figuring out what's in front of you.
« Reply #2 on: January 18, 2015, 07:08:38 pm »
This should probably be under the asm help section. If you have the coordinates of your objects, you just need to establish what your field of vision is (based on how far away they are) and check whether the coordinates fall in line.

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you.
« Reply #3 on: January 18, 2015, 07:29:50 pm »
So do you have the coordinates of the objects?

Yes, the coordinates of the objects are in a tilemap

#### shmibs

• しらす丼
• LV11 Super Veteran (Next: 3000)
• Posts: 2132
• Rating: +281/-3
• try to be ok, ok?
##### Re: Figuring out what's in front of you.
« Reply #4 on: January 18, 2015, 10:39:03 pm »
use LUTs. if you have a tilemap, it won't have to account for every single angle. just make a hash from the angle values to the shape, in tiles, it can see

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you.
« Reply #5 on: January 21, 2015, 11:44:11 am »
I hate when someone says "make a hash" lmao jk.

I really do need to get to work on this now that the static is out of the way.

I was considering looping the angle you are standing at and scanning the distance for objects, but that might be harder than some of the proposed solutions, that I don't entirely get. I may also be able to use trig functions to figure out the area that is viewable, and then check nearby objects to see if points fall in range. If this is indeed ray-casting, I have zero experience. What is the quickest way to do it?
« Last Edit: January 26, 2015, 09:33:05 am by ACagliano »

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #6 on: January 27, 2015, 11:54:57 am »
Edit: so with a little nudge, and a helpful resource, I am trying to develop my own raycasting engine, portable, and with configurable render distance (bc I'm not entirely sure what my render distance will be yet until I test). What I've have gathered so far is:

- RayStart becomes the X and Y position of the player, the "camera". Render distance is the camera plane, the farthest the routine will render to.
- You are basically following the direct line from you to the camera plane, incrementing by 1 "unit" per iteration and testing for an object.
- continue this until you hit the camera plane.

Which is great. I get that. But where does it come in where I'm going from POV-left to POV-right, not just directly in front of you? Unless I'm missing part of the explanation that talks about that.

Here's the start of what I have:

Code: [Select]
#define rayStart Op8#define rayEnd Op8+2#define renderDistance 10 ; change this to tweak render distance#define rcStack Op8+4 engine_rayCaster_Init: ld hl,smallEditCol ld (raycastStack),hl ; reset pointer to start of raycaster stack ld e,(playerPosY) ld (rayStart),e ld (rayEnd),e ; initialize player position as start and current end of ray ld d,(playerPosX) ld (rayStart+1),d ld (rayEnd+1),d ; initialize player position as start and current end of ray ld e,l ld d,h ; ray End temp (may delete ram if i can)  de = ray start, hl = ray end ld bc,(playerVectorX) push bc_rc_loop: add hl,bc ld a,l push hl multAbyWidth ; out hl ld c,b ld b,0 add hl,bc ; offset in map to get jr _rc_loop_test_rc_test_exit: pop hl call _rc_push _rc_loop_test:; yes, i know i didnt actually put in the pointer to the map data. pretend, i did that. ld a,(hl) or a jr nz,{[email protected]} pop bc jr _rc_loop@: jr _rc_test_exit _rc_push: ld de,(rcStack) ld (de),a ; map object pushed to stack inc de ld (de),hl ; object position push to stack ld hl,(rayStart) inc de inc de ld (de),hl ; your position pushed to stack (i will throw in a distance calc here, bc this is multiple data entries) inc de inc de ld (rcStack),de ret
« Last Edit: January 27, 2015, 12:50:42 pm by ACagliano »

#### Runer112

• Moderator
• LV11 Super Veteran (Next: 3000)
• Posts: 2289
• Rating: +639/-31
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #7 on: January 27, 2015, 02:10:57 pm »
You simply loop through angle values between the left edge of the field of view and the right edge. If you're raycasting for rendering purposes, the step size should usually be set such that one ray is cast for each column of pixels in the output. If you're raycasting for other purposes, it should usually be the largest value that is still small enough not to "miss" seeing objects between two rays.

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #8 on: January 27, 2015, 02:18:27 pm »
My angle is +/- 5 byte degrees. So in pseudo-code:

Code: [Select]
for (a,  from angle-5 to angle+5, 1 ) {     calc (x,y) vectors of a     figure out all points on line from player (x,y), in increments of above (x,y), till render distance     push any objects found onto a stack     }render stack

#### Runer112

• Moderator
• LV11 Super Veteran (Next: 3000)
• Posts: 2289
• Rating: +639/-31
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #9 on: January 27, 2015, 02:20:18 pm »
5 binary degrees seems like it could work to me. If not, you can just decrease it easily enough.

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #10 on: January 27, 2015, 02:22:50 pm »
Ok sounds good. Now to convert that pseudo-code into assembly... LET THE 200 PAGES OF CODE COMMENCE!!!!!!

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #11 on: January 27, 2015, 03:43:28 pm »
Update: Got a routine. Let me know if I goofed up anywhere:

The routine should create an 11-entry stack for the rendering-routine to process. Each "entry" corresponds to a section of the "screen". Entry 1 is far left, 2 is next to that, and so on. If the renderer hits a $ff, it skips that section of screen. Otherwise, it renders the masked greyscale sprite (which is based through a scale-down routine, based on distance) for that section and moves on. Feel free to correct/optimize, but let me know what I did wrong so I learn from it :p Code: [Select] #define distance tempSwapArea ; 1 byte#define rayCurrent distance+1 ; 2 bytes#define angleCurrent rayEnd+2 ; 1 byte#define angleStart angleCurrent+1 ; 1 byte#define angleStop angleStart+1 ; 1 byte#define iterVector angleStop+1 ; 2 bytes#define rcStack iterVector+2 ; 2 bytes, a pointer to the start of the raycaster object stack#define renderDistance 10 ; adjust this to change the render distance#define priorAngle rcStack+2 ; 1 byte engine_raycaster_Init: ld hl,smallEditCol ld (rcStack),hl ; reset pointer to start of raycaster stack ld a,(playerDirection) ld hl,priorAngle cp (hl) jr z,{[email protected]} ld a,b ld b,5 add a,b ld (angleStop),a ld b,-10 add a,b ld (angleStart),a@: ld a,(angleStart) ; sorry about this bit, but needs to be here for the jump to work ld (angleCurrent),a ; shouldnt be too time-consuming to do thatrc_loop_angle: call _getTempVector ld a,(playerPosX) ld h,a ld a,(playerPosY) ld l,a ld bc,(iterVector)rc_loop_ray: add hl,bc call rc_getDistance ld (distance),a ld a,l multAbyWidth ld c,h ld b,0 add hl,bc call rc_getMap ld a,(hl) or a jr z,rc_tilepush_skip; rc_tilepush: if tile is something, push this object onto rcStack, renderer will handle it ld de,(rcStack) ld (de),a ; object type Id inc de ld a,(distance) ld (de),a inc de ld (rcStack),de jr rc_skip_writeemptyrc_tiletest_skip: ld a,(distance) cp renderDistance jr z,rc_loop_angle_next jr c,rc_loop_angle_next jr rc_loop_rayrc_loop_angle_next: ld de,(rcStack) ld a,$ff ld (de),a inc de ld (rcStack),derc_skip_writeempty: ld a,(angleCurrent) inc a ld (angleCurrent),a jr rc_loop_angle rc_getTempVector:; using current angle, gets vectors. each vector is in 8.8 FP format, so we only save the .8 part; input: a = angle; output: new vectors loaded into (iterVector) word push af call calcSin ; a = angle ld (iterVector),l ; hl = 8.8 FP pop af call calcCos ld (iterVector+1),l retrc_getMap:; input: hl = offset in map; output: hl points to tile ld bc,(SlendMapPtr) add hl,bc retrc_getDistance:; input: hl = current testing location; output: a = distance from origin ret
« Last Edit: January 28, 2015, 09:25:10 am by ACagliano »

#### chickendude

• Posts: 816
• Rating: +90/-1
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #12 on: January 28, 2015, 04:46:37 am »
Um.. have you even tried to assemble that code? Don't you have the other necessary portions of the program already written to be able to check if the code works or not? I'm not sure why you're working on this if the other portions of the code haven't been written yet

The code you gave won't compile, there are several invalid instructions. The only 8-bit register that can read from/write to an address is a, so you can't do "ld b,(addr)" or "ld (addr),l". You have to load the value into a first.

This:
Code: [Select]
 ld a,(priorAngle) ld b,(playerDirection) cp b jr z,rc_loop_angle ld a,b ld b,5 add a,b ld (angleStop),a ld b,-10 add a,b ld (angleCurrent),aCould be:
Code: [Select]
 ld a,(playerDirection) ld hl,priorAngle cp (hl) jr z,rc_loop_angle add a,5 ld (angleStop),a sub 10 ld (angleCurrent),aThat does what your code does (and will actually assemble). But i'm not sure if you really wanted to be using playerDirection to add those values to or priorAngle. Probably priorAngle. Shouldn't you at least try to assemble your code first?

I can't comment on the code as a whole because i don't really understand raycasting or what you're trying to do, sorry...

#### ACagliano

• Posts: 910
• Rating: +32/-2
##### Re: Figuring out what's in front of you (RayCaster)
« Reply #13 on: January 28, 2015, 09:17:40 am »
That does what your code does (and will actually assemble). But i'm not sure if you really wanted to be using playerDirection to add those values to or priorAngle. Probably priorAngle. Shouldn't you at least try to assemble your code first?

I can't comment on the code as a whole because i don't really understand raycasting or what you're trying to do, sorry...

I know there are certain technicalities within it like the ld b,** stuff. However, I want to get the routine conceptually working, then i fix that.
To answer your question about priorAngle, that is actually just a check if whether the current angle and the last angle we calculated are the same. If they are, then we skip the part where we figure out angleStop and the starting angle (which I just found a mistake... angle current needs to be manually set if we do that, or angleStart and angleCurrent need to be separate).

***Edit*** fixed all instances of that, and amended my code to above to reflect

***Edit 2 *** found another mistake. As of now, the raycaster, when calculating the vectors for the present angle, only saves the .8 part of the 8.8FP number. However, in the routine, i add hl (where h= x origin integer and l= y origin integer) to bc (where b is the .8 part of the x vector and c is the .8 part of the y vector). Clearly, that's a mistake, but short of adding more RAM and using the full 8.8 location, i don't see a workaround.
« Last Edit: January 28, 2015, 01:16:49 pm by ACagliano »