diff options
| author | chaos.powdertoy.co.uk <admin@powdertoy.co.uk> | 2012-03-15 02:14:17 (GMT) |
|---|---|---|
| committer | chaos.powdertoy.co.uk <admin@powdertoy.co.uk> | 2012-03-15 02:14:17 (GMT) |
| commit | 6254d4064dff390ce92c1803cdf9d9fb58a62e79 (patch) | |
| tree | c95626a1f5ea562d7a4dc5c58a02b0db3c902043 /src/powder.c | |
| parent | 4fc0f750221a33a9ac922022ee58ccda6bbe3440 (diff) | |
| parent | 7a454d4d729a5715a7c1e71dfbaf303471bf8d1f (diff) | |
| download | powder-6254d4064dff390ce92c1803cdf9d9fb58a62e79.zip powder-6254d4064dff390ce92c1803cdf9d9fb58a62e79.tar.gz | |
Merge branch 'master' of github.com:FacialTurd/The-Powder-Toy
Diffstat (limited to 'src/powder.c')
| -rw-r--r-- | src/powder.c | 271 |
1 files changed, 134 insertions, 137 deletions
diff --git a/src/powder.c b/src/powder.c index c869e59..233fa32 100644 --- a/src/powder.c +++ b/src/powder.c @@ -1,6 +1,7 @@ #include <stdint.h> #include <math.h> #include <defines.h> +#include <squares.h> #include <powder.h> #include <air.h> #include <misc.h> @@ -317,43 +318,17 @@ int try_move(int i, int x, int y, int nx, int ny) if (parts[i].type==PT_NEUT && (ptypes[r&0xFF].properties&PROP_NEUTABSORB)) { - parts[i].type=PT_NONE; + kill_part(i); return 0; } if ((r&0xFF)==PT_VOID || (r&0xFF)==PT_PVOD) //this is where void eats particles { - if (parts[i].type == PT_STKM) - { - player.spwn = 0; - } - if (parts[i].type == PT_STKM2) - { - player2.spwn = 0; - } - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - parts[i].type=PT_NONE; + kill_part(i); return 0; } if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles { - if (parts[i].type == PT_STKM) - { - player.spwn = 0; - } - if (parts[i].type == PT_STKM2) - { - player2.spwn = 0; - } - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - parts[i].type=PT_NONE; + kill_part(i); if (!legacy_enable) { parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; @@ -363,7 +338,7 @@ int try_move(int i, int x, int y, int nx, int ny) } if (((r&0xFF)==PT_WHOL||(r&0xFF)==PT_NWHL) && parts[i].type==PT_ANAR) //whitehole eats anar { - parts[i].type=PT_NONE; + kill_part(i); if (!legacy_enable) { parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP); @@ -414,8 +389,10 @@ int try_move(int i, int x, int y, int nx, int ny) // try to move particle, and if successful update pmap and parts[i].x,y int do_move(int i, int x, int y, float nxf, float nyf) { - int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f); - int result = try_move(i, x, y, nx, ny); + int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f), result; + if (parts[i].type == PT_NONE) + return 0; + result = try_move(i, x, y, nx, ny); if (result) { int t = parts[i].type; @@ -612,6 +589,9 @@ void kill_part(int i)//kills particle number i { int x, y; + if (parts[i].type == PT_NONE) //This shouldn't happen anymore, but it's here just in case + return; + x = (int)(parts[i].x+0.5f); y = (int)(parts[i].y+0.5f); if (parts[i].type == PT_STKM) @@ -1831,8 +1811,14 @@ void update_particles_i(pixel *vid, int start, int inc) if (ptypes[t].diffusion)//the random diffusion that gasses have { +#ifdef REALISTIC + //The magic number controlls diffusion speed + parts[i].vx += 0.05*squares[(unsigned int)round(parts[i].temp)]*ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f); + parts[i].vy += 0.05*squares[(unsigned int)round(parts[i].temp)]*ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f); +#else parts[i].vx += ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f); parts[i].vy += ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f); +#endif } j = surround_space = nt = 0;//if nt is 1 after this, then there is a particle around the current particle, that is NOT the current particle's type, for water movement. @@ -1863,8 +1849,8 @@ void update_particles_i(pixel *vid, int start, int inc) //heat transfer code h_count = 0; -#ifdef REALHEAT - if (t&&(t!=PT_HSWC||parts[i].life==10)) +#ifdef REALISTIC + if (t&&(t!=PT_HSWC||parts[i].life==10)&&ptypes[t].hconduct) { float c_Cm = 0.0f; #else @@ -1874,12 +1860,25 @@ void update_particles_i(pixel *vid, int start, int inc) #endif if (aheat_enable) { +#ifdef REALISTIC + c_heat = parts[i].temp*96.645/ptypes[t].hconduct*fabs(ptypes[t].weight) + + hv[y/CELL][x/CELL]*100*(pv[y/CELL][x/CELL]+273.15f)/256; + c_Cm = 96.645/ptypes[t].hconduct*fabs(ptypes[t].weight) + + 100*(pv[y/CELL][x/CELL]+273.15f)/256; + pt = c_heat/c_Cm; + pt = restrict_flt(pt, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP); + parts[i].temp = pt; + //Pressure increase from heat (temporary) + pv[y/CELL][x/CELL] += (pt-hv[y/CELL][x/CELL])*0.004; + hv[y/CELL][x/CELL] = pt; +#else c_heat = (hv[y/CELL][x/CELL]-parts[i].temp)*0.04; c_heat = restrict_flt(c_heat, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP); parts[i].temp += c_heat; hv[y/CELL][x/CELL] -= c_heat; +#endif } - c_heat = 0.0f; + c_heat = 0.0f; c_Cm = 0.0f; for (j=0; j<8; j++) { surround_hconduct[j] = i; @@ -1892,7 +1891,7 @@ void update_particles_i(pixel *vid, int start, int inc) &&(rt!=PT_FILT||(t!=PT_BRAY&&t!=PT_PHOT&&t!=PT_BIZR&&t!=PT_BIZRG))) { surround_hconduct[j] = r>>8; -#ifdef REALHEAT +#ifdef REALISTIC c_heat += parts[r>>8].temp*96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); c_Cm += 96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); #else @@ -1901,7 +1900,7 @@ void update_particles_i(pixel *vid, int start, int inc) h_count++; } } -#ifdef REALHEAT +#ifdef REALISTIC if (t == PT_PHOT) pt = (c_heat+parts[i].temp*96.645)/(c_Cm+96.645); else @@ -2196,7 +2195,7 @@ killed: clear_y = (int)(clear_yf+0.5f); break; } - if (fin_x<CELL || fin_y<CELL || fin_x>=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT || !eval_move(t,fin_x,fin_y,NULL)))) + if (fin_x<CELL || fin_y<CELL || fin_x>=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || !eval_move(t,fin_x,fin_y,NULL)))) { // found an obstacle clear_xf = fin_xf-dx; @@ -2205,7 +2204,8 @@ killed: clear_y = (int)(clear_yf+0.5f); break; } - + if (bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT && emap[fin_y/CELL][fin_x/CELL]<8) + set_emap(fin_x/CELL, fin_y/CELL); } } @@ -2263,13 +2263,15 @@ killed: if (stagnant)//FLAG_STAGNANT set, was reflected on previous frame { // cast coords as int then back to float for compatibility with existing saves - if (!do_move(i, x, y, (float)fin_x, (float)fin_y)) { + if (!do_move(i, x, y, (float)fin_x, (float)fin_y) && parts[i].type) { kill_part(i); continue; } } else if (!do_move(i, x, y, fin_xf, fin_yf)) { + if (parts[i].type == PT_NONE) + continue; // reflection parts[i].flags |= FLAG_STAGNANT; if (t==PT_NEUT && 100>(rand()%1000)) @@ -2329,6 +2331,8 @@ killed: // gasses and solids (but not powders) if (!do_move(i, x, y, fin_xf, fin_yf)) { + if (parts[i].type == PT_NONE) + continue; // can't move there, so bounce off // TODO if (fin_x>x+ISTP) fin_x=x+ISTP; @@ -2360,6 +2364,8 @@ killed: // liquids and powders if (!do_move(i, x, y, fin_xf, fin_yf)) { + if (parts[i].type == PT_NONE) + continue; if (fin_x!=x && do_move(i, x, y, fin_xf, clear_yf)) { parts[i].vx *= ptypes[t].collision; @@ -2703,7 +2709,7 @@ void create_box(int x1, int y1, int x2, int y2, int c, int flags) } for (j=y1; j<=y2; j++) for (i=x1; i<=x2; i++) - create_parts(i, j, 0, 0, c, flags); + create_parts(i, j, 0, 0, c, flags, 1); } int flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap) @@ -2828,7 +2834,7 @@ int flood_parts(int x, int y, int fullc, int cm, int bm, int flags) if (create_part(-1,x, y, fullc)==-1) return 0; } - else if (!create_parts(x, y, 0, 0, fullc, flags)) + else if (!create_parts(x, y, 0, 0, fullc, flags, 1)) return 0; } // fill children @@ -2951,9 +2957,9 @@ int create_part_add_props(int p, int x, int y, int tv, int rx, int ry) } //this creates particles from a brush, don't use if you want to create one particle -int create_parts(int x, int y, int rx, int ry, int c, int flags) +int create_parts(int x, int y, int rx, int ry, int c, int flags, int fill) { - int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p;//n; + int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p, fn; int wall = c - 100; if (c==SPC_WIND || c==PT_FIGH) @@ -2963,6 +2969,8 @@ int create_parts(int x, int y, int rx, int ry, int c, int flags) prop_edit_ui(vid_buf, x, y); return 0; } + if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV) + fill = 1; for (r=UI_ACTUALSTART; r<=UI_ACTUALSTART+UI_WALLCOUNT; r++) { if (wall==r) @@ -3054,114 +3062,102 @@ int create_parts(int x, int y, int rx, int ry, int c, int flags) return 1; } - //eraser - if (c == 0 && !(flags&BRUSH_REPLACEMODE)) - { - if (rx==0&&ry==0) - { - delete_part(x, y, 0); - } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - delete_part(x+i, y+j, 0); - return 1; - } + if (c == 0 && !(flags&BRUSH_REPLACEMODE)) // delete + fn = 0; + else if ((flags&BRUSH_SPECIFIC_DELETE) && !(flags&BRUSH_REPLACEMODE)) // specific delete + fn = 1; + else if (flags&BRUSH_REPLACEMODE) // replace + fn = 2; + else // normal draw + fn = 3; - //specific deletion - if ((flags&BRUSH_SPECIFIC_DELETE)&& !(flags&BRUSH_REPLACEMODE)) + if (rx<=0) //workaround for rx == 0 crashing. todo: find a better fix later. { - if (rx==0&&ry==0) - { - delete_part(x, y, flags); - } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - delete_part(x+i, y+j, flags); - return 1; + for (j = y - ry; j <= y + ry; j++) + if (create_parts2(fn,x,j,c,rx,ry,flags)) + f = 1; } - - //why do these need a special if - if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV) + else { - if (rx==0&&ry==0) - { - create_part(-2, x, y, c); + int tempy = y, i, j, jmax, oldy; + if (CURRENT_BRUSH == TRI_BRUSH) + tempy = y + ry; + for (i = x - rx; i <= x; i++) { + oldy = tempy; + while (InCurrentBrush(i-x,tempy-y,rx,ry)) + tempy = tempy - 1; + tempy = tempy + 1; + jmax = 2*y - tempy; + if (CURRENT_BRUSH == TRI_BRUSH) + jmax = y + ry; + if (fill) + { + for (j = tempy; j <= jmax; j++) { + if (create_parts2(fn,i,j,c,rx,ry,flags)) + f = 1; + if (create_parts2(fn,2*x-i,j,c,rx,ry,flags)) + f = 1; + } + } + else + { + if ((oldy != tempy && CURRENT_BRUSH != SQUARE_BRUSH) || i == x-rx) + oldy--; + if (CURRENT_BRUSH == TRI_BRUSH) + oldy = tempy; + for (j = tempy; j <= oldy+1; j++) { + int i2 = 2*x-i, j2 = 2*y-j; + if (CURRENT_BRUSH == TRI_BRUSH) + j2 = y+ry; + if (create_parts2(fn,i,j,c,rx,ry,flags)) + f = 1; + if (create_parts2(fn,i2,j,c,rx,ry,flags)) + f = 1; + if (create_parts2(fn,i,j2,c,rx,ry,flags)) + f = 1; + if (create_parts2(fn,i2,j2,c,rx,ry,flags)) + f = 1; + } + } } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - { - if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES) - continue; - if (!REPLACE_MODE) - create_part(-2, x+i, y+j, c); - else if ((pmap[y+j][x+i]&0xFF)==SLALT&&SLALT!=0) - create_part(-2, x+i, y+j, c); - } - return 1; } + return !f; +} - if (flags&BRUSH_REPLACEMODE) +int create_parts2(int f, int x, int y, int c, int rx, int ry, int flags) +{ + if (f == 0) //delete + delete_part(x, y, 0); + else if (f == 1) //specific delete + delete_part(x, y, flags); + else if (f == 2) //replace mode { - if (rx==0&&ry==0) + if (x<0 || y<0 || x>=XRES || y>=YRES) + return 0; + if ((pmap[y][x]&0xFF)!=SLALT&&SLALT!=0) + return 0; + if ((pmap[y][x])) { - if ((pmap[y][x]&0xFF)==SLALT || SLALT==0) - { - if ((pmap[y][x])) - { - delete_part(x, y, 0); - if (c!=0) - create_part_add_props(-2, x, y, c, rx, ry); - } - } + delete_part(x, y, 0); + if (c!=0) + create_part_add_props(-2, x, y, c, rx, ry); } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - { - if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES) - continue; - if ((pmap[y+j][x+i]&0xFF)!=SLALT&&SLALT!=0) - continue; - if ((pmap[y+j][x+i])) - { - delete_part(x+i, y+j, 0); - if (c!=0) - create_part_add_props(-2, x+i, y+j, c, rx, ry); - } - } - return 1; - } - //else, no special modes, draw element like normal. - if (rx==0&&ry==0)//workaround for 1pixel brush/floodfill crashing. todo: find a better fix later. - { + else if (f == 3) //normal draw if (create_part_add_props(-2, x, y, c, rx, ry)==-1) - f = 1; - } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - if (create_part_add_props(-2, x+i, y+j, c, rx, ry)==-1) - f = 1; - return !f; + return 1; + return 0; } + int InCurrentBrush(int i, int j, int rx, int ry) { switch(CURRENT_BRUSH) { case CIRCLE_BRUSH: - return (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2)); + return (pow((double)i,2)*pow((double)ry,2)+pow((double)j,2)*pow((double)rx,2)<=pow((double)rx,2)*pow((double)ry,2)); break; case SQUARE_BRUSH: - return (i*j<=ry*rx); + return (abs(i) <= rx && abs(j) <= ry); break; case TRI_BRUSH: return (j <= ry ) && ( j >= (((-2.0*ry)/rx)*i) -ry) && ( j >= (((-2.0*ry)/(-rx))*i)-ry ) ; @@ -3184,7 +3180,7 @@ int get_brush_flags() } void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags) { - int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; + int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy, fill = 1; float e, de; if (c==SPC_PROP) return; @@ -3218,9 +3214,10 @@ void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flag for (x=x1; x<=x2; x++) { if (cp) - create_parts(y, x, rx, ry, c, flags); + create_parts(y, x, rx, ry, c, flags, fill); else - create_parts(x, y, rx, ry, c, flags); + create_parts(x, y, rx, ry, c, flags, fill); + fill = 0; e += de; if (e >= 0.5f) { @@ -3229,9 +3226,9 @@ void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flag && ((y1<y2) ? (y<=y2) : (y>=y2))) { if (cp) - create_parts(y, x, rx, ry, c, flags); + create_parts(y, x, rx, ry, c, flags, fill); else - create_parts(x, y, rx, ry, c, flags); + create_parts(x, y, rx, ry, c, flags, fill); } e -= 1.0f; } |
