00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026
00027 #include "crogue.h"
00028
00029 #define MAX_LIGHT_RADIUS 15
00030 #define MAX_LIGHT_RADIUS_SQUARED 225
00031
00032 static void calc_light_tile(int x, int y);
00033
00034
00035 void calc_light(void)
00036
00037
00038
00039
00040 {
00041 int xi, yi;
00042 int min_x, min_y;
00043 int max_x, max_y;
00044
00045 min_x = w->plr.x - MAX_LIGHT_RADIUS;
00046 if(min_x < 0) min_x = 0;
00047 max_x = w->plr.x + MAX_LIGHT_RADIUS;
00048 if(max_x >= MAPSIZE_X) max_x = MAPSIZE_X - 1;
00049 min_y = w->plr.y - MAX_LIGHT_RADIUS;
00050 if(min_y < 0) min_y = 0;
00051 max_y = w->plr.y + MAX_LIGHT_RADIUS;
00052 if(max_y >= MAPSIZE_Y) max_y = MAPSIZE_Y - 1;
00053
00054 for(yi=min_y; yi<=max_y; yi++)
00055 for(xi=min_x; xi<=max_x; xi++)
00056 {
00057 calc_light_tile(xi, yi);
00058 }
00059 }
00060
00061
00062 static void calc_light_tile(int x, int y)
00063 {
00064 int distance;
00065 int is_in_range;
00066 int change;
00067
00068 distance = distancesquare(x, y, w->plr.x, w->plr.y);
00069
00070 if(distance <= w->plr.extrinsic[STAT_LIGHTRADIUS])
00071 is_in_range = 1;
00072 else
00073 is_in_range = 0;
00074
00075
00076 if(w->t[y][x].flags & TFLAG_LIT)
00077 {
00078 if(w->t[y][x].flags & TFLAG_INTRINSIC_LIGHT)
00079 {
00080 if( distance > MAX_LIGHT_RADIUS_SQUARED ||
00081 !tracevision(x, y, w->plr.x, w->plr.y) )
00082 {
00083 w->t[y][x].flags &= ~TFLAG_LIT;
00084 draw_tile(x, y);
00085 }
00086 } else {
00087 if( !is_in_range ||
00088 !tracevision(x, y, w->plr.x, w->plr.y) )
00089 {
00090 w->t[y][x].flags &= ~TFLAG_LIT;
00091 draw_tile(x, y);
00092 }
00093 }
00094 }
00095
00096 else if(!(w->t[y][x].flags & TFLAG_LIT))
00097 {
00098 change = 0;
00099
00100 if(w->t[y][x].flags & TFLAG_INTRINSIC_LIGHT)
00101 {
00102 if(distance > MAX_LIGHT_RADIUS_SQUARED) return;
00103
00104 if(TILEDESC(w->t[y][x]).transparent) {
00105 change = tracevision(x, y, w->plr.x, w->plr.y);
00106 } else if(is_in_range) {
00107 change = tracevision(x, y, w->plr.x, w->plr.y);
00108 } else {
00109 int xd=x, yd=y;
00110
00111 if(w->plr.x > x) xd++;
00112 else if(w->plr.x < x) xd--;
00113 if(w->plr.y > y) yd++;
00114 else if(w->plr.y < y) yd--;
00115
00116 if(w->t[yd][xd].flags & TFLAG_INTRINSIC_LIGHT)
00117 change = tracevision(x, y, w->plr.x, w->plr.y);
00118 }
00119 }
00120 else
00121 {
00122 if(is_in_range && tracevision(x, y, w->plr.x, w->plr.y))
00123 change = 1;
00124 }
00125 if(change)
00126 {
00127 w->t[y][x].flags |= (TFLAG_LIT | TFLAG_EXPLORED);
00128 draw_tile(x, y);
00129 }
00130 }
00131 }
00132
00133
00134 ushort tracevision(sshort x1, sshort y1, sshort x2, sshort y2)
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 {
00145 sshort xdist, ydist;
00146 sshort xi, yi;
00147 sshort xdir, ydir;
00148
00149 xdir=(x1<x2)?1 : (x1==x2)?0:-1;
00150 ydir=(y1<y2)?1 : (y1==y2)?0:-1;
00151
00152
00153
00154
00155 if( !w->tiledescs[w->t[y1][x1].type].transparent ) {
00156 x1 += xdir;
00157 y1 += ydir;
00158 }
00159
00160 xdist=abs(x1-x2); ydist=abs(y1-y2);
00161 xi=(ydist/2); yi=(xdist/2);
00162
00163 while(x1!=x2 || y1!=y2)
00164 {
00165 if( !w->tiledescs[w->t[y1][x1].type].transparent )
00166 return 0;
00167
00168 xi+=xdist; yi+=ydist;
00169 if(xi>=ydist) {
00170 x1 += xdir;
00171 xi -= ydist;
00172 }
00173 if(yi>=xdist) {
00174 y1 += ydir;
00175 yi -= xdist;
00176 }
00177 }
00178
00179 return 1;
00180 }
00181
00182
00183 void illuminate(sint x, sint y, sint radiussquared)
00184
00185
00186
00187
00188 {
00189 int i, j;
00190
00191 for(i=0; i<MAPSIZE_Y; i++)
00192 for(j=0; j<MAPSIZE_X; j++)
00193 {
00194 if( (x-j)*(x-j)+(y-i)*(y-i) <= radiussquared && tracevision(j,i,x,y) )
00195 w->t[i][j].flags |= TFLAG_INTRINSIC_LIGHT;
00196 }
00197 }
00198
00199