Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by MD_Reptile · May 07, 2016 at 02:58 PM · pixelradiusdestructionpenetration

Destroying pixels of a dynamic 2D world based on hardness of a pixel?

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: alt text

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.

pic.png (18.8 kB)
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eno-Khaon · May 07, 2016 at 06:30 PM 0
Share

Is this using a bought/downloaded asset package, or are they all your own creations?

Either way, the line dividing your intent appears to be line 37:

 if (Game$$anonymous$$aster.G$$anonymous$$.pixel$$anonymous$$agic.isPixelSolid(x + i, y + j)) // returns true if the pixel is not "air" or a clear pixel

Depending on how it's retrieving data (for example, if it's an efficient-enough "is alpha zero?"), you could potentially create a variant which returns the value for that pixel rather than a boolean for whether it's "solid" or not.

Then, for each pixel, you can have a "blast strength" dropping off with its radius from the center pixel. If the value of the blast is greater than the value held in the pixel (or less than it, if 0 is solid and 255 (or 1, depending on scale) is empty), the pixel is eligible for destruction.

avatar image MD_Reptile Eno-Khaon · May 07, 2016 at 09:43 PM 0
Share

It's not based on any existing asset or anything, but very similar to Joe strouts asset "pixel surface" in nature.

I see what your saying, and I do have an alternative method that gives a int between 0 and 255 ins$$anonymous$$d of a bool value.

I guess what I'm hung up on is how can I keep track of something like "passed hardness" and if x amount has been "blown up" outwards, prevent any more removals after that.

Does this make sense? I guess this is very difficult to explain!

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Eno-Khaon · May 08, 2016 at 12:22 AM

If the value for a pixel is "air" then it doesn't need to be eligible to be blasted out. An if condition would settle that easily enough.

For every other pixel, you could perform a breadth-first search. Rather than looking for anything in particular, though, simply use this as your means of working away from the starting pixel. Test the center pixel (the strongest point for the blast), then work your way out from there.

For any pixel that is not blown up, save a note of its position. Then, on subsequent pixels, determine whether it should be protected by the pixels not blown up. If not, determine whether they're weak enough to be blown up.

 // Pseudo-code C#
 public float protectionAngle = 0.95f; (Dot Product-based angle
 System.Collections.Generic.List<Vector2> safePixels;
 float blastRange; // Maximum range of blast
 float blastStrength; // How strong is the blast initially?
 
 safePixels = new List<Vector2>();
 // Perform breadth-first search from center
 foreach pixel from center, radiating to a maximum of "blastRange" pixels' distance ((pixel - center).magnitude)
 {
     bool safe = false;
     for(int i = 0; i < safePixels.Count; i++)
     {
         if(Vector2.Dot(safePixels[i] - center, currentPixel - center) > protectionAngle)
         {
         safe = true;
         }
     }
     if(blastStrength > pixelHardness)
     {
         // Blow it up...
         // Then...
         blastStrength -= (pixelHardness * falloffRate); // falloffRate should be tiny, unless you want most of the explosive force lost when the blast is barely strong enough
     }
     else
     {
         safePixels.Add(current Vector2);
     }
 }

It'll take some engineering to get it all working together, but here's the concept in brief:

Start in the middle of the blast.

Radiate out toward the ends, determining whether...

1) Is the pixel shielded from the blast? If so, you're done. It's safe.

2) Is the blast is strong enough to destroy the pixel?

--a) If not, that one will now shield others behind it.

--b) If so, how much will the blast's remaining strength be reduced?

Perform these tests on each pixel until you reach the maximum range from the center (or any other boundaries) and make sure not to retest any pixel more than once.

Also, I didn't really add it in sooner, but the blast strength per pixel would basically be calculated as something like:

 Mathf.Lerp(0, blastStrength, (currentPixel - center).magnitude / blastRange);
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MD_Reptile · May 08, 2016 at 12:32 AM 0
Share

You know that sounds about right. I guess it makes more sense to breadth first search outwards from the impact rather than gather a surrounding square and deter$$anonymous$$e distance.

Thanks for this, if it works I'll convert your comment to an answer!

avatar image MD_Reptile MD_Reptile · May 09, 2016 at 05:06 PM 0
Share

Worked perfect! I have awarded you 3 entire points :P

Ended up using a queue to do breadth-first and using distance and "hardness" as almost a heuristic, I was able to get a cool result.

Thanks so much for the advice!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

42 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Help With Animation 1 Answer

Keep SphereCollider radius the same, even though scale is changed 2 Answers

Getting radius of a sphere 2 Answers

How can i make a object break when i am in range with the object, while holding another object in hand? 1 Answer

Get Pixel Coordinate When Click On 2D Object 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges