Factor PlanMove out of Simulation::UpdateParticles
This will be useful later for a debug feature I'm planning to add.
This commit is contained in:
parent
edcbeaca56
commit
ac99fb8a11
@ -1090,7 +1090,7 @@ void Simulation::clear_sim(void)
|
|||||||
SetEdgeMode(edgeMode);
|
SetEdgeMode(edgeMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Simulation::IsWallBlocking(int x, int y, int type)
|
bool Simulation::IsWallBlocking(int x, int y, int type) const
|
||||||
{
|
{
|
||||||
if (bmap[y/CELL][x/CELL])
|
if (bmap[y/CELL][x/CELL])
|
||||||
{
|
{
|
||||||
@ -1258,7 +1258,7 @@ void Simulation::init_can_move()
|
|||||||
0 = No move/Bounce
|
0 = No move/Bounce
|
||||||
2 = Both particles occupy the same space.
|
2 = Both particles occupy the same space.
|
||||||
*/
|
*/
|
||||||
int Simulation::eval_move(int pt, int nx, int ny, unsigned *rr)
|
int Simulation::eval_move(int pt, int nx, int ny, unsigned *rr) const
|
||||||
{
|
{
|
||||||
unsigned r;
|
unsigned r;
|
||||||
int result;
|
int result;
|
||||||
@ -2227,6 +2227,115 @@ void Simulation::delete_part(int x, int y)//calls kill_part with the particle lo
|
|||||||
kill_part(ID(i));
|
kill_part(ID(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Simulation::PlanMoveResult Simulation::PlanMove(int i, int x, int y, bool update_emap)
|
||||||
|
{
|
||||||
|
// This function would be const if not for calling set_emap if update_emap is true,
|
||||||
|
// and users of this function *expect* it to be const if update_emap is false. So
|
||||||
|
// whenever you change something here, make sure it compiles *as const* if you
|
||||||
|
// remove the set_emap call.
|
||||||
|
auto t = parts[i].type;
|
||||||
|
int fin_x, fin_y, clear_x, clear_y;
|
||||||
|
float fin_xf, fin_yf, clear_xf, clear_yf;
|
||||||
|
auto vx = parts[i].vx;
|
||||||
|
auto vy = parts[i].vy;
|
||||||
|
auto mv = fmaxf(fabsf(vx), fabsf(vy));
|
||||||
|
if (mv < ISTP)
|
||||||
|
{
|
||||||
|
clear_x = x;
|
||||||
|
clear_y = y;
|
||||||
|
clear_xf = parts[i].x;
|
||||||
|
clear_yf = parts[i].y;
|
||||||
|
fin_xf = clear_xf + vx;
|
||||||
|
fin_yf = clear_yf + vy;
|
||||||
|
fin_x = (int)(fin_xf+0.5f);
|
||||||
|
fin_y = (int)(fin_yf+0.5f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mv > MAX_VELOCITY)
|
||||||
|
{
|
||||||
|
vx *= MAX_VELOCITY/mv;
|
||||||
|
vy *= MAX_VELOCITY/mv;
|
||||||
|
mv = MAX_VELOCITY;
|
||||||
|
}
|
||||||
|
// interpolate to see if there is anything in the way
|
||||||
|
auto dx = vx*ISTP/mv;
|
||||||
|
auto dy = vy*ISTP/mv;
|
||||||
|
fin_xf = parts[i].x;
|
||||||
|
fin_yf = parts[i].y;
|
||||||
|
fin_x = (int)(fin_xf+0.5f);
|
||||||
|
fin_y = (int)(fin_yf+0.5f);
|
||||||
|
bool closedEholeStart = InBounds(fin_x, fin_y) && (bmap[fin_y/CELL][fin_x/CELL] == WL_EHOLE && !emap[fin_y/CELL][fin_x/CELL]);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
mv -= ISTP;
|
||||||
|
fin_xf += dx;
|
||||||
|
fin_yf += dy;
|
||||||
|
fin_x = (int)(fin_xf+0.5f);
|
||||||
|
fin_y = (int)(fin_yf+0.5f);
|
||||||
|
if (edgeMode == EDGE_LOOP)
|
||||||
|
{
|
||||||
|
bool x_ok = (fin_xf >= CELL-.5f && fin_xf < XRES-CELL-.5f);
|
||||||
|
bool y_ok = (fin_yf >= CELL-.5f && fin_yf < YRES-CELL-.5f);
|
||||||
|
if (!x_ok)
|
||||||
|
fin_xf = remainder_p(fin_xf-CELL+.5f, XRES-CELL*2.0f)+CELL-.5f;
|
||||||
|
if (!y_ok)
|
||||||
|
fin_yf = remainder_p(fin_yf-CELL+.5f, YRES-CELL*2.0f)+CELL-.5f;
|
||||||
|
fin_x = (int)(fin_xf+0.5f);
|
||||||
|
fin_y = (int)(fin_yf+0.5f);
|
||||||
|
}
|
||||||
|
if (mv <= 0.0f)
|
||||||
|
{
|
||||||
|
// nothing found
|
||||||
|
fin_xf = parts[i].x + vx;
|
||||||
|
fin_yf = parts[i].y + vy;
|
||||||
|
if (edgeMode == EDGE_LOOP)
|
||||||
|
{
|
||||||
|
bool x_ok = (fin_xf >= CELL-.5f && fin_xf < XRES-CELL-.5f);
|
||||||
|
bool y_ok = (fin_yf >= CELL-.5f && fin_yf < YRES-CELL-.5f);
|
||||||
|
if (!x_ok)
|
||||||
|
fin_xf = remainder_p(fin_xf-CELL+.5f, XRES-CELL*2.0f)+CELL-.5f;
|
||||||
|
if (!y_ok)
|
||||||
|
fin_yf = remainder_p(fin_yf-CELL+.5f, YRES-CELL*2.0f)+CELL-.5f;
|
||||||
|
}
|
||||||
|
fin_x = (int)(fin_xf+0.5f);
|
||||||
|
fin_y = (int)(fin_yf+0.5f);
|
||||||
|
clear_xf = fin_xf-dx;
|
||||||
|
clear_yf = fin_yf-dy;
|
||||||
|
clear_x = (int)(clear_xf+0.5f);
|
||||||
|
clear_y = (int)(clear_yf+0.5f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//block if particle can't move (0), or some special cases where it returns 1 (can_move = 3 but returns 1 meaning particle will be eaten)
|
||||||
|
//also photons are still blocked (slowed down) by any particle (even ones it can move through), and absorb wall also blocks particles
|
||||||
|
int eval = eval_move(t, fin_x, fin_y, NULL);
|
||||||
|
if (!eval || (can_move[t][TYP(pmap[fin_y][fin_x])] == 3 && eval == 1) || (t == PT_PHOT && pmap[fin_y][fin_x]) || bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || closedEholeStart!=(bmap[fin_y/CELL][fin_x/CELL] == WL_EHOLE && !emap[fin_y/CELL][fin_x/CELL]))
|
||||||
|
{
|
||||||
|
// found an obstacle
|
||||||
|
clear_xf = fin_xf-dx;
|
||||||
|
clear_yf = fin_yf-dy;
|
||||||
|
clear_x = (int)(clear_xf+0.5f);
|
||||||
|
clear_y = (int)(clear_yf+0.5f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (update_emap && 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fin_x,
|
||||||
|
fin_y,
|
||||||
|
clear_x,
|
||||||
|
clear_y,
|
||||||
|
fin_xf,
|
||||||
|
fin_yf,
|
||||||
|
clear_xf,
|
||||||
|
clear_yf,
|
||||||
|
vx,
|
||||||
|
vy,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void Simulation::UpdateParticles(int start, int end)
|
void Simulation::UpdateParticles(int start, int end)
|
||||||
{
|
{
|
||||||
//the main particle loop function, goes over all particles.
|
//the main particle loop function, goes over all particles.
|
||||||
@ -2868,90 +2977,17 @@ killed:
|
|||||||
int fin_x, fin_y, clear_x, clear_y;
|
int fin_x, fin_y, clear_x, clear_y;
|
||||||
float fin_xf, fin_yf, clear_xf, clear_yf;
|
float fin_xf, fin_yf, clear_xf, clear_yf;
|
||||||
{
|
{
|
||||||
auto mv = fmaxf(fabsf(parts[i].vx), fabsf(parts[i].vy));
|
auto mr = PlanMove(i, x, y, true);
|
||||||
if (mv < ISTP)
|
fin_x = mr.fin_x;
|
||||||
{
|
fin_y = mr.fin_y;
|
||||||
clear_x = x;
|
clear_x = mr.clear_x;
|
||||||
clear_y = y;
|
clear_y = mr.clear_y;
|
||||||
clear_xf = parts[i].x;
|
fin_xf = mr.fin_xf;
|
||||||
clear_yf = parts[i].y;
|
fin_yf = mr.fin_yf;
|
||||||
fin_xf = clear_xf + parts[i].vx;
|
clear_xf = mr.clear_xf;
|
||||||
fin_yf = clear_yf + parts[i].vy;
|
clear_yf = mr.clear_yf;
|
||||||
fin_x = (int)(fin_xf+0.5f);
|
parts[i].vx = mr.vx;
|
||||||
fin_y = (int)(fin_yf+0.5f);
|
parts[i].vy = mr.vy;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mv > MAX_VELOCITY)
|
|
||||||
{
|
|
||||||
parts[i].vx *= MAX_VELOCITY/mv;
|
|
||||||
parts[i].vy *= MAX_VELOCITY/mv;
|
|
||||||
mv = MAX_VELOCITY;
|
|
||||||
}
|
|
||||||
// interpolate to see if there is anything in the way
|
|
||||||
auto dx = parts[i].vx*ISTP/mv;
|
|
||||||
auto dy = parts[i].vy*ISTP/mv;
|
|
||||||
fin_xf = parts[i].x;
|
|
||||||
fin_yf = parts[i].y;
|
|
||||||
fin_x = (int)(fin_xf+0.5f);
|
|
||||||
fin_y = (int)(fin_yf+0.5f);
|
|
||||||
bool closedEholeStart = InBounds(fin_x, fin_y) && (bmap[fin_y/CELL][fin_x/CELL] == WL_EHOLE && !emap[fin_y/CELL][fin_x/CELL]);
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
mv -= ISTP;
|
|
||||||
fin_xf += dx;
|
|
||||||
fin_yf += dy;
|
|
||||||
fin_x = (int)(fin_xf+0.5f);
|
|
||||||
fin_y = (int)(fin_yf+0.5f);
|
|
||||||
if (edgeMode == EDGE_LOOP)
|
|
||||||
{
|
|
||||||
bool x_ok = (fin_xf >= CELL-.5f && fin_xf < XRES-CELL-.5f);
|
|
||||||
bool y_ok = (fin_yf >= CELL-.5f && fin_yf < YRES-CELL-.5f);
|
|
||||||
if (!x_ok)
|
|
||||||
fin_xf = remainder_p(fin_xf-CELL+.5f, XRES-CELL*2.0f)+CELL-.5f;
|
|
||||||
if (!y_ok)
|
|
||||||
fin_yf = remainder_p(fin_yf-CELL+.5f, YRES-CELL*2.0f)+CELL-.5f;
|
|
||||||
fin_x = (int)(fin_xf+0.5f);
|
|
||||||
fin_y = (int)(fin_yf+0.5f);
|
|
||||||
}
|
|
||||||
if (mv <= 0.0f)
|
|
||||||
{
|
|
||||||
// nothing found
|
|
||||||
fin_xf = parts[i].x + parts[i].vx;
|
|
||||||
fin_yf = parts[i].y + parts[i].vy;
|
|
||||||
if (edgeMode == EDGE_LOOP)
|
|
||||||
{
|
|
||||||
bool x_ok = (fin_xf >= CELL-.5f && fin_xf < XRES-CELL-.5f);
|
|
||||||
bool y_ok = (fin_yf >= CELL-.5f && fin_yf < YRES-CELL-.5f);
|
|
||||||
if (!x_ok)
|
|
||||||
fin_xf = remainder_p(fin_xf-CELL+.5f, XRES-CELL*2.0f)+CELL-.5f;
|
|
||||||
if (!y_ok)
|
|
||||||
fin_yf = remainder_p(fin_yf-CELL+.5f, YRES-CELL*2.0f)+CELL-.5f;
|
|
||||||
}
|
|
||||||
fin_x = (int)(fin_xf+0.5f);
|
|
||||||
fin_y = (int)(fin_yf+0.5f);
|
|
||||||
clear_xf = fin_xf-dx;
|
|
||||||
clear_yf = fin_yf-dy;
|
|
||||||
clear_x = (int)(clear_xf+0.5f);
|
|
||||||
clear_y = (int)(clear_yf+0.5f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//block if particle can't move (0), or some special cases where it returns 1 (can_move = 3 but returns 1 meaning particle will be eaten)
|
|
||||||
//also photons are still blocked (slowed down) by any particle (even ones it can move through), and absorb wall also blocks particles
|
|
||||||
int eval = eval_move(t, fin_x, fin_y, NULL);
|
|
||||||
if (!eval || (can_move[t][TYP(pmap[fin_y][fin_x])] == 3 && eval == 1) || (t == PT_PHOT && pmap[fin_y][fin_x]) || bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || closedEholeStart!=(bmap[fin_y/CELL][fin_x/CELL] == WL_EHOLE && !emap[fin_y/CELL][fin_x/CELL]))
|
|
||||||
{
|
|
||||||
// found an obstacle
|
|
||||||
clear_xf = fin_xf-dx;
|
|
||||||
clear_yf = fin_yf-dy;
|
|
||||||
clear_x = (int)(clear_xf+0.5f);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stagnant = parts[i].flags & FLAG_STAGNANT;
|
auto stagnant = parts[i].flags & FLAG_STAGNANT;
|
||||||
|
@ -136,9 +136,16 @@ public:
|
|||||||
int do_move(int i, int x, int y, float nxf, float nyf);
|
int do_move(int i, int x, int y, float nxf, float nyf);
|
||||||
bool move(int i, int x, int y, float nxf, float nyf);
|
bool move(int i, int x, int y, float nxf, float nyf);
|
||||||
int try_move(int i, int x, int y, int nx, int ny);
|
int try_move(int i, int x, int y, int nx, int ny);
|
||||||
int eval_move(int pt, int nx, int ny, unsigned *rr);
|
int eval_move(int pt, int nx, int ny, unsigned *rr) const;
|
||||||
|
struct PlanMoveResult
|
||||||
|
{
|
||||||
|
int fin_x, fin_y, clear_x, clear_y;
|
||||||
|
float fin_xf, fin_yf, clear_xf, clear_yf;
|
||||||
|
float vx, vy;
|
||||||
|
};
|
||||||
|
PlanMoveResult PlanMove(int i, int x, int y, bool update_emap);
|
||||||
void init_can_move();
|
void init_can_move();
|
||||||
bool IsWallBlocking(int x, int y, int type);
|
bool IsWallBlocking(int x, int y, int type) const;
|
||||||
bool IsElement(int type) const {
|
bool IsElement(int type) const {
|
||||||
return (type > 0 && type < PT_NUM && elements[type].Enabled);
|
return (type > 0 && type < PT_NUM && elements[type].Enabled);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user