Algorithm to find positions list on a grid - algorithm

I'm creating a small 2D game (With Javascript) on a grid. In this game, I have 3 kind of unit types let's say:
green: unit which have a shot range of 1 tile (they can attack a target 1 tile around)
orange: unit which have a shot range of 2 tiles
blue: unit which have a shot range of 3 tiles
Here's a schema:
The black square is the target. The gray one is the unit.
The movement of the unit is OK, I can move on wathever square when I want. The target is fixed.
My question is:
How can I find, according the unit color (range 1,2 or 3), all the tiles where the unit will be able to shot?
I mean:
Blue unit can shot from: blue, orange and green tiles
Orange unit can shot from: orange and green tiles
Green unit can shot from: green tiles
I though about an ugly solution with two nested loops but, maybe there is a known algorithm to do this...
I have a (x,y) position for the target and the unit
I saw this one Algorithm for finding spaces to attack target within move-attack area on a 2D grid game board but my probleme seems to me more simple:
Can you help me?

What about this?
boolean canShot(Unit unit, Target target){
if ((unit.minimumShotDistance <= Math.abs(unit.position.x - target.position.x) &&
unit.minimumShotDistance <= Math.abs(unit.position.y - target.position.y)){
return true;
}
return false;
}

Depending on color of unit tile, set value of range=1(green), 2(orange) or 3(blue).
Now, all tiles in range (x,y) such that:
x = targetX - range to targetX + range
y = targetY - range to targetY + range
and (x,y) is within board limits
will give all the tiles from where your unit can shoot.
If you want to know that whether from its current position, unit can shoot the target or not, check if unit's coordinates (x,y) satisfy above conditions.

Related

Calculate 3D distance based on change in intensity

I have three sections (top, mid, bot) of grayscale images (3D). In each section, I have a point with coordinates (x,y) and intensity values [0-255]. The distance between each section is 20 pixels.
I created an illustration to show how those images were generated using a microscope:
Illustration
Illustration (side view): red line is the object of interest. Blue stars represents the dots which are visible in top, mid, bot section. The (x,y) coordinates of these dots are known. The length of the object remains the same but it can rotate in space - 'out of focus' (illustration shows a rotating line at time point 5). At time point 1, the red line is resting (in 2D image: 2 dots with a distance equal to the length of the object).
I want to estimate the x,y,z-coordinate of the end points (represents as stars) by using the changes in intensity, the knowledge about the length of the object and the information in the sections I have. Any help would be appreciated.
Here is an example of images:
Bot section
Mid section
Top section
My 3D PSF data:
https://drive.google.com/file/d/1qoyhWtLDD2fUy2zThYUgkYM3vMXxNh64/view?usp=sharing
Attempt so far:
enter image description here
I guess the correct approach would be to record three images with slightly different z-coordinates for your bot and your top frame, then do a 3D-deconvolution (using Richardson-Lucy or whatever algorithm).
However, a more simple approach would be as I have outlined in my comment. If you use the data for a publication, I strongly recommend to emphasize that this is just an estimation and to include the steps how you have done it.
I'd suggest the following procedure:
Since I do not have your PSF-data, I fake some by estimating the PSF as a 3D-Gaussiamn. Of course, this is a strong simplification, but you should be able to get the idea behind it.
First, fit a Gaussian to the PSF along z:
[xg, yg, zg] = meshgrid(-32:32, -32:32, -32:32);
rg = sqrt(xg.^2+yg.^2);
psf = exp(-(rg/8).^2) .* exp(-(zg/16).^2);
% add some noise to make it a bit more realistic
psf = psf + randn(size(psf)) * 0.05;
% view psf:
%
subplot(1,3,1);
s = slice(xg,yg,zg, psf, 0,0,[]);
title('faked PSF');
for i=1:2
s(i).EdgeColor = 'none';
end
% data along z through PSF's center
z = reshape(psf(33,33,:),[65,1]);
subplot(1,3,2);
plot(-32:32, z);
title('PSF along z');
% Fit the data
% Generate a function for a gaussian distibution plus some background
gauss_d = #(x0, sigma, bg, x)exp(-1*((x-x0)/(sigma)).^2)+bg;
ft = fit ((-32:32)', z, gauss_d, ...
'Start', [0 16 0] ... % You may find proper start points by looking at your data
);
subplot(1,3,3);
plot(-32:32, z, '.');
hold on;
plot(-32:.1:32, feval(ft, -32:.1:32), 'r-');
title('fit to z-profile');
The function that relates the intensity I to the z-coordinate is
gauss_d = #(x0, sigma, bg, x)exp(-1*((x-x0)/(sigma)).^2)+bg;
You can re-arrange this formula for x. Due to the square root, there are two possibilities:
% now make a function that returns the z-coordinate from the intensity
% value:
zfromI = #(I)ft.sigma * sqrt(-1*log(I-ft.bg))+ft.x0;
zfromI2= #(I)ft.sigma * -sqrt(-1*log(I-ft.bg))+ft.x0;
Note that the PSF I have faked is normalized to have one as its maximum value. If your PSF data is not normalized, you can divide the data by its maximum.
Now, you can use zfromI or zfromI2 to get the z-coordinate for your intensity. Again, I should be normalized, that is the fraction of the intensity to the intensity of your reference spot:
zfromI(.7)
ans =
9.5469
>> zfromI2(.7)
ans =
-9.4644
Note that due to the random noise I have added, your results might look slightly different.

Find number of white/black pixels in binary image

I have an binary word image with grid and i want to find the foreground pixels (number of black and white in each segments) in each segments
So I just wanted to get the total number of black pixels for an image and I didn't want to segment it. Didn't feel like having to learn how to segment a matrix.
Easy fix to get the sum of the black pixels:
sum(sum(bw == 0))
Conversely to get the white pixels
sum(sum(bw == 1))
The operation function sum(bw == 0) just gets everything to a [1xn] matrix, so you will need to perform sum and you will get the whole image matrix summed.
Thought that cumsum would do the trick, but sum(sum()) is just better for this case. Tells you how little I know about coding. Have fun with this info, note that I'm just using this to determine the area coverage of a binarized image, but for anything else particularly useful.
Assume your black and white image is bw
sum(bw==0) // number of black pixels
sum(bw==1) // number of white pixels
For each grid find the range in both directions, then apply the same idea.
For example, from x1 to x2 and y1 to y2 is one grid:
sum(bw(x1:x2, y1:y2) == 0) // will give you the black pixels you want
That is easy with logical indexing.
For each segment, do:
n_white=sum(segment(:)==1);
n_black=sum(segment(:)==0);

Pie chart icon placing algorithm

I have a problem when trying to draw a pie chart.
Of course, there is no problem with drawing the chart, the problem is the icon placement.
Ideally, the icons should be placed on a circle (let's forget the percent labels for now).
However, the design obviously breaks when there are neighbor items with small values.
Could you recommend an algorithm solving this issue? To simplify, as input we have:
PIE_RADIUS - The outer radius of the pie.
ICON_RADIUS - The radius of the icon circle.
ICON_PLACEMENT_RADIUS - The radius of the circle when icon center should be ideally placed.
NUM_ICONS - Number of icons to place.
iconAngles Angle for every icon, in the center of its section
Required output:
Either iconAngles for items placed around the pie or iconPositions when moving the icons out of their ideal circle.
I know how to check whether two icons overlap.
We can consider the center of the pie to be at (0, 0).
(The implementation is part of an iOS application but I am interested in a general algorihm).
A first naive algorithm , we "push" the icons that overlap with an other icon:
FOR iconToPlace in icons do:
isPlaced = false
WHILE(not isPlaced) DO:
isPlaced = true
FOR icon in icons DO:
IF overlap(iconToPlace, icon) AND iconToPlace != icon THEN:
isPlaced = false
push(iconToPlace) // same angle but the icon is now further
BREAK
ENDIF
ENDFOR
ENDWHILE
ENDFOR
With this first algorithm some icons will be futher from the center than other. But it does not exploit the possible place by changing the angle. By applying this to your second design (with small values) it is clear that the solution will be far away from the ideal one.
A second less naive algorithm, first we allocate a new angle (difference less than DeltaAngleMax) for each icon then we apply the first algo:
icons = SORT(icons)
iconsRef = icons
isFinished = false
WHILE(not isFinished) DO:
isFinished = true
FOR i = 0 TO i = NUM_ICONS-1 DO:
IF overlap(icons(i), icons(i+1 % NUM_ICONS))
AND not overlap(icons(i), icons(i-1 % NUM_ICONS)) //seems useless
AND not overlap(icons(i)-DeltaAngle % 360, icons(i-1 % NUM_ICONS))
AND ABS(icons(i)-iconsRef(i)) <= DeltaAngleMax THEN:
//overlap with next icon but not with previous,
//if we decrease angle we still not overlap with previous icon and
//the futur delta angle is less than DeltaAngleMax
//then we can move the icon :
icons(i) = icons(i)-DeltaAngle
isFinished = false
ELSE IF overlap(icons(i), icons(i-1 % NUM_ICONS))
AND not overlap(icons(i), icons(i+1 % NUM_ICONS)) //seems useless
AND not overlap(icons(i)+DeltaAngle % 360, icons(i+1 % NUM_ICONS))
AND ABS(icons(i)-iconsRef(i)) <= DeltaAngleMax THEN:
//vice et versa:
icons(i) = icons(i)+DeltaAngle
isFinished = false
ENDFOR
ENDWHILE
APPLY_FIRST_ALGO
Choose wisely deltaAngle and DeltaAngleMax. A too little deltaAngle will lead to a big running time.
To go further you should have a look at the force-directed graph drawing algorithm which is much more robust method to achieve your goal, one of the difficulty is to find the correct forces of the nodes (your icons, you have no edges).
Just brainstorming:
A genetic algorithm with a fitness function that has a high penalty for overlaps plus a penalty equal to the sum of the squares of the angular distances between each candidate location and its ideal location (centered relative to its slice).
The solution I implemented was the following:
Calculate the position for all the icons relative to their slice (icon centered on ICON_PLACEMENT_RADIUS)
Find sequences of overlapping icons (iterate the icons and check if the next is overlapping with the previous).
Calculate the minimum angular distance between two icons (approximately (2.0f * ICON_RADIUS + 1.0f) / ICON_PLACEMENT_RADIUS)
Calculate the center of the sequence (sum all the slices for the sequence and find the center), place the icons together (distance between them is the minimum angular distance).
When all icons placed, check if icons overlap, if yes, merge their sequences and iterate.
Note this algorithm works only if all the number of icons is small comparing to the size of the circle but it's simple and very fast.
The result is:

Color tint and temperature

Though I have found a lot of topics on color tint and temperature, but till now I have not seen any definite solution, which is the reason I am creating this post..My apologies for that.
I am interested in adjusting color temp and tint in images from RGB values, somewhat similar to the iPhoto application found in iOS where it can be adjusted with a slider bar from left to right.
Whatever I have found, temp and tint are orthogonal properties, where temp adjustment is along the blue (left; cool colors)--yellow(right; warm colors) and tint along the green (left) -- magenta (right) axis.
How do I adjust them using formulas from RGB values i.e., uderlying implementation of the color temp and tint slider bars.
I can convert them to HSV space and then I can rotate the hue wheel channel towards those (blue, yello, green, magenta) angles, but how to do them in a systematic fashion similar to the slider bar implementation by changing gradually from low level (middle of the slider bar) to high level (right/left ends of the slider bar).
Thanks!
You should try using HSL instead of HSV. HSL saturation separates itself from the hue and luminosity has very definitive range when it comes to mathematical calculation.
In HSL, to add tint you move the L factor between 50-100 and to add shade the L factor varies between 0-50. Also saturation for HSL controls the tone directly unlike HSV.
For temperature, you have to devise your own stratagy changing the color between red and blue but one golden hint that I can give you is "every pure RGB color has one of 3 color values as zero, second fixed to 255 and 3rd varies with the factor of 255/60.
Hope this helps-
Whereas color temparature is a physical value, its expression
in terms of RGB values
not
trivial. If all you need is a pair of orthogonal axes in the RGB colorspace for the visual adjustment of white balance, they can be defined with relative ease in such a way as to resemble the true color temperature and its derivative the tint.
Let us name our RGB temperature BY—for the balance between blue and yellow, and our RGB tint GR—for the balance balance between green and red. Now, these functions must satisfy the following obvious requirements:
They shall not depend on brightness, or be invariant to multiplication of all the RGB components by the same factor:
BY(r,g,b) = BY(kr, kg, kb),
GR(r,g,b) = GR(kr, kg, kb).
They shall be zero for neutral gray:
BY(0,0,0) = 0,
GR(0,0,0) = 0.
They shall belong the to same range, symmetrical around zero point. I will use [-1..+1]
Any combination of BY and GR shall define a valid color.
Now, one of the ways to define them could be:
BY = (r + g - 2b)/(r + g + 2b),
GR = (r - g )/(r + g) .
so that each pair of BY and GR determines a specific proportion
r:g:b = (1 + BY)(1 + GR)
(1 + BY)(1 - GR)
1 - BY
The following image shows the colors of maximum brightness on our BY-GR plane. BY is directed right, GR down, and the neutral point (0,0) is at the center:
Proper
adjustment of white balance consists of multiplication of the linear RGB values by individual factors:
r_new = wb_r * r_old
g_new = wb_g * g_old
b_new = wb_b * b_old
It happens to work on gamma-compressed RGB too, but not so well on sRGB, because of a
piece-wise
definition of its transfer function, but the distortion will be small and often unnoticeable. If you want a perfect adjustment, however, make sure to work in linear RGB.
Once a BY-GR pair is chosen and the corresponding RGB proportion calculated, only one degree of freedom remains—the overall multiplier (see req. 1). Choose it so that no pixels become clipped.

Calculating which tiles are lit in a tile-based game ("raytracing")

I'm writing a little tile-based game, for which I'd like to support light sources. But my algorithm-fu is too weak, hence I come to you for help.
The situation is like this: There is a tile-based map (held as a 2D array), containing a single light source and several items standing around. I want to calculate which tiles are lit up by the light source, and which are in shadow.
A visual aid of what it would look like, approximately. The L is the light source, the Xs are items blocking the light, the 0s are lit tiles, and the -s are tiles in shadow.
0 0 0 0 0 0 - - 0
0 0 0 0 0 0 - 0 0
0 0 0 0 0 X 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 L 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 X X X X 0 0
0 0 0 - - - - - 0
0 0 - - - - - - -
A fractional system would be even better, of course, where a tile can be in half-shadow due to being partially obscured. The algorithm wouldn't have to be perfect - just not obviously wrong and reasonably fast.
(Of course, there would be multiple light sources, but that's just a loop.)
Any takers?
The roguelike development community has a bit of an obsession with line-of-sight, field-of-view algorithms.
Here's a link to a roguelike wiki article on the subject:
http://roguebasin.roguelikedevelopment.org/index.php?title=Field_of_Vision
For my roguelike game, I implemented a shadow casting algorithm (http://roguebasin.roguelikedevelopment.org/index.php?title=Shadow_casting) in Python. It was a bit complicated to put together, but ran reasonably efficiently (even in pure Python) and generated nice results.
The "Permissive Field of View" seems to be gaining popularity as well:
http://roguebasin.roguelikedevelopment.org/index.php?title=Permissive_Field_of_View
You can get into all sorts of complexities with calculating occlusion etc, or you can go for the simple brute force method: For every cell, use a line drawing algorithm such as the Bresenham Line Algorithm to examine every cell between the current one and the light source. If any are filled cells or (if you have only one light source) cells that have already been tested and found to be in shadow, your cell is in shadow. If you encounter a cell known to be lit, your cell will likewise be lit. An easy optimisation to this is to set the state of any cells you encounter along the line to whatever the final outcome is.
This is more or less what I used in my 2004 IOCCC winning entry. Obviously that doesn't make good example code, though. ;)
Edit: As loren points out, with these optimisations, you only need to pick the pixels along the edge of the map to trace from.
The algorithms being presented here seem to me to be doing more calculations than I think are needed. I have not tested this but I think it would work:
Initially, mark all pixels as lit.
For every pixel on the edge of the map: As Arachnid suggested, use Bresenham to trace a line from the pixel to the light. If that line strikes an obstruction then mark all pixels from the edge to just beyond the obstruction as being in shadow.
Quick and dirty:
(Depending on how big the array is)
Loop through each tile
draw a line to the Light
If any pary of the line hits an X, then it is in shadow
(Optional): calculate the amount of X the line passes through and do fancy maths to determint the proportion of the tile in shadow. NB: This could be done by anti-aliasing the line between the tile and the Light (therefore looking at other tiles along the route back to the light source) during the thresholding procedure these will appear as small anomolies. Depending on the logic used you could potentially determine how much (if at all) the tile is in shadow.
You could also keep a track of which pixels have been tested, therefore optimize the solution a little and not re-test pixels twice.
This could be dome pretty well by using image manipulation and drawing straight lines between pixles (tiles) If the lines are semi transparent and the X blocks are semi-transparent again. You can threshold the image to determine if the line has intersected an 'X'
If you have an option to use a 3rd party tool, then Id probably take it. In the long run it might turn out to be quicker, but you'd understand less about your game.
This is just for fun:
You can replicate the Doom 3 approach in 2D if you first do a step to convert your tiles into lines. For instance,
- - - - -
- X X X -
- X X - -
- X - - -
- - - - L
...would be reduced into three lines connecting the corners of the solid object in a triangle.
Then, do what the Doom 3 engine does: From the perspective of the light source, consider each "wall" that faces the light. (In this scene, only the diagonal line would be considered.) For each such line, project it into a trapezoid whose front edge is the original line, whose sides lie on lines from the light source through each end point, and whose back is far away, past the whole scene. So, it's a trapezoid that "points at" the light. It contains all the space that the wall casts its shadow on. Fill every tile in this trapezoid with darkness.
Proceed through all such lines and you will end up with a "stencil" that includes all the tiles visible from the light source. Fill these tiles with the light color. You may wish to light the tile a little less as you get away from the source ("attenuation") or do other fancy stuff.
Repeat for every light source in your scene.
To check if a tile is in shadow you need to draw a straight line back to the light source. If the line intersects another tile that's occupied, then the tile you were testing is in shadow. Raytracing algorithms do this for every object (in your case tile) in the view.
The Raytracing article on Wikipedia has pseudocode.
Here is a very simple but fairly effective approach that uses linear time in the number of tiles on screen. Each tile is either opaque or transparent (that's given to us), and each can be visible or shaded (that's what we're trying to compute).
We start by marking the avatar itself as "visible".
We then apply this recursive rule to determine the visibility of the remaining tiles.
If the tile is on the same row or column as the avatar, then it is only visible if the adjacent tile nearer to the avatar is visible and transparent.
If the tile is on a 45 degree diagonal from the avatar, then it is only visible if the neighboring diagonal tile (towards the avatar) is visible and transparent.
In all other cases, consider the three neighboring tiles that are closer to the avatar than the tile in question. For example, if this tile is at (x,y) and is above and to the right of the avatar, then the three tiles to consider are (x-1, y), (x, y-1) and (x-1, y-1). The tile in question is visible if any of those three tiles are visible and transparent.
In order to make this work, the tiles must be inspected in a specific order to ensure that the recursive cases are already computed. Here is an example of a working ordering, starting from 0 (which is the avatar itself) and counting up:
9876789
8543458
7421247
6310136
7421247
8543458
9876789
Tiles with the same number can be inspected in any order amongst themselves.
The result is not beautiful shadow-casting, but computes believable tile visibility.
I know this is years old question, but for anyone searching for this style of stuff I'd like to offer a solution I used once for a roguelike of my own; manually "precalculated" FOV. If you field of view of light source has a maximum outer distance it's really not very much effort to hand draw the shadows created by blocking objects. You only need to draw 1/8 th of the circle (plus the straight and diagonal directions); you can use symmerty for the other eigths. You'll have as many shadowmaps as you have squares in that 1/8th of a circle. Then just OR them together according to objects.
The three major pros for this are:
1. It's very quick if implemented right
2. You get to decide how the shadow should be cast, no comparing which algorith handles which situation the best
3. No weird algorith induced edge cases which you have to somehow fix
The con is you don't really get to implement a fun algorithm.
TK's solution is the one that you would generally use for this sort of thing.
For the partial lighting scenario, you could have it so that if a tile results in being in shadow, that tile is then split up into 4 tiles and each one of those is tested. You could then split that up as much as you wanted?
Edit:
You can also optimise it out a bit by not testing any of the tiles adjacent to a light - this would be more important to do when you have multiple light sources, I guess...
I've actually just recently wrote this functionality into one of my projects.
void Battle::CheckSensorRange(Unit* unit,bool fog){
int sensorRange = 0;
for(int i=0; i < unit->GetSensorSlots(); i++){
if(unit->GetSensorSlot(i)->GetSlotEmpty() == false){
sensorRange += unit->GetSensorSlot(i)->GetSensor()->GetRange()+1;
}
}
int originX = unit->GetUnitX();
int originY = unit->GetUnitY();
float lineLength;
vector <Place> maxCircle;
//get a circle around the unit
for(int i = originX - sensorRange; i < originX + sensorRange; i++){
if(i < 0){
continue;
}
for(int j = originY - sensorRange; j < originY + sensorRange; j++){
if(j < 0){
continue;
}
lineLength = sqrt( (float)((originX - i)*(originX - i)) + (float)((originY - j)*(originY - j)));
if(lineLength < (float)sensorRange){
Place tmp;
tmp.x = i;
tmp.y = j;
maxCircle.push_back(tmp);
}
}
}
//if we're supposed to fog everything we don't have to do any fancy calculations
if(fog){
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
Map->GetGrid(maxCircle[circleI].x,maxCircle[circleI].y)->SetFog(fog);
}
}else{
bool LOSCheck = true;
vector <bool> placeCheck;
//have to check all of the tiles to begin with
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
placeCheck.push_back(true);
}
//for all tiles in the circle, check LOS
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
vector<Place> lineTiles;
lineTiles = line(originX, originY, maxCircle[circleI].x, maxCircle[circleI].y);
//check each tile in the line for LOS
for(int lineI = 0; lineI < (int) lineTiles.size(); lineI++){
if(false == CheckPlaceLOS(lineTiles[lineI], unit)){
LOSCheck = false;
//mark this tile not to be checked again
placeCheck[circleI] = false;
}
if(false == LOSCheck){
break;
}
}
if(LOSCheck){
Map->GetGrid(maxCircle[circleI].x,maxCircle[circleI].y)->SetFog(fog);
}else{
LOSCheck = true;
}
}
}
}
There's some extra stuff in there that you wouldn't need if you're adapting it for your own use. The type Place is just defined as an x and y position for conveniences sake.
The line function is taken from Wikipedia with very small modifications. Instead of printing out x y coordinates I changed it to return a place vector with all the points in the line. The CheckPlaceLOS function just returns true or false based on if the tile has an object on it. There's some more optimizations that could be done with this but this is fine for my needs.
i have implemented tilebased field of view in a single C function. here it is:
https://gist.github.com/zloedi/9551625
If you don't want to spend the time to reinvent/re-implement this, there are plenty of game engines out there. Ogre3D is an open source game engine that fully supports lighting, as well as sound and game controls.

Resources