import java.awt.Color; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.RoundRectangle2D; import java.util.ArrayList; import java.util.HashMap; import org.jbox2d.common.Vec2; import org.jbox2d.dynamics.Body; import pulpcore.math.CoreMath; import pulpfizz.physics.Actor; import pulpfizz.physics.BodyUtils; import pulpfizz.physics.Material; import pulpfizz.physics.PolygonUtils; import pulpfizz.pulp.body.Java2DBodySprite; import pulpfizz.pulp.body.PhysicsLayer; import pulpfizz.pulp.body.ShapeBodyDrawer; public class Blokk extends Actor { PhysicsLayer physics; Body body; BodyShapes bodyShape; Java2DBodySprite sprite; long creationTime; public static final int BLOKK_GROUP = 0; public Blokk(PhysicsLayer physics, BodyShapes bodyShape) { this.physics = physics; this.bodyShape = bodyShape; creationTime = System.currentTimeMillis(); Shape s = getShape(bodyShape, 1f, 2f); body = getBody(bodyShape, s); body.setXForm(new Vec2(0, -30), 0); Actor a = new Actor(); setName("Blokk " + bodyShape.name()); addToGroup(BLOKK_GROUP); Material m = Material.WOOD(); m.setDensity(2); m.setRestitution(0.02f); m.setFriction(1.2f); m.applyAll(body); sprite = new Java2DBodySprite(body, physics, 1, Color.white, Color.white); sprite.setPadding(2); Area ar; ShapeBodyDrawer sbd = new ShapeBodyDrawer(s); sbd.setTexture(GameScene.IMG_LOC + "wood.jpg", 2, CoreMath.rand(0, 5), CoreMath.rand(0, 5)); sbd.setStrokePaint(sbd.getPaint()); sprite.setBodyDrawer(sbd); physics.add(sprite); // Hah, what a hack! physics.moveToTop(sprite); physics.moveDown(sprite); physics.moveDown(sprite); addBody(body); } private static HashMap typeToShape = new HashMap(); private Shape getShape(BodyShapes bodyType, float smallSide, float bigSide) { if (typeToShape.containsKey(bodyType)) { return typeToShape.get(bodyType); } Shape s = null; switch (bodyType) { case FULL_RECT: s = createRectangle(smallSide, bigSide); break; case HALF_RECT: s = createHalfRectangle(smallSide, bigSide); break; case FULL_TRIANGLE_L: s = createTriangle(smallSide, bigSide, false); break; case FULL_TRIANGLE_R: s = createTriangle(smallSide, bigSide, true); break; case HALF_TRIANGLE_L: s = createHalfTriangle(smallSide, bigSide, false); break; case HALF_TRIANGLE_R: s = createHalfTriangle(smallSide, bigSide, true); break; case FULL_CRESCENT: s = createFullCrescent(smallSide, bigSide); break; case FULL_CRESCENT_FILL: s = creatFullCrescentFill(smallSide, bigSide); break; case QUARTER_RECT: s = createQuarterRect(smallSide, bigSide); break; case SHORT_EDGE: s = createShortEdge(smallSide, bigSide); break; case LONG_EDGE: s = createLongEdge(smallSide, bigSide); break; } typeToShape.put(bodyType, s); return s; } private static HashMap typeToBody = new HashMap(); private Body getBody(BodyShapes bs, Shape s) { if (typeToBody.containsKey(bs)) { Body b = typeToBody.get(bs); Body newB = BodyUtils.cloneBody(b); return newB; } Body b = PolygonUtils.areaToBody(physics, s, 0.1f); typeToBody.put(bs, b); return b; } public static enum BodyShapes { FULL_RECT, HALF_RECT, FULL_TRIANGLE_L, FULL_TRIANGLE_R, HALF_TRIANGLE_L, HALF_TRIANGLE_R, FULL_CRESCENT, FULL_CRESCENT_FILL, QUARTER_RECT, SHORT_EDGE, LONG_EDGE } /* * All the block-creation functions take in the smallSide and bigSide params, and return a block cornered on (0,0) * NOTE: BigSide is in the X direction! */ final static double ROUND_OFF = 0f; /* * Full rectangle. */ private static Shape createRectangle(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); return rect; } /* * Half-rectangle. */ private static Shape createHalfRectangle(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide / 2, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); return rect; } private static Shape createTriangle(float smallSide, float bigSide, boolean flip) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); GeneralPath tri = new GeneralPath(); tri.moveTo(0, 0); tri.lineTo(0, smallSide); tri.lineTo(bigSide, smallSide); tri.lineTo(0, 0); tri.closePath(); Area rectA = new Area(rect); rectA.subtract(new Area(tri)); if (flip) { rectA = rectA.createTransformedArea(AffineTransform.getScaleInstance(1, -1)); } return rectA; } private static Shape createHalfTriangle(float smallSide, float bigSide, boolean flip) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide / 2, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); GeneralPath tri = new GeneralPath(); tri.moveTo(0, 0); tri.lineTo(0, smallSide); tri.lineTo(bigSide / 2, smallSide); tri.lineTo(0, 0); tri.closePath(); Area rectA = new Area(rect); rectA.subtract(new Area(tri)); if (flip) { rectA = rectA.createTransformedArea(AffineTransform.getScaleInstance(1, -1)); } return rectA; } private static Shape createFullCrescent(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); Ellipse2D.Float ell = new Ellipse2D.Float(); ell.setFrameFromCenter(bigSide / 2f, smallSide, bigSide * .2f, smallSide * .33f); Area rectA = new Area(rect); rectA.subtract(new Area(ell)); return rectA; } private static Shape creatFullCrescentFill(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, bigSide, smallSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); Ellipse2D.Float ell = new Ellipse2D.Float(); ell.setFrameFromCenter(bigSide / 2f, smallSide, bigSide * .2f, smallSide * .33f); Area rectA = new Area(rect); rectA.intersect(new Area(ell)); return rectA; } private static Shape createQuarterRect(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, smallSide / 2f, bigSide / 4f, smallSide * ROUND_OFF, smallSide * ROUND_OFF); return rect; } private static Shape createShortEdge(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, smallSide, bigSide / 4f, smallSide * ROUND_OFF, smallSide * ROUND_OFF); return rect; } private static Shape createLongEdge(float smallSide, float bigSide) { RoundRectangle2D.Double rect = new RoundRectangle2D.Double(); rect.setRoundRect(0, 0, smallSide / 2f, bigSide, smallSide * ROUND_OFF, smallSide * ROUND_OFF); return rect; } public void destroy() { body.getWorld().destroyBody(body); physics.remove(sprite); } }