Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <cstdlib>
#include "line_of_sight.h"
#include "util.h"
// Bresenham's line drawing algorithm
// Based on pseudocode from Wikipedia
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
// Not perfect, but does a decent job of line of sight
static uint8_t plot_line_low(int x0, int y0, int x1, int y1, dungeon &d) {
int dx = x1 - x0;
int dy = y1 - y0;
int yi = 1;
if (dy < 0) {
yi = -1;
dy = -dy;
}
int D = 2*dy - dx;
int y = y0;
int x;
for (x = x0; x != x1; x += sign(x1-x0)) {
if (d.hardness[y][x]) return 0;
if (D > 0) {
y = y + yi;
D = D - 2*dx;
}
D = D + 2*dy;
}
return 1;
}
static uint8_t plot_line_high(int x0, int y0, int x1, int y1, dungeon &d) {
int dx = x1 - x0;
int dy = y1 - y0;
int xi = 1;
if (dx < 0) {
xi = -1;
dx = -dx;
}
int D = 2*dx - dy;
int x = x0;
int y;
for (y = y0; y != y1; y += sign(y1-y0)) {
if (d.hardness[y][x]) return 0;
if (D > 0) {
x = x + xi;
D = D - 2*dy;
}
D = D + 2*dx;
}
return 1;
}
static uint8_t test_line(int x0, int y0, int x1, int y1, dungeon &d) {
int i;
// Vertical line
if (x0 == x1) {
for (i = y0; i != y1; i += sign(y1-y0)) {
if (d.hardness[i][x1]) return 0;
}
return 1;
}
if (abs(y1 - y0) < abs(x1 - x0)) {
if (x0 > x1) {
return plot_line_low(x1, y1, x0, y0, d);
} else {
return plot_line_low(x0, y0, x1, y1, d);
}
} else {
if (y0 > y1) {
return plot_line_high(x1, y1, x0, y0, d);
} else {
return plot_line_high(x0, y0, x1, y1, d);
}
}
return 1;
}
void calc_line_of_sight(dungeon &d) {
int i, j;
int x = d.player_pos.x;
int y = d.player_pos.y;
for (i = 0; i < MAP_HEIGHT; i++) {
for (j = 0; j < MAP_WIDTH; j++) {
d.pc_sight[i][j] = 0;
}
}
for (i = std::max(0, y-VIEW_DIST); i < std::min(MAP_HEIGHT, y+VIEW_DIST+1); i++) {
for (j = std::max(0, x-VIEW_DIST); j < std::min(MAP_WIDTH, x+VIEW_DIST+1); j++) {
d.pc_sight[i][j] = test_line(j, i, x, y, d);
}
}
d.update_fog_of_war();
}