|
|
|
@ -3,514 +3,506 @@
@@ -3,514 +3,506 @@
|
|
|
|
|
|
|
|
|
|
namespace pengine { |
|
|
|
|
|
|
|
|
|
Uint8 part_colours[][3] = { |
|
|
|
|
{255,255,255}, // BASIC
|
|
|
|
|
{252,250,148}, // SAND
|
|
|
|
|
{70,90,255}, // WATER
|
|
|
|
|
{200,220,255}, // STEAM
|
|
|
|
|
{200,20,20}, // LAVA
|
|
|
|
|
{140,111,71}, // ROCK
|
|
|
|
|
{200,20,20}, // LIQUID QUARTZ
|
|
|
|
|
{20,80,40}, // QUARTZ
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::string part_names[] = { |
|
|
|
|
"default", |
|
|
|
|
"Sand", |
|
|
|
|
"Water", |
|
|
|
|
"Steam", |
|
|
|
|
"Lava", |
|
|
|
|
"Rock" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct particle_data BasicParticle::default_data(ParticleID id)
|
|
|
|
|
{ |
|
|
|
|
struct particle_data datap; |
|
|
|
|
switch (id) { |
|
|
|
|
case ParticleID::WATER: |
|
|
|
|
datap = {.density=10,
|
|
|
|
|
.liquid = true,
|
|
|
|
|
.temperature=20, |
|
|
|
|
.boiling_point = 100,
|
|
|
|
|
.gas_state = ParticleID::STEAM |
|
|
|
|
}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::LAVA: |
|
|
|
|
datap = {.density=20, .liquid = true, .temperature=5000, |
|
|
|
|
.boiling_point = 10000,.freezing_point=200, .solid_state=ParticleID::ROCK}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::STEAM: |
|
|
|
|
datap = {.density=0, .liquid = false, .temperature=150,
|
|
|
|
|
.liquid_state = ParticleID::WATER}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::SAND: |
|
|
|
|
datap = {.density=100, .liquid = false, .temperature=20}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::ROCK: |
|
|
|
|
datap = {.density=150, .liquid = false, .temperature=20, |
|
|
|
|
.melting_point = 700, .liquid_state=ParticleID::LAVA}; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
datap = {.temperature = 0}; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return datap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
BasicParticle::BasicParticle(ParticleID id) : Particle(id)
|
|
|
|
|
{ |
|
|
|
|
this->id = id; |
|
|
|
|
data = default_data(id); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
State
|
|
|
|
|
BasicParticle::get_state()
|
|
|
|
|
{ |
|
|
|
|
switch(id) { |
|
|
|
|
case (ParticleID::STEAM): |
|
|
|
|
return State::GAS; |
|
|
|
|
|
|
|
|
|
case (ParticleID::WATER): |
|
|
|
|
case (ParticleID::LAVA): |
|
|
|
|
return State::LIQUID; |
|
|
|
|
|
|
|
|
|
case (ParticleID::ROCK): |
|
|
|
|
case (ParticleID::SAND): |
|
|
|
|
return State::SOLID; |
|
|
|
|
default: |
|
|
|
|
return State::SOLID; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Particle * |
|
|
|
|
get_new_particle(ParticleID p)
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
switch (p) { |
|
|
|
|
case ParticleID::SAND: |
|
|
|
|
return new Sand(); |
|
|
|
|
case ParticleID::WATER: |
|
|
|
|
return new Water(); |
|
|
|
|
case ParticleID::BASIC: |
|
|
|
|
return new BasicParticle(); |
|
|
|
|
case ParticleID::STEAM: |
|
|
|
|
return new Steam(); |
|
|
|
|
case ParticleID::LAVA: |
|
|
|
|
return new Lava(); |
|
|
|
|
case ParticleID::ROCK: |
|
|
|
|
return new Rock(); |
|
|
|
|
default: |
|
|
|
|
std::cout << "Unknown particle create\n"; |
|
|
|
|
throw "unknown particle"; |
|
|
|
|
} |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(short r, short g, short b, short a) { |
|
|
|
|
this->r = r; |
|
|
|
|
this->g = g; |
|
|
|
|
this->b = b; |
|
|
|
|
this->a = a; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(Uint32 c) { |
|
|
|
|
pixel = c; |
|
|
|
|
} |
|
|
|
|
Uint8 part_colours[][3] = { |
|
|
|
|
{255, 255, 255}, // BASIC
|
|
|
|
|
{252, 250, 148}, // SAND
|
|
|
|
|
{70, 90, 255}, // WATER
|
|
|
|
|
{200, 220, 255}, // STEAM
|
|
|
|
|
{200, 20, 20}, // LAVA
|
|
|
|
|
{140, 111, 71}, // ROCK
|
|
|
|
|
{200, 20, 20}, // LIQUID QUARTZ
|
|
|
|
|
{20, 80, 40}, // QUARTZ
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::string part_names[] = {"default", "Sand", "Water", |
|
|
|
|
"Steam", "Lava", "Rock"}; |
|
|
|
|
|
|
|
|
|
struct particle_data BasicParticle::default_data(ParticleID id) { |
|
|
|
|
struct particle_data datap; |
|
|
|
|
switch (id) { |
|
|
|
|
case ParticleID::WATER: |
|
|
|
|
datap = {.density = 10, |
|
|
|
|
.liquid = true, |
|
|
|
|
.temperature = 20, |
|
|
|
|
.boiling_point = 100, |
|
|
|
|
.gas_state = ParticleID::STEAM}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::LAVA: |
|
|
|
|
datap = {.density = 20, |
|
|
|
|
.liquid = true, |
|
|
|
|
.temperature = 5000, |
|
|
|
|
.boiling_point = 10000, |
|
|
|
|
.freezing_point = 200, |
|
|
|
|
.solid_state = ParticleID::ROCK}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::STEAM: |
|
|
|
|
datap = {.density = 0, |
|
|
|
|
.liquid = false, |
|
|
|
|
.temperature = 150, |
|
|
|
|
.liquid_state = ParticleID::WATER}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::SAND: |
|
|
|
|
datap = {.density = 100, .liquid = false, .temperature = 20}; |
|
|
|
|
break; |
|
|
|
|
case ParticleID::ROCK: |
|
|
|
|
datap = {.density = 150, |
|
|
|
|
.liquid = false, |
|
|
|
|
.temperature = 20, |
|
|
|
|
.melting_point = 700, |
|
|
|
|
.liquid_state = ParticleID::LAVA}; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
datap = {.temperature = 0}; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return datap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(short r, short g, short b) { |
|
|
|
|
this->r = r; |
|
|
|
|
this->g = g; |
|
|
|
|
this->b = b; |
|
|
|
|
this->a = 255; |
|
|
|
|
} |
|
|
|
|
BasicParticle::BasicParticle(ParticleID id) : Particle(id) { |
|
|
|
|
this->id = id; |
|
|
|
|
data = default_data(id); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
State BasicParticle::get_state() { |
|
|
|
|
switch (id) { |
|
|
|
|
case (ParticleID::STEAM): |
|
|
|
|
return State::GAS; |
|
|
|
|
|
|
|
|
|
case (ParticleID::WATER): |
|
|
|
|
case (ParticleID::LAVA): |
|
|
|
|
return State::LIQUID; |
|
|
|
|
|
|
|
|
|
case (ParticleID::ROCK): |
|
|
|
|
case (ParticleID::SAND): |
|
|
|
|
return State::SOLID; |
|
|
|
|
default: |
|
|
|
|
return State::SOLID; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(SDL_Color c) { |
|
|
|
|
this->r = c.r; |
|
|
|
|
this->g = c.g; |
|
|
|
|
this->b = c.b; |
|
|
|
|
this->a = c.a; |
|
|
|
|
} |
|
|
|
|
Particle *get_new_particle(ParticleID p) { |
|
|
|
|
|
|
|
|
|
switch (p) { |
|
|
|
|
case ParticleID::SAND: |
|
|
|
|
return new Sand(); |
|
|
|
|
case ParticleID::WATER: |
|
|
|
|
return new Water(); |
|
|
|
|
case ParticleID::BASIC: |
|
|
|
|
return new BasicParticle(); |
|
|
|
|
case ParticleID::STEAM: |
|
|
|
|
return new Steam(); |
|
|
|
|
case ParticleID::LAVA: |
|
|
|
|
return new Lava(); |
|
|
|
|
case ParticleID::ROCK: |
|
|
|
|
return new Rock(); |
|
|
|
|
default: |
|
|
|
|
std::cout << "Unknown particle create\n"; |
|
|
|
|
throw "unknown particle"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(const Uint8 p[3]) : PixelColour (p[0], p[1], p[2]) {} |
|
|
|
|
PixelColour::PixelColour(short r, short g, short b, short a) { |
|
|
|
|
this->r = r; |
|
|
|
|
this->g = g; |
|
|
|
|
this->b = b; |
|
|
|
|
this->a = a; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour::PixelColour(Uint32 c) { pixel = c; } |
|
|
|
|
|
|
|
|
|
SDL_Color PixelColour::get_sdlcol() { |
|
|
|
|
SDL_Color c; |
|
|
|
|
c.r = r; |
|
|
|
|
c.b = b; |
|
|
|
|
c.g = g; |
|
|
|
|
c.a = a; |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
PixelColour::PixelColour(short r, short g, short b) { |
|
|
|
|
this->r = r; |
|
|
|
|
this->g = g; |
|
|
|
|
this->b = b; |
|
|
|
|
this->a = 255; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Uint32 PixelColour::get_pixelcol() { |
|
|
|
|
return pixel; |
|
|
|
|
} |
|
|
|
|
PixelColour::PixelColour(SDL_Color c) { |
|
|
|
|
this->r = c.r; |
|
|
|
|
this->g = c.g; |
|
|
|
|
this->b = c.b; |
|
|
|
|
this->a = c.a; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Grid::Grid(int xs, int ys) { |
|
|
|
|
xsize = xs; |
|
|
|
|
ysize = ys; |
|
|
|
|
PixelColour::PixelColour(const Uint8 p[3]) : PixelColour(p[0], p[1], p[2]) {} |
|
|
|
|
|
|
|
|
|
grid = new Particle *[xs * ys] {};
|
|
|
|
|
pixels = new Uint32[xs * ys] {};
|
|
|
|
|
SDL_Color PixelColour::get_sdlcol() { |
|
|
|
|
SDL_Color c; |
|
|
|
|
c.r = r; |
|
|
|
|
c.b = b; |
|
|
|
|
c.g = g; |
|
|
|
|
c.a = a; |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < xs * ys; i++) { |
|
|
|
|
grid[i] = 0; |
|
|
|
|
pixels[i] = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Uint32 PixelColour::get_pixelcol() { return pixel; } |
|
|
|
|
|
|
|
|
|
Grid::~Grid()
|
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < xsize * ysize; i++) { |
|
|
|
|
if (grid[i]) |
|
|
|
|
delete grid[i]; |
|
|
|
|
} |
|
|
|
|
delete[] grid; |
|
|
|
|
delete[] pixels; |
|
|
|
|
} |
|
|
|
|
Grid::Grid(int xs, int ys) { |
|
|
|
|
xsize = xs; |
|
|
|
|
ysize = ys; |
|
|
|
|
|
|
|
|
|
void Grid::update()
|
|
|
|
|
{ |
|
|
|
|
static bool updated = false; |
|
|
|
|
bool done = true; |
|
|
|
|
|
|
|
|
|
while (done) { |
|
|
|
|
done = false; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < xsize; i++) { |
|
|
|
|
for (int j = 0; j < ysize; j++) { |
|
|
|
|
int p = j * xsize + i; |
|
|
|
|
if (grid[p]) { |
|
|
|
|
if (grid[p]->updated != updated) { |
|
|
|
|
grid[p]->updated = updated; |
|
|
|
|
grid[p]->update(this, i, j); |
|
|
|
|
done = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
grid = new Particle *[xs * ys] {}; |
|
|
|
|
pixels = new Uint32[xs * ys]{}; |
|
|
|
|
|
|
|
|
|
updated = !updated; |
|
|
|
|
clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
Grid::~Grid() { |
|
|
|
|
for (int i = 0; i < xsize * ysize; i++) { |
|
|
|
|
if (grid[i]) |
|
|
|
|
delete grid[i]; |
|
|
|
|
} |
|
|
|
|
delete[] grid; |
|
|
|
|
delete[] pixels; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Grid &Grid::operator=(Grid o) { |
|
|
|
|
xsize = o.xsize; |
|
|
|
|
ysize = o.ysize; |
|
|
|
|
|
|
|
|
|
void Grid::add_particle_at(int x, int y, ParticleID p)
|
|
|
|
|
{ |
|
|
|
|
if (x >= xsize || y >= ysize || x < 0 || y < 0) { |
|
|
|
|
std::cout << "invalid position " << x << " " << y << std::endl; |
|
|
|
|
throw "invalid boundaries"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (grid[x + y * xsize]) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
grid = new Particle *[xsize * ysize] {}; |
|
|
|
|
pixels = new Uint32[xsize * ysize]{}; |
|
|
|
|
|
|
|
|
|
grid[x + y * xsize] = get_new_particle(p); |
|
|
|
|
} |
|
|
|
|
for (int i = 0; i < xsize * ysize; i++) { |
|
|
|
|
grid[i] = o.grid[i]; |
|
|
|
|
pixels[i] = o.pixels[i]; |
|
|
|
|
} |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Particle * Grid::get_particle(int x, int y) { |
|
|
|
|
if (!inside_grid(x,y)) { |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
void Grid::clear() { |
|
|
|
|
for (int i = 0; i < xsize * ysize; i++) { |
|
|
|
|
grid[i] = 0; |
|
|
|
|
pixels[i] = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return grid[x + xsize * y]; |
|
|
|
|
} |
|
|
|
|
void Grid::update() { |
|
|
|
|
static bool updated = false; |
|
|
|
|
bool done = true; |
|
|
|
|
|
|
|
|
|
void Grid::update_texture() { |
|
|
|
|
PixelColour defaultcol = PixelColour(0,0,0,0); |
|
|
|
|
for (int i = 0; i < xsize; i++) { |
|
|
|
|
for (int j = 0; j < ysize; j++) { |
|
|
|
|
int p = j * xsize + i; |
|
|
|
|
if (grid[p] != nullptr) { |
|
|
|
|
//:w pixels[p] = defaultcoll.pixel;
|
|
|
|
|
pixels[p] = grid[p]->get_colour().get_pixelcol(); |
|
|
|
|
} else { |
|
|
|
|
pixels[p] = defaultcol.get_pixelcol(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
while (done) { |
|
|
|
|
done = false; |
|
|
|
|
|
|
|
|
|
bool Grid::inside_grid(int x, int y) { |
|
|
|
|
if (x >= xsize || y >= ysize || x < 0 || y < 0) { |
|
|
|
|
return false; |
|
|
|
|
for (int i = 0; i < xsize; i++) { |
|
|
|
|
for (int j = 0; j < ysize; j++) { |
|
|
|
|
int p = j * xsize + i; |
|
|
|
|
if (grid[p]) { |
|
|
|
|
if (grid[p]->updated != updated) { |
|
|
|
|
grid[p]->updated = updated; |
|
|
|
|
grid[p]->update(this, i, j); |
|
|
|
|
done = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Grid::move_particle(int xa, int ya, int xb, int yb) { |
|
|
|
|
updated = !updated; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xb, yb)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
void Grid::erase_particle_at(int x, int y) { |
|
|
|
|
if (x >= xsize || y >= ysize || x < 0 || y < 0) { |
|
|
|
|
std::cout << "invalid position " << x << " " << y << std::endl; |
|
|
|
|
throw "invalid boundaries"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xa, ya)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
grid[x + y * xsize] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((get_particle(xa,ya) != nullptr) && (get_particle(xb,yb) == nullptr)) { |
|
|
|
|
grid[xb + yb * xsize] = grid[xa + ya * xsize]; |
|
|
|
|
grid[xa + ya * xsize] = nullptr; |
|
|
|
|
return true; |
|
|
|
|
}
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
void Grid::add_particle_at(int x, int y, ParticleID p) { |
|
|
|
|
if (x >= xsize || y >= ysize || x < 0 || y < 0) { |
|
|
|
|
std::cout << "invalid position " << x << " " << y << std::endl; |
|
|
|
|
throw "invalid boundaries"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int Grid::swap_particle(int xa, int ya, int xb, int yb) { |
|
|
|
|
if (grid[x + y * xsize]) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xb, yb)) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
grid[x + y * xsize] = get_new_particle(p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xa, ya)) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
Particle *Grid::get_particle(int x, int y) { |
|
|
|
|
if (!inside_grid(x, y)) { |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int num = 0; |
|
|
|
|
if (get_particle(xa,ya) != nullptr) { |
|
|
|
|
num++; |
|
|
|
|
} |
|
|
|
|
if (get_particle(xb,yb) != nullptr) { |
|
|
|
|
num++; |
|
|
|
|
} |
|
|
|
|
return grid[x + xsize * y]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (num > 0) { |
|
|
|
|
Particle *temp = grid[xb + yb * xsize]; |
|
|
|
|
grid[xb + yb * xsize] = grid[xa + ya * xsize]; |
|
|
|
|
grid[xa + ya * xsize] = temp; |
|
|
|
|
return num; |
|
|
|
|
}
|
|
|
|
|
return 0; |
|
|
|
|
void Grid::update_texture() { |
|
|
|
|
PixelColour defaultcol = PixelColour(0, 0, 0, 0); |
|
|
|
|
for (int i = 0; i < xsize; i++) { |
|
|
|
|
for (int j = 0; j < ysize; j++) { |
|
|
|
|
int p = j * xsize + i; |
|
|
|
|
if (grid[p] != nullptr) { |
|
|
|
|
//: w pixels[p] = defaultcoll.pixel;
|
|
|
|
|
pixels[p] = grid[p]->get_colour().get_pixelcol(); |
|
|
|
|
} else { |
|
|
|
|
pixels[p] = defaultcol.get_pixelcol(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Grid::inside_grid(int x, int y) { |
|
|
|
|
if (x >= xsize || y >= ysize || x < 0 || y < 0) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Grid::replace_particle(int x, int y, Particle *new_particle) { |
|
|
|
|
auto p = get_particle(x, y); |
|
|
|
|
|
|
|
|
|
if (!p) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
delete p; |
|
|
|
|
bool Grid::move_particle(int xa, int ya, int xb, int yb) { |
|
|
|
|
|
|
|
|
|
grid[x + y * xsize] = new_particle; |
|
|
|
|
} |
|
|
|
|
if (!inside_grid(xb, yb)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xa, ya)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((get_particle(xa, ya) != nullptr) && (get_particle(xb, yb) == nullptr)) { |
|
|
|
|
grid[xb + yb * xsize] = grid[xa + ya * xsize]; |
|
|
|
|
grid[xa + ya * xsize] = nullptr; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Sand::update(Grid * const g, int x, int y) { |
|
|
|
|
int Grid::swap_particle(int xa, int ya, int xb, int yb) { |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xb, yb)) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!inside_grid(xa, ya)) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int num = 0; |
|
|
|
|
if (get_particle(xa, ya) != nullptr) { |
|
|
|
|
num++; |
|
|
|
|
} |
|
|
|
|
if (get_particle(xb, yb) != nullptr) { |
|
|
|
|
num++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (num > 0) { |
|
|
|
|
Particle *temp = grid[xb + yb * xsize]; |
|
|
|
|
grid[xb + yb * xsize] = grid[xa + ya * xsize]; |
|
|
|
|
grid[xa + ya * xsize] = temp; |
|
|
|
|
return num; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (update_temperature(g, x, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
void Grid::replace_particle(int x, int y, Particle *new_particle) { |
|
|
|
|
auto p = get_particle(x, y); |
|
|
|
|
|
|
|
|
|
Particle *p; |
|
|
|
|
if(g->move_particle(x, y, x, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x-1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x+1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!p) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x, y+1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x, y+1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (g->swap_particle(x, y, x, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
delete p; |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x-1, y+1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x-1, y+1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if
|
|
|
|
|
(g->swap_particle(x, y, x-1, y+1)) |
|
|
|
|
return; |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = g->get_particle(x+1, y+1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x+1, y+1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (g->swap_particle(x, y, x+1, y+1)) |
|
|
|
|
return; |
|
|
|
|
}
|
|
|
|
|
grid[x + y * xsize] = new_particle; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Sand::update(Grid *const g, int x, int y) { |
|
|
|
|
|
|
|
|
|
if (update_temperature(g, x, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Particle *p; |
|
|
|
|
if (g->move_particle(x, y, x, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x - 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x + 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x, y + 1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x, y + 1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
BasicParticle::BasicParticle() : Particle(ParticleID::BASIC) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void BasicParticle::update(Grid * const g, int x, int y) { |
|
|
|
|
return; |
|
|
|
|
} else { |
|
|
|
|
if (g->swap_particle(x, y, x, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PixelColour BasicParticle::get_colour() { |
|
|
|
|
return PixelColour {part_colours[((int)this->id)]}; |
|
|
|
|
p = g->get_particle(x - 1, y + 1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x - 1, y + 1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string BasicParticle::get_name() { |
|
|
|
|
return part_names[((int)this->id)]; |
|
|
|
|
} else { |
|
|
|
|
if (g->swap_particle(x, y, x - 1, y + 1)) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x + 1, y + 1); |
|
|
|
|
if (p != nullptr) { |
|
|
|
|
if (p->data.density < data.density || p->data.liquid) { |
|
|
|
|
g->swap_particle(x, y, x + 1, y + 1); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (g->swap_particle(x, y, x + 1, y + 1)) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool BasicParticle::update_temperature(Grid * const g, int x, int y)
|
|
|
|
|
{ |
|
|
|
|
for (int i = -1; i <= 1; i++) { |
|
|
|
|
for (int j = -1; j <= 1; j++) { |
|
|
|
|
int xa = x + i; |
|
|
|
|
int ya = y + j; |
|
|
|
|
auto p = g->get_particle(xa,ya); |
|
|
|
|
if (p) { |
|
|
|
|
data.temperature += (p->data.temperature - data.temperature) / 5; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* apply state transition */ |
|
|
|
|
BasicParticle::BasicParticle() : Particle(ParticleID::BASIC) {} |
|
|
|
|
|
|
|
|
|
if (get_state() != State::GAS && data.temperature > data.boiling_point) { |
|
|
|
|
if (data.gas_state != ParticleID::BASIC){ |
|
|
|
|
auto gas = get_new_particle(data.gas_state); |
|
|
|
|
g->replace_particle(x,y,gas); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void BasicParticle::update(Grid *const g, int x, int y) { return; } |
|
|
|
|
|
|
|
|
|
if (get_state() != State::LIQUID && data.temperature < data.boiling_point
|
|
|
|
|
&& data.temperature > data.freezing_point) { |
|
|
|
|
if (data.liquid_state != ParticleID::BASIC){ |
|
|
|
|
auto liquid = get_new_particle(data.liquid_state); |
|
|
|
|
g->replace_particle(x,y,liquid); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (get_state() != State::SOLID && data.temperature < data.freezing_point) { |
|
|
|
|
if (data.solid_state != ParticleID::BASIC){ |
|
|
|
|
auto gas = get_new_particle(data.solid_state); |
|
|
|
|
g->replace_particle(x,y,gas); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
PixelColour BasicParticle::get_colour() { |
|
|
|
|
return PixelColour{part_colours[((int)this->id)]}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
std::string BasicParticle::get_name() { return part_names[((int)this->id)]; } |
|
|
|
|
|
|
|
|
|
bool BasicParticle::update_temperature(Grid *const g, int x, int y) { |
|
|
|
|
for (int i = -1; i <= 1; i++) { |
|
|
|
|
for (int j = -1; j <= 1; j++) { |
|
|
|
|
int xa = x + i; |
|
|
|
|
int ya = y + j; |
|
|
|
|
auto p = g->get_particle(xa, ya); |
|
|
|
|
if (p) { |
|
|
|
|
data.temperature += (p->data.temperature - data.temperature) / 5; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Water::update(Grid * const g, int x, int y) { |
|
|
|
|
if (update_temperature(g,x,y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto p = g->get_particle(x,y+1); |
|
|
|
|
if (p && p->data.liquid && p->id != id && this->data.density > p->data.density) { |
|
|
|
|
if (g->swap_particle(x, y, x, y+1)) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x-1,y+1); |
|
|
|
|
if ((p && p->data.liquid && p->id != id && data.density > p->data.density)) { |
|
|
|
|
if (g->swap_particle(x, y, x-1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x+1,y+1); |
|
|
|
|
if ((p && p->data.liquid && p->id != id && data.density > p->data.density)) { |
|
|
|
|
if (g->swap_particle(x, y, x+1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(g->move_particle(x, y, x, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x-1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x+1, y+1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* laksjdlaj */ |
|
|
|
|
|
|
|
|
|
if (g->move_particle(x, y, x-1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x+1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p = g->get_particle(x-1,y); |
|
|
|
|
if ((p && p->data.liquid)) { |
|
|
|
|
if (g->swap_particle(x, y, x-1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x+1,y); |
|
|
|
|
if ((p && p->data.liquid)) { |
|
|
|
|
if (g->swap_particle(x, y, x+1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
/* apply state transition */ |
|
|
|
|
|
|
|
|
|
if (get_state() != State::GAS && data.temperature > data.boiling_point) { |
|
|
|
|
if (data.gas_state != ParticleID::BASIC) { |
|
|
|
|
auto gas = get_new_particle(data.gas_state); |
|
|
|
|
g->replace_particle(x, y, gas); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (get_state() != State::LIQUID && data.temperature < data.boiling_point && |
|
|
|
|
data.temperature > data.freezing_point) { |
|
|
|
|
if (data.liquid_state != ParticleID::BASIC) { |
|
|
|
|
auto liquid = get_new_particle(data.liquid_state); |
|
|
|
|
g->replace_particle(x, y, liquid); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Steam::update(Grid *const g, int x, int y) { |
|
|
|
|
Particle *p = g->get_particle(x,y-1); |
|
|
|
|
if (g->move_particle(x, y, x, y-1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x-1,y-1); |
|
|
|
|
if (g->move_particle(x, y, x-1, y-1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x+1,y-1); |
|
|
|
|
if (g->move_particle(x, y, x+1, y-1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x+1,y); |
|
|
|
|
if (g->move_particle(x, y, x+1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x-1,y); |
|
|
|
|
if (g->move_particle(x, y, x-1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (get_state() != State::SOLID && data.temperature < data.freezing_point) { |
|
|
|
|
if (data.solid_state != ParticleID::BASIC) { |
|
|
|
|
auto gas = get_new_particle(data.solid_state); |
|
|
|
|
g->replace_particle(x, y, gas); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Lava::Lava() : Water(ParticleID::LAVA) {}; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Rock::Rock() : Sand(ParticleID::ROCK) {}; |
|
|
|
|
void Water::update(Grid *const g, int x, int y) { |
|
|
|
|
if (update_temperature(g, x, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto p = g->get_particle(x, y + 1); |
|
|
|
|
if (p && p->data.liquid && p->id != id && |
|
|
|
|
this->data.density > p->data.density) { |
|
|
|
|
if (g->swap_particle(x, y, x, y + 1)) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x - 1, y + 1); |
|
|
|
|
if ((p && p->data.liquid && p->id != id && data.density > p->data.density)) { |
|
|
|
|
if (g->swap_particle(x, y, x - 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Lava::update(Grid *const g, int x, int y) { |
|
|
|
|
Water::update(g,x,y); |
|
|
|
|
p = g->get_particle(x + 1, y + 1); |
|
|
|
|
if ((p && p->data.liquid && p->id != id && data.density > p->data.density)) { |
|
|
|
|
if (g->swap_particle(x, y, x + 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (g->move_particle(x, y, x, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x - 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x + 1, y + 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* laksjdlaj */ |
|
|
|
|
|
|
|
|
|
if (g->move_particle(x, y, x - 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (g->move_particle(x, y, x + 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = g->get_particle(x - 1, y); |
|
|
|
|
if ((p && p->data.liquid)) { |
|
|
|
|
if (g->swap_particle(x, y, x - 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Rock::update(Grid *const g, int x, int y) { |
|
|
|
|
Sand::update(g,x,y); |
|
|
|
|
p = g->get_particle(x + 1, y); |
|
|
|
|
if ((p && p->data.liquid)) { |
|
|
|
|
if (g->swap_particle(x, y, x + 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Steam::update(Grid *const g, int x, int y) { |
|
|
|
|
Particle *p = g->get_particle(x, y - 1); |
|
|
|
|
if (g->move_particle(x, y, x, y - 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x - 1, y - 1); |
|
|
|
|
if (g->move_particle(x, y, x - 1, y - 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x + 1, y - 1); |
|
|
|
|
if (g->move_particle(x, y, x + 1, y - 1)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x + 1, y); |
|
|
|
|
if (g->move_particle(x, y, x + 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
p = g->get_particle(x - 1, y); |
|
|
|
|
if (g->move_particle(x, y, x - 1, y)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Lava::Lava() : Water(ParticleID::LAVA){}; |
|
|
|
|
|
|
|
|
|
Rock::Rock() : Sand(ParticleID::ROCK){}; |
|
|
|
|
|
|
|
|
|
void Lava::update(Grid *const g, int x, int y) { Water::update(g, x, y); } |
|
|
|
|
|
|
|
|
|
void Rock::update(Grid *const g, int x, int y) { Sand::update(g, x, y); } |
|
|
|
|
} // namespace pengine
|
|
|
|
|