diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index 1f4aed872..af6826ee1 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -1483,6 +1483,27 @@ void Renderer::render_parts() draw_line(cplayer->legs[0], cplayer->legs[1], cplayer->legs[4], cplayer->legs[5], legr, legg, legb, 255); draw_line(nx, ny+3, cplayer->legs[8], cplayer->legs[9], legr, legg, legb, 255); draw_line(cplayer->legs[8], cplayer->legs[9], cplayer->legs[12], cplayer->legs[13], legr, legg, legb, 255); + if (cplayer->rocketBoots) + { + for (int leg=0; leg<2; leg++) + { + int nx = cplayer->legs[leg*8+4], ny = cplayer->legs[leg*8+5]; + int colr = 255, colg = 0, colb = 255; + if (((int)(cplayer->comm)&0x04) == 0x04 || (((int)(cplayer->comm)&0x01) == 0x01 && leg==0) || (((int)(cplayer->comm)&0x02) == 0x02 && leg==1)) + blendpixel(nx, ny, 0, 255, 0, 255); + else + blendpixel(nx, ny, 255, 0, 0, 255); + blendpixel(nx+1, ny, colr, colg, colb, 223); + blendpixel(nx-1, ny, colr, colg, colb, 223); + blendpixel(nx, ny+1, colr, colg, colb, 223); + blendpixel(nx, ny-1, colr, colg, colb, 223); + + blendpixel(nx+1, ny-1, colr, colg, colb, 112); + blendpixel(nx-1, ny-1, colr, colg, colb, 112); + blendpixel(nx+1, ny+1, colr, colg, colb, 112); + blendpixel(nx-1, ny+1, colr, colg, colb, 112); + } + } #endif } if(pixel_mode & PMODE_FLAT) diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 577da9343..1ab97fdff 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -112,12 +112,14 @@ int Simulation::Load(int fullX, int fullY, GameSave * save) Element_STKM::STKM_init_legs(this, &player, i); player.spwn = 1; player.elem = PT_DUST; + player.rocketBoots = false; } else if (parts[i].type == PT_STKM2) { Element_STKM::STKM_init_legs(this, &player2, i); player2.spwn = 1; player2.elem = PT_DUST; + player2.rocketBoots = false; } else if (parts[i].type == PT_FIGH) { @@ -3052,6 +3054,7 @@ int Simulation::create_part(int p, int x, int y, int tv) Element_STKM::STKM_init_legs(this, &player, i); player.spwn = 1; player.elem = PT_DUST; + player.rocketBoots = false; } else { @@ -3073,6 +3076,7 @@ int Simulation::create_part(int p, int x, int y, int tv) Element_STKM::STKM_init_legs(this, &player2, i); player2.spwn = 1; player2.elem = PT_DUST; + player2.rocketBoots = false; } else { @@ -3108,6 +3112,7 @@ int Simulation::create_part(int p, int x, int y, int tv) Element_STKM::STKM_init_legs(this, &fighters[fcount], i); fighters[fcount].spwn = 1; fighters[fcount].elem = PT_DUST; + fighters[fcount].rocketBoots = false; fighcount++; return i; @@ -3560,8 +3565,22 @@ void Simulation::update_particles_i(int start, int inc) rt = pmap[ady][adx]; if (!rt || (rt&0xFF)==PT_LIFE) { - gol2[ady][adx][golnum] ++; + //the total neighbor count is in 0 gol2[ady][adx][0] ++; + //insert golnum into neighbor table + for ( i=1; i<9; i++) + { + if (!gol2[ady][adx][i]) + { + gol2[ady][adx][i] = (golnum<<4)+1; + break; + } + else if((gol2[ady][adx][i]>>4)==golnum) + { + gol2[ady][adx][i]++; + break; + } + } } } } @@ -3585,21 +3604,25 @@ void Simulation::update_particles_i(int start, int inc) if (!r) { //Find which type we can try and create - for (golnum = 1; golnum<=NGOL; golnum++) + int creategol = 0xFF; + for ( i=1; i<9; i++) { - if (grule[golnum][neighbors]>=2 && gol2[ny][nx][golnum]>=(neighbors%2)+neighbors/2) + if (!gol2[ny][nx][i]) break; + golnum = (gol2[ny][nx][i]>>4); + if (grule[golnum][neighbors]>=2 && (gol2[ny][nx][i]&0xF)>=(neighbors%2)+neighbors/2) { - create_part(-1, nx, ny, PT_LIFE|((golnum-1)<<8)); - break; + if (golnum>8].tmp==grule[golnum][9]-1) parts[r>>8].tmp --; } - for ( z = 0; z<=NGOL; z++) + for ( z = 0; z<9; z++) gol2[ny][nx][z] = 0;//this improves performance A LOT compared to the memset, i was getting ~23 more fps with this. } //we still need to kill things with 0 neighbors (higher state life) diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 9e9424f94..5ce0d1e5a 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -74,10 +74,9 @@ public: int emp_decor; //Gol sim int CGOL; - int ISGOL; int GSPEED; unsigned char gol[YRES][XRES]; - unsigned char gol2[YRES][XRES][NGOL+1]; + unsigned short gol2[YRES][XRES][9]; //Air sim float (*vx)[XRES/CELL]; float (*vy)[XRES/CELL]; diff --git a/src/simulation/Stickman.h b/src/simulation/Stickman.h index 0e9cd3c65..a62a747f1 100644 --- a/src/simulation/Stickman.h +++ b/src/simulation/Stickman.h @@ -10,6 +10,7 @@ struct playerst float accs[8]; //accelerations char spwn; //if stick man was spawned unsigned int frames; //frames since last particle spawn - used when spawning LIGH + bool rocketBoots; }; #endif diff --git a/src/simulation/elements/STKM.cpp b/src/simulation/elements/STKM.cpp index 52deee104..2323be328 100644 --- a/src/simulation/elements/STKM.cpp +++ b/src/simulation/elements/STKM.cpp @@ -74,6 +74,10 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { float dt = 0.9;///(FPSB*FPSB); //Delta time in square float gvx, gvy; float gx, gy, dl, dr; + float rocketBootsHeadEffect = 0.35f; + float rocketBootsFeetEffect = 0.15f; + float rocketBootsHeadEffectV = 0.3f;// stronger acceleration vertically, to counteract gravity + float rocketBootsFeetEffectV = 0.45f; if ((parts[i].ctype>0 && parts[i].ctypeelements[parts[i].ctype].Enabled && sim->elements[parts[i].ctype].Falldown>0) || parts[i].ctype==SPC_AIR || parts[i].ctype == PT_NEUT || parts[i].ctype == PT_PHOT || parts[i].ctype == PT_LIGH) playerp->elem = parts[i].ctype; @@ -123,6 +127,33 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { gvx += sim->gravx[((int)parts[i].y/CELL)*(XRES/CELL)+((int)parts[i].x/CELL)]; gvy += sim->gravy[((int)parts[i].y/CELL)*(XRES/CELL)+((int)parts[i].x/CELL)]; + float rbx = gvx; + float rby = gvy; + bool rbLowGrav = false; + float tmp = fmaxf(fabsf(rbx), fabsf(rby)); + if (tmp < 0.001f) + { + rbLowGrav = true; + rbx = -parts[i].vx; + rby = -parts[i].vy; + tmp = fmaxf(fabsf(rbx), fabsf(rby)); + } + if (tmp < 0.001f) + { + rbx = 0; + rby = 1.0f; + tmp = 1.0f; + } + float rbx1 = rbx/tmp, rby1 = rby/tmp;// scale so that the largest is 1.0 + tmp = 1.0f/sqrtf(rbx*rbx+rby*rby); + rbx *= tmp;// scale to a unit vector + rby *= tmp; + if (rbLowGrav) + { + rocketBootsHeadEffectV = rocketBootsHeadEffect; + rocketBootsFeetEffectV = rocketBootsFeetEffect; + } + parts[i].vx -= gvx*dt; //Head up! parts[i].vy -= gvy*dt; @@ -176,6 +207,7 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { //Go left if (((int)(playerp->comm)&0x01) == 0x01) { + bool moved = false; if (dl>dr) { if (!sim->eval_move(t, playerp->legs[4], playerp->legs[5], NULL)) @@ -184,6 +216,7 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { playerp->accs[3] = 3*gvx-3*gvy; playerp->accs[0] = -gvy; playerp->accs[1] = gvx; + moved = true; } } else @@ -194,6 +227,29 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { playerp->accs[7] = 3*gvx-3*gvy; playerp->accs[0] = -gvy; playerp->accs[1] = gvx; + moved = true; + } + } + if (!moved && playerp->rocketBoots) + { + parts[i].vx -= rocketBootsHeadEffect*rby; + parts[i].vy += rocketBootsHeadEffect*rbx; + playerp->accs[2] -= rocketBootsFeetEffect*rby; + playerp->accs[6] -= rocketBootsFeetEffect*rby; + playerp->accs[3] += rocketBootsFeetEffect*rbx; + playerp->accs[7] += rocketBootsFeetEffect*rbx; + for (int leg=0; leg<2; leg++) + { + if (leg==1 && (((int)(playerp->comm)&0x02) == 0x02)) + continue; + int footX = playerp->legs[leg*8+4], footY = playerp->legs[leg*8+5]; + int np = sim->create_part(-1, footX, footY, PT_PLSM); + if (np>=0) + { + parts[np].vx = parts[i].vx+rby*25; + parts[np].vy = parts[i].vy-rbx*25; + parts[np].life += 30; + } } } } @@ -201,6 +257,7 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { //Go right if (((int)(playerp->comm)&0x02) == 0x02) { + bool moved = false; if (dleval_move(t, playerp->legs[4], playerp->legs[5], NULL)) @@ -209,6 +266,7 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { playerp->accs[3] = -3*gvx-3*gvy; playerp->accs[0] = gvy; playerp->accs[1] = -gvx; + moved = true; } } else @@ -219,17 +277,75 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { playerp->accs[7] = -3*gvx-3*gvy; playerp->accs[0] = gvy; playerp->accs[1] = -gvx; + moved = true; + } + } + if (!moved && playerp->rocketBoots) + { + parts[i].vx += rocketBootsHeadEffect*rby; + parts[i].vy -= rocketBootsHeadEffect*rbx; + playerp->accs[2] += rocketBootsFeetEffect*rby; + playerp->accs[6] += rocketBootsFeetEffect*rby; + playerp->accs[3] -= rocketBootsFeetEffect*rbx; + playerp->accs[7] -= rocketBootsFeetEffect*rbx; + for (int leg=0; leg<2; leg++) + { + if (leg==0 && (((int)(playerp->comm)&0x01) == 0x01)) + continue; + int footX = playerp->legs[leg*8+4], footY = playerp->legs[leg*8+5]; + int np = sim->create_part(-1, footX, footY, PT_PLSM); + if (np>=0) + { + parts[np].vx = parts[i].vx-rby*25; + parts[np].vy = parts[i].vy+rbx*25; + parts[np].life += 30; + } } } } - //Jump - if (((int)(playerp->comm)&0x04) == 0x04 && - (!sim->eval_move(t, playerp->legs[4], playerp->legs[5], NULL) || !sim->eval_move(t, playerp->legs[12], playerp->legs[13], NULL))) + if (playerp->rocketBoots && ((int)(playerp->comm)&0x03) == 0x03) { - parts[i].vy -= 4*gvy; - playerp->accs[3] -= gvy; - playerp->accs[7] -= gvy; + // Pressing left and right simultaneously with rocket boots on slows the stickman down + // Particularly useful in zero gravity + parts[i].vx *= 0.5f; + parts[i].vy *= 0.5f; + playerp->accs[2] = playerp->accs[6] = 0; + playerp->accs[3] = playerp->accs[7] = 0; + } + + //Jump + if (((int)(playerp->comm)&0x04) == 0x04) + { + if (playerp->rocketBoots) + { + parts[i].vx -= rocketBootsHeadEffectV*rbx; + parts[i].vy -= rocketBootsHeadEffectV*rby; + playerp->accs[2] -= rocketBootsFeetEffectV*rbx; + playerp->accs[6] -= rocketBootsFeetEffectV*rbx; + playerp->accs[3] -= rocketBootsFeetEffectV*rby; + playerp->accs[7] -= rocketBootsFeetEffectV*rby; + for (int leg=0; leg<2; leg++) + { + int footX = playerp->legs[leg*8+4], footY = playerp->legs[leg*8+5]; + int np = sim->create_part(-1, footX, footY+1, PT_PLSM); + if (np>=0) + { + parts[np].vx = parts[i].vx+rbx*30; + parts[np].vy = parts[i].vy+rby*30; + parts[np].life += 10; + } + } + } + else if (!sim->eval_move(t, playerp->legs[4], playerp->legs[5], NULL) || !sim->eval_move(t, playerp->legs[12], playerp->legs[13], NULL)) + { + parts[i].vx -= 4*gvx; + parts[i].vy -= 4*gvy; + playerp->accs[2] -= gvx; + playerp->accs[6] -= gvx; + playerp->accs[3] -= gvy; + playerp->accs[7] -= gvy; + } } //Charge detector wall if foot inside @@ -255,7 +371,8 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { || sim->elements[r&0xFF].Properties&TYPE_LIQUID || (r&0xFF) == PT_NEUT || (r&0xFF) == PT_PHOT) { - playerp->elem = r&0xFF; //Current element + if (!playerp->rocketBoots || (r&0xFF)!=PT_PLSM) + playerp->elem = r&0xFF; //Current element } if ((r&0xFF)==PT_TESC || (r&0xFF)==PT_LIGH) playerp->elem = PT_LIGH; @@ -275,7 +392,12 @@ int Element_STKM::run_stickman(playerst* playerp, UPDATE_FUNC_ARGS) { sim->kill_part(r>>8); } if (sim->bmap[(ry+y)/CELL][(rx+x)/CELL]==WL_FAN) + { + playerp->rocketBoots = false; playerp->elem = SPC_AIR; + } + else if (sim->bmap[(ry+y)/CELL][(rx+x)/CELL]==WL_GRAV && parts[i].type!=PT_FIGH) + playerp->rocketBoots = true; if ((r&0xFF)==PT_PRTI) Element_STKM::STKM_interact(sim, playerp, i, rx, ry); if (!parts[i].type)//STKM_interact may kill STKM @@ -465,7 +587,7 @@ void Element_STKM::STKM_interact(Simulation * sim, playerst* playerp, int i, int sim->parts[i].life -= (int)(rand()*20/RAND_MAX)+32; } - if (sim->elements[r&0xFF].HeatConduct && ((playerp->elem!=PT_LIGH && sim->parts[r>>8].temp>=323) || sim->parts[r>>8].temp<=243)) + if (sim->elements[r&0xFF].HeatConduct && ((playerp->elem!=PT_LIGH && sim->parts[r>>8].temp>=323) || sim->parts[r>>8].temp<=243) && (!playerp->rocketBoots || (r&0xFF)!=PT_PLSM)) { sim->parts[i].life -= 2; playerp->accs[3] -= 1;