DungeonCrawl
Loading...
Searching...
No Matches
draw_light.c
Go to the documentation of this file.
1
5#include "draw_light.h"
6
7#include <stdlib.h>
8
9map_tile_t* map_arr;
10map_tile_t* revealed_map_arr;
11int map_height;
12int map_width;
13vector2d_t player_position;
14int radius;
15
23 {{1, 1}, {1, 0}}, // for up
24 {{-1, -1}, {-1, 0}},// for down
25 {{1, -1}, {0, -1}}, // for left
26 {{-1, 1}, {0, 1}}, // for right
27};
28
29
39int need_loop_break(const int x, const int y, const vector2d_t dir, int j, int* prev_wall_at) {
40 if (j == 0) {
41 //gets the x or y value of the calculated coordinates
42 *prev_wall_at = abs(y * dir.dy + x * dir.dx);
43 return 1;
44 }
45 if (*prev_wall_at == abs(y * dir.dy + x * dir.dx)) {
46 //if the previous j-loop had a wall at x or y coordinate, the loop must break
47 //or else diagonals tiles (behind a wall and not visible by the player) are revealed
48 return 1;
49 }
50 return 0;
51}
52
53
63int process_tile(int x, int y, int* prev_wall_at, const vector2d_t dir, int j) {
64 int break_loop = 0;
65 //calculated access index
66 const int access_idx = x * map_height + y;
67
68 revealed_map_arr[access_idx] = map_arr[access_idx];
69
70 if (map_arr[access_idx] == WALL) {
71 break_loop = need_loop_break(x, y, dir, j, prev_wall_at);
72 }
73 return break_loop;
74}
75
76
88int check_and_process_tile(int x, int y, int* prev_wall_at, const vector2d_t dir, int j,
89 const vector2d_t diagonal_check, const vector2d_t reverse_check) {
90 int quit = 0;
91 //calculated access index
92 const int access_idx = x * map_height + y;
93
94 if (x < 0 || x >= map_width || y < 0 || y >= map_height) {
95 //calculated x or y is out of bounds
96 quit = 1;
97 } else {
98 if (revealed_map_arr[access_idx] == HIDDEN) {
99 //initialize the relative diagonal and reverse tiles based on the y and x values
100 const int rel_diagonal = map_arr[(x + diagonal_check.dx) * map_height + y + diagonal_check.dy];
101 const int rel_reverse = map_arr[(x + reverse_check.dx) * map_height + y + reverse_check.dy];
102
103 if (rel_diagonal == WALL && rel_reverse == WALL && j > 1) {
104 //if the diagonal and reverse tiles are walls and the distance from the player is greater than 1
105 // then the tile must be hidden because reverse tile is blocking the view
106 quit = 1;
107 } else {
108 quit = process_tile(x, y, prev_wall_at, dir, j);
109 }
110 } else if (revealed_map_arr[access_idx] == WALL && need_loop_break(x, y, dir, j, prev_wall_at)) {
111 quit = 1;
112 }
113 }
114 return quit;
115}
116
117
126void process_light_in_direction(const vector2d_t player, const vector2d_t dir, const vector2d_t diagonal_check,
127 const vector2d_t reverse_check, const int light_radius) {
128 int correction = 0;
129 int prev_wall_at = -1;
130
131 for (int j = 0; j <= light_radius; j++) {
132 const int start_x = player.dx + j * dir.dy;
133 int start_y = player.dy + j * dir.dx;
134
135 if (dir.dx != 0) {
136 //if the direction is vertical negate the subtrahend
137 start_y = player.dy - j * dir.dx;
138 }
139
140 if (start_x < 0 || start_x >= map_width || start_y < 0 || start_y >= map_height) {
141 //start position is out of bounds, skip to the next direction
142 break;
143 }
144 for (int k = 1; k <= light_radius - correction; k++) {
145 const int x = start_x + k * dir.dx;
146 const int y = start_y + k * dir.dy;
147
148 if (check_and_process_tile(x, y, &prev_wall_at, dir, j, diagonal_check, reverse_check)) {
149 break;
150 }
151 }
152 correction++;
153 }
154}
155
156void draw_light_on_player(map_tile_t* arr1, map_tile_t* arr2, int height, int width, vector2d_t player,
157 const int light_radius) {
158 map_arr = arr1;
159 revealed_map_arr = arr2;
160 map_height = height;
161 map_width = width;
162 player_position = player;
163 radius = light_radius;
164
165 if (light_radius <= 0) {
166 //light radius is negative or 0, do nothing
167 return;
168 }
169
170 for (int i = 0; i < 4; i++) {
171 const vector2d_t dir = directions[i];
172 const vector2d_t diagonal_check = checks_vector[i][0];
173 const vector2d_t reverse_check = checks_vector[i][1];
174
175 process_light_in_direction(player, dir, diagonal_check, reverse_check, light_radius);
176 }
177}
int need_loop_break(const int x, const int y, const vector2d_t dir, int j, int *prev_wall_at)
This is a helper function to check if the loop needs to break with this specific edge case.
Definition draw_light.c:39
int process_tile(int x, int y, int *prev_wall_at, const vector2d_t dir, int j)
This function processes the tile at the given coordinates and updates the revealed_map_arr array.
Definition draw_light.c:63
const vector2d_t checks_vector[4][2]
Each array row corresponds to the vector in the directions array.
Definition draw_light.c:22
void process_light_in_direction(const vector2d_t player, const vector2d_t dir, const vector2d_t diagonal_check, const vector2d_t reverse_check, const int light_radius)
Processes light in a specific direction and updates the revealed map_arr.
Definition draw_light.c:126
int check_and_process_tile(int x, int y, int *prev_wall_at, const vector2d_t dir, int j, const vector2d_t diagonal_check, const vector2d_t reverse_check)
This function checks if the tile at the given coordinates is valid and processes it.
Definition draw_light.c:88
void draw_light_on_player(map_tile_t *arr1, map_tile_t *arr2, int height, int width, vector2d_t player, const int light_radius)
Draws light around the player.
Definition draw_light.c:156
Exposes functions for drawing light on player.
2-dimensional vector struct
Definition common.h:164