Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Background

I'm using a texture as a damage map represented by an array of floats for displaying damage effects on a space ship in a process.

http://i.stack.imgur.com/8MnwF.png

An upside of this is being able to 'slice' ships in half, using an input damage map with a line down the middle, as shown in the diagram below.

ShipInHalf

Question

However, I'm encountering problems separating this split ship into two different entities. I would like to be able to split the image down the 'damage line', in a process similar to this:

http://i.stack.imgur.com/IsTFr.png

I don't have much idea where to start detecting the red line above. Any advice would be welcome.

share|improve this question
    
If someone with sufficient reputation could convert my image links into actual images, that would be great. I had more images but had to remove them due to the 'spam prevention' mechanism. –  Simon Moles Jun 29 '12 at 18:12
add comment

1 Answer

Very interesting concept. The only thing I can think of is using Texture2D.GetData() to see the pixel data of your damage mask, iterate to find a sufficiently dark pixel, then use some basic maze-solving to follow it in a path through adjacent dark pixels. A stack-based algorithm (probably the simplest maze-solving ones) may work for this, but you're going to have to find something that's efficient enough for your desires. Basically, find the longest string of dark pixels you can.

Storing the start and end as a Vector2, you could calculate a line between them and use the angle and the distance to see if it bisects the rectangle area you define as your ship (not necessarily the whole texture, you'd need to manually define it I guess). To find out if it fully bisects the rectangle... I'll try to whip something up here, no guarantees:

float hypotenuse = damageLine.Length(); //this allows us to calculate trig stuff
float boxHeight = shipBoundingBox.Height;

//assuming the height of the box is its smallest dimension (i.e. long ships only, no fat 
//ones). it's possible to adapt this if your ship types vary; just use the smallest 
//dimension.
if (hypotenuse < boxHeight)
    return; //if the length is not long enough it could not possibly bisect it

float opposite = damageLine.X; //the x distance between start and end

float angle = (float)Math.Abs(Math.Asin(opposite/hypotenuse)); //this is the angle of the 
                                                               //line from y-axis

//now we can use trig to calculate the largest angle, based on the hypotenuse and the 
//vertical height of the bounding box, which would bisect the bounding box.
float largestAngle = (float)Math.Abs(Math.Acos(boxHeight / hypotenuse));

if (angle < largestAngle)
    doBisect(); //damage has bisected the rectangle
else
    return; //damage has not bisected the rectangle

Note that this would only check to see if you cut the ship in half width-wise (the way you've shown it in your example picture). You could easily use the dot product of the slice vector with Vector2.Right to see if the vector is actually length-wise on your ship, and switch a few values above for the calculations. Or, maybe there's a general formula you could adapt from that.

As for building new masks... perhaps extend the line you found so that the two points are at the edges of the texture, then use a RenderTarget2D to draw this new line on top of the existing damage texture. Using the equation of the line you could then fill in pixels above or below it for two successive draw calls, saving the RenderTarget2D as a different texture for both, then pass those on.

I'm sorry this is mostly ideas and less hard code, but I've never really thought about something like this before, and everything here would take some testing and tweaking to make it work. Hope it gives you something to go off of, though. The methods here would also only make straight cuts and not more complex ones, but I think that may be sufficient. If you use the damage texture with RenderTargets like I mentioned, it should retain the jagged edge.

share|improve this answer
    
Thanks for the insights (and sorry for the long delay before replying!) I'm exploring using an alternate method of expanding the physics collision mesh generated by Farseer Physics to clip the damage map right now, which seems like it will be simpler. –  Simon Moles Aug 2 '12 at 8:57
    
That sounds like a good plan. I haven't used Farseer much but I know it has a lot of great tools for this sort of thing. –  A-Type Aug 6 '12 at 14:48
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.