diff --git a/includes/air.h b/includes/air.h index 821d9fbb0..dfa417c01 100644 --- a/includes/air.h +++ b/includes/air.h @@ -5,6 +5,7 @@ extern float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread extern float gravx[YRES/CELL][XRES/CELL]; extern float gravy[YRES/CELL][XRES/CELL]; +extern unsigned gravmask[YRES/CELL][XRES/CELL]; extern float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread extern float th_gravmap[YRES/CELL][XRES/CELL]; diff --git a/includes/graphics.h b/includes/graphics.h index d228e83e9..50d8ab179 100644 --- a/includes/graphics.h +++ b/includes/graphics.h @@ -110,6 +110,8 @@ void draw_icon(pixel *vid_buf, int x, int y, char ch, int flag); void draw_air(pixel *vid); +void draw_grav_zones(pixel *vid); + void draw_grav(pixel *vid); void draw_line(pixel *vid, int x1, int y1, int x2, int y2, int r, int g, int b, int a); diff --git a/includes/misc.h b/includes/misc.h index 2ca0ac6da..51d7b98ce 100644 --- a/includes/misc.h +++ b/includes/misc.h @@ -71,6 +71,8 @@ int cpu_check(void); void HSV_to_RGB(int h,int s,int v,int *r,int *g,int *b); void RGB_to_HSV(int r,int g,int b,int *h,int *s,int *v); + +void membwand(void * dest, void * src, size_t destsize, size_t srcsize); // a b // c d struct matrix2d { diff --git a/includes/powder.h b/includes/powder.h index c0cf8b9db..86b0967cd 100644 --- a/includes/powder.h +++ b/includes/powder.h @@ -23,7 +23,7 @@ #define UI_WALLSTART 222 #define UI_ACTUALSTART 122 -#define UI_WALLCOUNT 20 +#define UI_WALLCOUNT 21 #define WL_WALLELEC 122 #define WL_EWALL 123 @@ -40,6 +40,7 @@ #define WL_ALLOWSOLID 133 #define WL_ALLOWALLELEC 134 #define WL_EHOLE 135 +#define WL_GRAV 142 #define SPC_AIR 236 #define SPC_HEAT 237 @@ -832,6 +833,7 @@ static wall_type wtypes[] = {PIXPACK(0x303030), PIXPACK(0x000000), -1, "Vacuum, reduces air pressure."}, {PIXPACK(0x579777), PIXPACK(0x000000), 1, "Wall. Indestructible. Blocks liquids and solids, allows gasses"}, {PIXPACK(0x000000), PIXPACK(0x000000), -1, "Drag tool"}, + {PIXPACK(0xFFEE00), PIXPACK(0xAA9900), 4, "Gravity wall"}, }; #define CHANNELS ((int)(MAX_TEMP-73.15f)/100+2) @@ -839,6 +841,8 @@ particle portalp[CHANNELS][8][80]; const particle emptyparticle; int wireless[CHANNELS][2]; +extern int gravwl_timeout; + extern int isplayer; extern float player[27]; @@ -913,4 +917,6 @@ void orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]); void orbitalparts_set(int *block1, int *block2, int resblock1[], int resblock2[]); +void gravity_mask(); + #endif diff --git a/src/air.c b/src/air.c index 63eaa4908..f17f9c9a0 100644 --- a/src/air.c +++ b/src/air.c @@ -7,6 +7,7 @@ float kernel[9]; float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread float gravx[YRES/CELL][XRES/CELL]; float gravy[YRES/CELL][XRES/CELL]; +unsigned gravmask[YRES/CELL][XRES/CELL]; float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread float th_gravmap[YRES/CELL][XRES/CELL]; diff --git a/src/graphics.c b/src/graphics.c index aab77ab7b..669086a3f 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -656,13 +656,17 @@ void draw_tool(pixel *vid_buf, int b, int sl, int sr, unsigned pc, unsigned iswa int draw_tool_xy(pixel *vid_buf, int x, int y, int b, unsigned pc) { int i, j, c; + pixel gc; if (x > XRES-26 || x < 0) return 26; if (b>=UI_WALLSTART) { int ds = 0; if (b-UI_WALLSTART>=0 && b-UI_WALLSTART=UI_WALLCOUNT) continue; pc = wtypes[wt].colour; + gc = wtypes[wt].eglow; // standard wall patterns if (wtypes[wt].drawstyle==1) @@ -3214,6 +3251,17 @@ void draw_walls(pixel *vid) for (i=0; i= size) goto version1; @@ -1060,6 +1062,7 @@ corrupt: void clear_sim(void) { + int x, y; memset(bmap, 0, sizeof(bmap)); memset(emap, 0, sizeof(emap)); memset(signs, 0, sizeof(signs)); @@ -1080,6 +1083,15 @@ void clear_sim(void) memset(fire_r, 0, sizeof(fire_r)); memset(fire_g, 0, sizeof(fire_g)); memset(fire_b, 0, sizeof(fire_b)); + memset(gravmask, 0xFF, sizeof(gravmask)); + memset(gravy, 0, sizeof(gravy)); + memset(gravx, 0, sizeof(gravx)); + for(x = 0; x < XRES/CELL; x++){ + for(y = 0; y < YRES/CELL; y++){ + hv[y][x] = 273.15f+22.0f; //Set to room temperature + } + } + gravity_mask(); } // stamps library @@ -1758,6 +1770,12 @@ int main(int argc, char *argv[]) #ifdef OpenGL ClearScreen(); #else + if(gravwl_timeout) + { + if(gravwl_timeout==1) + gravity_mask(); + gravwl_timeout--; + } if (cmode==CM_VEL || cmode==CM_PRESS || cmode==CM_CRACK || (cmode==CM_HEAT && aheat_enable))//air only gets drawn in these modes { draw_air(vid_buf); @@ -1788,6 +1806,8 @@ int main(int argc, char *argv[]) draw_walls(vid_buf); update_particles(vid_buf); //update everything draw_parts(vid_buf); //draw particles + if(sl == WL_GRAV+100 || sr == WL_GRAV+100) + draw_grav_zones(vid_buf); if(ngrav_enable){ pthread_mutex_lock(&gravmutex); @@ -1803,6 +1823,9 @@ int main(int argc, char *argv[]) } } pthread_mutex_unlock(&gravmutex); + //Apply the gravity mask + membwand(gravy, gravmask, sizeof(gravy), sizeof(gravmask)); + membwand(gravx, gravmask, sizeof(gravx), sizeof(gravmask)); } if (!sys_pause||framerender) //Only update if not paused diff --git a/src/misc.c b/src/misc.c index f2b713f74..2c84baf97 100644 --- a/src/misc.c +++ b/src/misc.c @@ -635,5 +635,15 @@ void RGB_to_HSV(int r,int g,int b,int *h,int *s,int *v)//convert 0-255 RGB value *v = (int)(255.0*x); } } + +void membwand(void * destv, void * srcv, size_t destsize, size_t srcsize) +{ + size_t i; + unsigned char * dest = destv; + unsigned char * src = srcv; + for(i = 0; i < destsize; i++){ + dest[i] = dest[i] & src[i%srcsize]; + } +} vector2d v2d_zero = {0,0}; matrix2d m2d_identity = {1,0,0,1}; diff --git a/src/powder.c b/src/powder.c index 5b3e03c11..adb5cb713 100644 --- a/src/powder.c +++ b/src/powder.c @@ -5,6 +5,8 @@ #include #include +int gravwl_timeout = 0; + int isplayer = 0; float player[27]; //[0] is a command cell, [3]-[18] are legs positions, [19] is index, [19]-[26] are accelerations float player2[27]; @@ -2428,6 +2430,10 @@ int create_parts(int x, int y, int rx, int ry, int c) b = WL_FANHELPER; dw = 1; } + if (wall == WL_GRAV) + { + gravwl_timeout = 60; + } if (dw==1) { rx = rx/CELL; @@ -2784,4 +2790,90 @@ inline void orbitalparts_set(int *block1, int *block2, int resblock1[], int resb *block1 = block1tmp; *block2 = block2tmp; } - +void grav_mask_r(int x, int y, char checkmap[YRES/CELL][XRES/CELL], char shape[YRES/CELL][XRES/CELL], char *shapeout) +{ + if(x < 0 || x >= XRES/CELL || y < 0 || y >= YRES/CELL) + return; + if(x == 0 || y ==0 || y == (YRES/CELL)-1 || x == (XRES/CELL)-1) + *shapeout = 1; + checkmap[y][x] = 1; + shape[y][x] = 1; + if(x-1 >= 0 && !checkmap[y][x-1] && bmap[y][x-1]!=WL_GRAV) + grav_mask_r(x-1, y, checkmap, shape, shapeout); + if(y-1 >= 0 && !checkmap[y-1][x] && bmap[y-1][x]!=WL_GRAV) + grav_mask_r(x, y-1, checkmap, shape, shapeout); + if(x+1 < XRES/CELL && !checkmap[y][x+1] && bmap[y][x+1]!=WL_GRAV) + grav_mask_r(x+1, y, checkmap, shape, shapeout); + if(y+1 < YRES/CELL && !checkmap[y+1][x] && bmap[y+1][x]!=WL_GRAV) + grav_mask_r(x, y+1, checkmap, shape, shapeout); + return; +} +struct mask_el { + char *shape; + char shapeout; + void *next; +}; +typedef struct mask_el mask_el; +void mask_free(mask_el *c_mask_el){ + if(c_mask_el==NULL) + return; + if(c_mask_el->next!=NULL) + mask_free(c_mask_el->next); + free(c_mask_el->shape); + free(c_mask_el); +} +void gravity_mask() +{ + char checkmap[YRES/CELL][XRES/CELL]; + int x = 0, y = 0; + mask_el *t_mask_el = NULL; + mask_el *c_mask_el = NULL; + memset(checkmap, 0, sizeof(checkmap)); + for(x = 0; x < XRES/CELL; x++) + { + for(y = 0; y < YRES/CELL; y++) + { + if(bmap[y][x]!=WL_GRAV && checkmap[y][x] == 0) + { + //Create a new shape + if(t_mask_el==NULL){ + t_mask_el = malloc(sizeof(mask_el)); + t_mask_el->shape = malloc((XRES/CELL)*(YRES/CELL)); + memset(t_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); + t_mask_el->shapeout = 0; + t_mask_el->next = NULL; + c_mask_el = t_mask_el; + } else { + c_mask_el->next = malloc(sizeof(mask_el)); + c_mask_el = c_mask_el->next; + c_mask_el->shape = malloc((XRES/CELL)*(YRES/CELL)); + memset(c_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); + c_mask_el->shapeout = 0; + c_mask_el->next = NULL; + } + //Fill the shape + grav_mask_r(x, y, checkmap, c_mask_el->shape, &c_mask_el->shapeout); + } + } + } + c_mask_el = t_mask_el; + memset(gravmask, 0, sizeof(gravmask)); + while(c_mask_el!=NULL) + { + char *cshape = c_mask_el->shape; + for(x = 0; x < XRES/CELL; x++) + { + for(y = 0; y < YRES/CELL; y++) + { + if(cshape[y*(XRES/CELL)+x]){ + if(c_mask_el->shapeout) + gravmask[y][x] = 0xFFFFFFFF; + else + gravmask[y][x] = 0x00000000; + } + } + } + c_mask_el = c_mask_el->next; + } + mask_free(t_mask_el); +}