Seeing is believing


I'm struggling with line of sight this week.

The cardinal directions are easy.  If something is in your face, you can't see directly behind it.  But how do you handle a tile that is 9,4 away?  Do you just diagonal straight back?  At some point, that doesn't make sense.  But neither does a horizontal line back either.

In Ultima, Deathlord, etc... the screens were only 11x11, so the Line of Sight (LoS) only went 5 out in any direction.  You could fake it.  But with modern wide screen monitors, you might get a tile blocking vision that's 9 tiles away.  What then?

In other news:  Audio Mixers!

This is a huge improvement for Unity sound control.  I can adjust the music and SFX separately, and now I'll know when you move the slider, you move it for all the audio.

SO:  Music and the first SFX have been added to the game.  Video on that to follow next week.

Comments

Log in with itch.io to leave a comment.

Hi. Looks great so far! I used a 2-D array overlay to approach both this and the lighting issue. You have the speed to calculate a blocked view scenario for each of the tiles in one 'quadrant' say north and west of player (I drew rays on a grid paper and decided which would be blocked). The algorithm code block can then be reflected to each of the other 'quadrants' about the player. A blocked view = no/zero lighting. Light sources can then add to this value based on size/brightness and the view can be rendered using the 'overlay' as a lighting guide. Probably not the best solution but worked for me (except for calculating light blockage). Don't know if that helps but watching your project with interest. Good luck!

PS - reading back my response before posting I just figured out how I could have done the light block. :)

Thanks!  I'll take all the advice I can get.

I have a grid that flags a tile if it's "Blocking" or not in a 2d array.  I'm not thrilled with the performance speed wise, but since it lowered my FPS from 2000 to 700, I'm going to say "I'll worry about it if everything drops bellow 200fps."

Right now I have it so that the line of sight works spirals a check outward from the player each step to 15 tiles.  That more than covers the long way on 16x9 screens.  The formula to see what square to check is GetTileAt(Mathf.Abs(X)-(Mathf.Sign(X), Mathf.Abs(Y)-(Mathf.Sign(Y)).    This will always check the diagnal block closest to the player, and (oddly enough) deal with straight lines appropriately too.

What I'm really trying to decide on how to handle is what happens if you have multiple light sources?  Like you're approaching a campfire with a torch.  The obvious answer is "Add them together", but then lets say I put out my torch... how do I figure out which part of that luminosity is the torch, and which is the campfire?  I'm debating between:

A)  Do a 'negative illumination' function that gets called when a light source is put out.  And is my leading contender right now.

B)  Add all light sources on a tile to a list of objects ( List<GameObject> LightSources ) and add remove them when a source is added removed.

I feel like B is way over engineered now that I'm looking at it.  

I sometimes wish I wasn't doing a shaded value, and just did it Ultima style where things are either visible, or not.  But I feel like this really makes the cave spooky.

Hey, Chris. If I understand your view blocking method correctly then you came up with a more efficient method than I. :) In L1 I used the same array to hold view blocking (0=dark/no tile render) as for lighting. I only had 4 Val's 0-3 dark-full light. I ran I light source check before view blocking and final render and added light increments from different sources. Any value above 3 was just 3. If you have more lighting values that should be fine. If a light source goes out, it will then drop from the lighting calculations and render properly. I also had an ambient light setting (0-4) that was applied before all else based on day/night/dungeon conditions. Not sure if this approach would work in your code but maybe it gives you an idea. Keep up the good work, looks great!

Thanks!  I've been messing with it for a while now.  I'm not going to dig into it tonight, but should be doing some coding Friday (if not sooner) I'll throw actual code up when I open it up again.

Not sure what you're coding in, but I'm using Unity, which helps a bit.  

On each Tile gameobject I have a SpriteRenderer and a custom class called Tile.

What that lets me do is figure out "OK, I want the torch to have a range of 3.  So all the tiles in the next square have an alpha channel value of their illumination * (distance from source)/3.   When I get more than source +/- range away I stop updating illumination values.   Initially, I set Illumination to a base of 1, but have been putting it at 1.25 because it looks better.

Now before I would then do a second pass on "Is this tile blocked from a nearby tile?" if so set alpha on the sprite to zero, otherwise set it to the illumination value stored in the Tile.   Circling out from the player object, but I'm going to start doing that as part of the alpha value pass so that I can set illumination targets other than the player and still have line of sight blocking objects block their light.  

The map controller would also have a base illumination value added to any tile in view.  So if you're outside, I could set it high, and dial it down towards evening, or in a dungeon just turn it off (as I did in the demo).

The upshot of all this is I don't have to create multiple sprites, or anything for different light values and I can basically have as many different shades as a c# float from 0 to 1.0 will give me.  Which is a lot.  Right now it only happens on my movement, but if I get ambitious, I may add a torch flicker for some extra style.

I may go back later and add a shader to the sprites that lets me kind of pixelate them out as well as shade them.  I think that will give more of that old school feel.  Eventually anyway.  Right now I'm so eager to be done with lighting and move on to ANYTHING else....