I want to blow up pixels that are part of a 2D terrain, and be able to have the explosion penetrate further through pixels depending on how “hard” the pixels are considered, with 0 being invincible, and 254 being super soft, and 255 being an empty pixel (air). I am not totally sure how I might go about doing that, even though I already can check how “hard” a pixel is…
Here is an image explaining what I want to happen:
In this example the grass would be “soft” and the dirt “somewhat hard” for instance…
Right now my explosion takes a square of pixels surrounding the explosions location, then within a certain radius they are removed from the world (what the PURPLE radius would be doing in my example) but with no consideration for the “hardness” of a pixel, but rather only if it is open (air) or solid (anything but air).
Here is a snippet of the C# code for removing pixels in explosions I use right now:
/* Explode */
// Creates an "explosion" by finding all pixels near a point and launching them away
public void explode(int xPos, int yPos, int radius)
{
// we don't explode if were hitting the boundaries, or shooting the open sky at an edge will explode!
if (xPos > 1 && yPos > 1 &&
xPos < worldWidth - 1 && yPos < worldHeight - 1)
{
radiusSq = radius * radius; // get a square radius for this explosion
explodePosition.x = xPos; // set the position where it will happen
explodePosition.y = yPos;
randomNumber = Random.Range(0, 99); // generate a random number between 0 and 99 to select a random sprite using...
CreateExplodeSprite(explodePosition, 0); // this is for the graphical "explosion" sprite to show
// loop through every x from xPos-radius to xPos+radius
for (int x = xPos - radius; x < xPos + radius; x += GameMaster.GM.DestructionResolution) // this "DestructionResolution" is always 1
{
// first make sure that the x is within terrain's boundaries
if (x >= 0 && x < worldWidth)//pD.SourceTexture.width)
{
// next loop through every y pos from yPos-radius to yPos+radius, having a "box" of the terrain we will check for whether or not its "solid"
for (int y = yPos - radius; y < yPos + radius; y += GameMaster.GM.DestructionResolution)
{
if (y >= 0 && y < worldHeight)//pD.SourceTexture.height) // boundary check
{
// first determine if this pixel (or if any contained within its square area) is solid
int solidX = 0, solidY = 0;
bool solid = false;
// loop through every pixel from (xPos,yPos) to (xPos + destructionRes, yPos + destructionRes)
// to find whether this area is solid or not
for (int i = 0; i < GameMaster.GM.DestructionResolution && !solid; i++) // if destruction resolution wasn't 1, this would loop through the "resolution" of pixels, but its 1...
{
for (int j = 0; j < GameMaster.GM.DestructionResolution && !solid; j++) // same here, this loops only a single time!
{
if (GameMaster.GM.pixelMagic.isPixelSolid(x + i, y + j)) // returns true if the pixel is not "air" or a clear pixel
{
solid = true;
solidX = x + i; // keep a reference to where that solid pixel is
solidY = y + j;
}
}
}
if (solid) // we know this pixel is solid, now we need to find out if it's close enough
{
float xDiff = x - xPos; // get the difference on x
float yDiff = y - yPos; // and y
float distSq = xDiff * xDiff + yDiff * yDiff; // as well as the the square distance
// if the distance squared is less than radius squared, then it's within the explosion radius
if (distSq < radiusSq)
{
// finally calculate the distance
float distance = Mathf.Sqrt(distSq);
if (distance == 0) // error prevention!
distance = 0.001f; // prevent divide by zero later
// remove the static pixels
for (int i = 0; i < GameMaster.GM.DestructionResolution; i++) // only loops once
{
for (int j = 0; j < GameMaster.GM.DestructionResolution; j++) // only loops once
{
GameMaster.GM.pixelMagic.removePixel(x + i, y + j); // remove the pixel from our terrain
}
}
}
}
}
}
}
}
}
}
So how could I go about considering how hard a pixel is, and then make the explosion radius shorter when it is hitting more “harder” pixels, and longer when hitting “softer” pixels, which would make my explosion have smaller or larger radius (to a certain maximum) depending how “hard” a pixel is… and not allow it to destroy “invincible” pixels?
If you made it this far through this wall of text and have any ideas please comment or answer with anything that might push me in the right direction, and psuedocode or whatever is totally acceptable for me! I am sure others have run into similar problems within voxel engines and 3D destruction games, and perhaps other situations. I’ll be here scratching my head about it.