I wanted to have dynamic terrain in my game, so I created a hack for Phys2D that allows for destruction of small portions of Shapes. Basically if you've got a square and take a circle out of the edge, you get a polygonal Shape that looks like a "bite" out of a square.
The actual function I wrote appears to work, except actual implementation is very difficult, because doing this creates a huge number of artifacts. And rather than redo all the complicated geometry myself, I just convert the Shape to an Area (from java.awt.geom), then back to a Shape again after subtracting. This therefore allows you to do any and every of Area's modifications to Phys2D Shapes. But, once again, lots of artifacts when adding these shapes back into the world, especially if a shape splits into several. But it's a good experiment nonetheless, and I'll post implementation code when I actually have that working okay.
There are a few strange results here, like when cubes get turned into polygons, Phys2D treats them differently, and once you put any shape into this it comes out a polygon. So, certain shapes may act one way and then come out completely different, even though they look the same. I only want to use this on static bodies myself, so lots of these issues shouldn't matter too much for me.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| package apk;
import net.phys2d.math.Vector2f; import net.phys2d.math.ROVector2f; import java.awt.geom.*; import java.util.ArrayList;
public class ShapeSubtractor { public static ArrayList<net.phys2d.raw.shapes.Shape> subtract(ROVector2f pos, net.phys2d.raw.shapes.Shape original, java.awt.Shape subtract) { if (original instanceof net.phys2d.raw.shapes.Line) return null; Area o = new Area(phys2dToAwt(pos, original)); o.subtract(new Area(subtract)); return awtToPhys2d(pos, o); } private static java.awt.Shape phys2dToAwt(ROVector2f pos, net.phys2d.raw.shapes.Shape s) { if (s instanceof net.phys2d.raw.shapes.Circle) { net.phys2d.raw.shapes.Circle c = (net.phys2d.raw.shapes.Circle) s; return new Ellipse2D.Float(pos.getX(),pos.getY(),c.getRadius(),c.getRadius()); } else if (s instanceof net.phys2d.raw.shapes.Box) { net.phys2d.raw.shapes.Box b = (net.phys2d.raw.shapes.Box) s; return new Rectangle2D.Float(pos.getX(),pos.getY(),b.getSize().getX(),b.getSize().getY()); } else if (s instanceof net.phys2d.raw.shapes.Polygon) { net.phys2d.raw.shapes.Polygon p = (net.phys2d.raw.shapes.Polygon) s; ROVector2f[] verts = p.getVertices(); int[] x = new int[verts.length]; int[] y = new int[verts.length]; for (int i = 0; i < verts.length; i++) { x[i] = Math.round(verts[i].getX() + pos.getX()); y[i] = Math.round(verts[i].getY() + pos.getY()); } return new java.awt.Polygon(x,y,verts.length); } return null; } private static ArrayList<net.phys2d.raw.shapes.Shape> awtToPhys2d(ROVector2f pos, Area a) { ArrayList<net.phys2d.raw.shapes.Shape>polygons = new ArrayList<net.phys2d.raw.shapes.Shape>(); ArrayList<Point2D.Float> current = new ArrayList<Point2D.Float>(); PathIterator pi = a.getPathIterator(null); float [] pt = new float [6]; while (! pi.isDone()) { int code = pi.currentSegment(pt); if (code == PathIterator.SEG_MOVETO) { if (current.size() > 0) current.clear(); current.add(new Point2D.Float(pt[0],pt[1])); } else if (code == PathIterator.SEG_CLOSE) { if (current.size() > 2) { Vector2f[] points = new Vector2f[current.size()]; for (int i = current.size()-1; i >= 0; i--) points[current.size()-i-1] = new Vector2f(current.get(i).x-pos.getX(),current.get(i).y-pos.getY()); polygons.add(new net.phys2d.raw.shapes.Polygon(points)); } } else if (code == PathIterator.SEG_LINETO) { current.add(new Point2D.Float(pt[0],pt[1])); } pi.next (); } return polygons; } } |
Also, I would love if Kev or someone could come up with some more intelligent way of doing this and implemented it into Phys2D. I'm not good at all with Bezier curves and all that... I just already had made a function written for converting Area to Polygon, and putting destructible terrain into my current Phys2D game would be great. So I'm basically testing if it's possible.
[EDIT] Looks like maybe I've got a bug of some kind in here, although I need to test more to be sure. Some shape cuts are all hokey, while others are good. But I have a final in 13 hours I haven't studied for, so I think I'll take a more detailed look tomorrow.

[/EDIT]