I've tried Bresenham line and Raycasting, but they don't quite give the results I need (examples in the screenshot).
'&' - character
'+' - cells that can be attacked by the character
'#' - walls
Bresenham:
As can be seen in the screenshot, a character can attack a cell, but if moved to it, it cannot attack from there to its original position.
Is there a fair algorithm so that a character who can attack an enemy can be attacked by the enemy in return.
Perhaps the problem is in my code?
void FieldOfSight(Field &field, const Vector2i &player, float distance,
int type)
{
Vector2i endPosition;
float radians = 0;
float step = M_PI / (distance * 10);
while (radians < 2 * M_PI) {
endPosition.x = player.x + round(cos(radians) * (distance));
endPosition.y = player.y + round(sin(radians) * (distance));
if (endPosition.y >= field.GetHeight())
endPosition.y = field.GetHeight() - 1;
else if (endPosition.y <= 0)
endPosition.y = 0;
if (endPosition.x >= field.GetWidth())
endPosition.x = field.GetWidth() - 1;
else if (endPosition.x <= 0)
endPosition.x = 0;
radians += step;
switch (type) {
case (0):
SupercoverLine(field, player, endPosition);
break;
case (1):
WalkLine(field, player, endPosition);
break;
case (2):
BresenhamLine(field, player, endPosition);
break;
}
}
}
void SupercoverLine(Field &field, int x0, int y0, int x1, int y1)
{
int dx = x1 - x0, dy = y1 - y0;
int nx = abs(dx), ny = abs(dy);
int sign_x = dx > 0 ? 1 : -1, sign_y = dy > 0 ? 1 : -1;
int px = x0, py = y0;
field.SetFG(px, py, 8);
for (int ix = 0, iy = 0; ix < nx || iy < ny;) {
int decision = (1 + 2 * ix) * ny - (1 + 2 * iy) * nx;
if (decision == 0) {
px += sign_x;
py += sign_y;
if (field[py - sign_y][px] == 1 && field[py][px - sign_x] == 1)
break;
++ix;
++iy;
} else if (decision < 0) {
px += sign_x;
++ix;
} else {
py += sign_y;
++iy;
}
if (sqrt((x0 - px) * (x0 - px) + (y0 - py) * (y0 - py)) > 5 ||
field[py][px] == 1)
break;
field.SetFG(px, py, 8);
}
}
void WalkLine(Field &field, int x0, int y0, int x1, int y1)
{
int dx = x1 - x0, dy = y1 - y0;
int nx = abs(dx), ny = abs(dy);
int sign_x = dx > 0 ? 1 : -1, sign_y = dy > 0 ? 1 : -1;
int px = x0, py = y0;
for (int ix = 0, iy = 0; ix < nx || iy < ny;) {
if ((0.5 + ix) / nx < (0.5 + iy) / ny) {
px += sign_x;
ix++;
} else {
py += sign_y;
iy++;
}
if (sqrt((x0 - px) * (x0 - px) + (y0 - py) * (y0 - py)) > 5 ||
field[py][px] == 1)
break;
field.SetFG(px, py, 8);
}
}
void BresenhamLine(Field &field, int x0, int y0, int x1, int y1)
{
int dx = abs(x1 - x0);
int sx = x0 < x1 ? 1 : -1;
int dy = -abs(y1 - y0);
int sy = y0 < y1 ? 1 : -1;
int error = dx + dy;
int x = x0, y = y0;
field.SetFG(x0, y0, 8);
while (true) {
if (x0 == x1 && y0 == y1)
break;
int e2 = 2 * error;
if (e2 >= dy) {
if (x == x1)
break;
error += dy;
x += sx;
}
if (e2 <= dx) {
if (y == y1)
break;
error += dx;
y += sy;
}
if ((field[y - sy][x] == 1 && field[y][x - sx] == 1) ||
sqrt((x0 - x) * (x0 - x) + (y0 - y) * (y0 - y)) > 5 ||
field[y][x] == 1)
break;
field.SetFG(x, y, 8);
}
}
Sorry for the code without comments
if(x0>x1){swap(x0,x1);swap(y0,y1);}
. \$\endgroup\$