I'm new here and trigonometry is still a bit complicated for me. I'm not quite sure where to start on this, so sorry I can't really be specific, but I've been wanting to make a field of view.
I have no idea how to tell the game which squares to check for vision and how to block vision. As a newcomer to all this, what do I need to learn?
Learn how to translate between polar coordinates (magnitude and direction) and cartesian coordinates (x/y). Then use that to set up a range to check within.
(Note: I am not that good a coder (yet), so there probably is a better way, or more advanced way.)
If you just want something simple like link to the past, then you could only draw stuff near you and leave the rest black. Maybe do a second pass further away/dimmer for fanciness. Heck, if you want a super simple/cheap way, just use clip() to only draw in a box near the character. (and reset the clip when you draw the UI etc)
If you want moving diagonal lines as you pass corners, then you're going to be casting rays, and manually drawing shadows or lit areas. I won't pretend to have real advice, but there is a game that does crazy-awesome shadows. Also, here's an explanation of the pseudo-3d ray-casting cart if you want a peek at some methods and shortcuts used for that kind of stuff.
You might want to start reading at the Field of Vision article on the roguebasin wiki. IIRC recursive shadowcasting is at the sweet spot of simplicity and speed.
Here is my FOV code from my lil roguelike WIP, to give an idea of the algorithm.
function cast(d,lo_slp,hi_slp,oct) -- distance, height from player -- to map xy -- flips/transposes per octant function dhtoxy(d,h) local x,y=p.x,p.y if band(oct,0x1)>0 then d=-d end if band(oct,0x2)>0 then h=-h end if band(oct,0x4)>0 then return x+h,y+d end return x+d,y+h end if d>16 then return end local mapx,mapy,lo,hi local in_gap lo=flr(lo_slp*d+0.5) hi=flr(hi_slp*d+0.5) for h=lo,hi do mapx,mapy=dhtoxy(d,h) set_visible(mapx,mapy) if is_opaque(mapx,mapy) then if in_gap then -- reached end of gap cast(d+1,lo_slp,(h-0.5)/d,oct) end lo_slp=(h+0.5)/d in_gap=false else in_gap=true if h==hi then -- end of gap cast(d+1,lo_slp,hi_slp,oct) end end end end function do_vis() clear_vis() for oct=0,7 do cast(1,0,1,oct) end end |
Thanks for your responses. I've noticed I will have to figure out how to draw angles. I think this is the scary obstacle I'm stuck on, so I could have some suggestions on how to practice doing that so I can make something like field of vision.
One of the easiest ways to block vision from walls or other obstacles I have seen was in Ultima /// for the Apple ][.
Here is a chart to explain what I saw:
White represents the player, BLUE represents an obstacle, and RED represents the tiles that are blocked from vision.
As you can see, anything that matches the player's X or Y creates an easy triangular field block.
Anything ELSE only creates a single diagonal line of blocked tiles spreading outward based on the position of the player.
Using this, you can indeed walk through doors and see only the contents of the room you are in while the room you left is shadowed from view.
This method is especially useful if you leave the player in the center of the screen and merely scroll the map around him.
So I've gotten the hang of taking a variable and utilizing it to draw an angle. I'm wondering if there are any other exercises I should do before tackling FOV proper, or if this is sufficient enough to do something like shadowcasting, or shadowcasting.
DarkMatt, there is the classic Metal Gear Solid if you have not seen it. They use a cone of vision for the bad guys.
Mei Ling explains it well here:
https://youtu.be/WpG9XIfFkE0?t=729
Another game release was made, much simpler, for the Gameboy Color. Despite not having a cone of vision, I found in playing the game that the guards in there were very intuitive and if you got in their line of sight, even diagonally, they would sound the alarm.
[Please log in to post a comment]