67

You need to change the shape of the field of view. So that when you move in any direction, the same number of new squares become visible. Here is one possibility:


67

Dungeons and Dragons 3.5 (pen-and-paper RPG) has a solution used for both movement and grid-based radius calculations: diagonal movement costs 1.5 what orthogonal costs. Since the diagonal of a unit square is approximately 1.414, 1.5 is pretty close. Because D&D 3.5 only supports integer movement, the way this is actually calculated is that orthogonal ...


27

To have diagonal and orthogonal movement reveal approximately the same area, you need two things (each of which, alone, has already been suggested in another answer or comment): Approximately circular view range: On its own, this won't give exactly the same revealed area for both types of movement. For example, in the image above, orthogonal movement ...


11

Since you are using a grid and know which direction the user is proceeding there is nothing constraining you from adapting the prior answer and using a different fields of view depending on the direction. For example you could extended the field to include the corners when you travel in cardinal directions and shrink it down two squares on each end in your ...


8

You could try casting "shadow arcs" to cover larger areas at once. While the actual details are a bit involved, Eric Lippert has a very in-depth explanation (with live Silverlight demo) at http://blogs.msdn.com/b/ericlippert/archive/2011/12/12/shadowcasting-in-c-part-one.aspx.


8

In algorithm 1, you're using “even-q” but you should use “odd-q” instead. Your grid is flipped upside down relative to the one on my page, so you want to shift every odd column up instead of every even column down. Change + (x % 2) in coordOffset2Cube and coordCube2Offset to use - (x % 2) instead. Also, on diagonals, the line drawing algorithm will not hit ...


8

As requested, one possible solution (with some flaws) is to use raycasting: Attaching a (C#) Script similar to this to the GameObject from which you want to check visibility would work: if(renderer.isVisible) //Check if Camera is turned towards the GameObject first { RaycastHit hit; // Calculate Ray direction Vector3 direction = Camera.main....


7

How about, rather than having a fixed viewing range, have the player's visibility area depend upon what direction the player was facing, as well as perhaps the direction the player faced in the last few turns (a player who was moving north might be able to immediately take a step south, but might take a few turns to get maximum viewing distance in that ...


7

Do the LOS and AOI (Area Of Interest) filtering on the server. Yes, any data you send the client can be hacked. OR extra programs can be inserted as a proxy between client and server to sniff excess data, like the old EverQuest viewer that lets players not only see far-away monsters but even what loot they would drop (which is a bit mind-boggling why that ...


7

One of the popular ways to do this, as Doorknob says in their comment, is Bresenham's line algorithm. The example image of which looks nearly identical to you requirement example: It's commonly used to draw lines on the computer screen deciding which pixels to use to represent that line. In your case, you'll use it to decide which grid spaces to check. ...


7

Eric Lippert wrote an excellent series on generating line-of-sight in C# with Shadow Casting on a rectangular planar grid.. Amongst other issues, Eric dealt with various questions that must be answered about the line-of-sight requirements, which give different results, and gives examples of a couple of different results. One of the articles deals in depth ...


7

As long as your movement space isn't Euclidean and things can block an entire grid space, you'll have this problem. If you want people to not "play the grid" you're probably going to have to not use a grid.


6

Ray casting is a very fast and efficient way to determine line-of-sight. It basically involves sending a ray (think of it like an infinite laser that can't be redirected) from a certain position in a certain direction. Using this ray, you can determine things like which point(s) it intersects and how far away from the origin it was when it crossed a certain ...


6

(I don't have enough reputation to comment) The answer here is that the distances are wrong. A is closer than B. To convince yourself, compare A and the reflection of B w.r.t. the player, so I don't think there is an issue here. Hex grids are tricky in a lot of ways.


6

The first thing I would suggest is to use a 2d implementation like the one in Teleglitch, like you said yourself, you found solutions, this is a lot simpler. Line of sight is a gameplay mechanic. If the game is top-down, the gameplay is essentially 2d and there is likely a limited benefit to using actual 3d line of sight. No, you are absolutely right. This ...


5

One thought would be to maintain non-panicky and panicky people in separate lists N and P, and then limit your LOS checks to <n, p> ∈ N × P. That way you never check same-state people, which will speed things up. Another thing (which you may already be doing--not sure) would be to make sure that once you determine that a nonpanicker has ...


5

I have implemented the algorithm suggested by Jimmy. Video of the code in action here: https://youtu.be/lIlPfwlcbHo /* What this code does: Rasterizes a single Field Of View octant on a grid, similar to the way FOV / shadowcasting is implemented in some roguelikes. Clips to bitmap Steps on pixel centers Optional ...


5

Depending on your exact needs, another possible solution would be to do a test render where you set different objects to different colors and then check for that color in the test render. However this would only be useful in pretty obscure situations; in the majority of situations I would use raycasting. I'm just dropping in this different answer for ...


4

Basically, you're going to be doing raycasting to figure out where exactly the vision gets blocked. The complexities come in with trying to make that clean and efficient and fit with how you're managing the actual scene. Other people have done a much better job explaining everything than I can, so I'm just going to reference them. Amit has a fantastic ...


4

If you use an algorithm like Bresenham, where the two lines can be different, depending on their start- and end-position, you then have to either: Plot both lines and use the result of both plots for your LoS calculation. Plot only one line (for example always from Player to Enemy) and use this one LoS calculation for both entities.


4

The shape is irregular because of the obstacles. If you shoot a ray in every direction (360 cicle around unit), you determine if you hit an obstacle, and if yes, at what distance. If the ray does not encounter any obstacles before reaching the line of sight distance, then it stops, otherwise it stops at the point of encounter. This is by no means efficient ...


3

As an alternative to a more complex field of view (which as discussed above adds its own problems because of the constraints of a grid-based layout) you could try to emulate the effect of movement in a game that isn't based on a discreet grid. Where free movement is possible a diagonal move of one unit would be exactly that, not the ~1.41 units of movement ...


3

Use 3D DDA. It is the 3D version of 2D cell-based raycasting which you refer to.


3

I have blogged code to compute line of sight from a height-map. A simple flat map with obstacles is just a very flat height-map, and this implementation is still completely applicable. Here it is in C++ and its O(n); if you know the maximum height in the map, you can track a scanline that has no rays remaining under that height, and early-out: typedef std:...


3

First, ahead of time, build a list of BoundingBox objects from your clutter. (If you're calling this 10 times a frame, there's no sense creating a list of them in the method itself. If removing objects that are definitely off-screen proves to be a useful optimization, then do that only once per frame and store the list of bounding boxes for repeated use.) ...


3

Given that your walls are not cells, you will need a way to identify occluders as you raymarch. The easiest way to do this would be, as you step from one cell to the next, check whether there is a wall on the boundary you are crossing from tile A to tile B, and store the result for use. Let's look at three different approaches to clarify this for you. ...


2

From your description it seems like your code is iterating over every possible pairing of two civilians. The drawing suggests that this is unnecessary. You can use some sort of geometric indexing to keep track of nearby civilians. Then test them first. If they are in the LOS, then panic. Otherwise test farther away civilians.


2

How to distinguish these two? Distinguishing between these two is a common need in triangulation algorithms, for both of those are vertex-to-vertex diagonals, one internal the other external. Typically one writes a primitive inside predicate, something like this. Let (a,b,c) be three consecutive vertices of the polygon in ccw order, and the potential ...


2

I recommend using a trigger instead of a collider. Using triggers has almost no performance impact, as raycasts are very performance hungry (you should never use raycasts in the update loop). Triggers do not block movement on collision but trigger the OnTriggerEnter event. If possible use different layers for your collides and triggers, and use the ...


2

You could make the player move two spaces if they move up, down, left or right, and only one diagonally. It wouldn't completely even it out, but it would be much closer.


Only top voted, non community-wiki answers of a minimum length are eligible