package org.ripple.power.ui.projector.action.sprite; import java.awt.Graphics2D; import java.awt.Image; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import org.ripple.power.ui.graphics.LGraphics; import org.ripple.power.ui.graphics.geom.RectBox; import org.ripple.power.utils.GraphicsUtils; import org.ripple.power.utils.MathUtils; public class SpriteRotateSheet { private final int width, height, halfWidth, halfHeight; private int number, bitmapWidth, bitmapHeight; private boolean isCircle; private BufferedImage sheetRotationImages; public SpriteRotateSheet(String fileName, int number, boolean c) { this(GraphicsUtils.loadImage(fileName), number, c); } public SpriteRotateSheet(Image img, int number, boolean c) { this.isCircle = c; this.number = number; this.width = img.getWidth(null); this.height = img.getHeight(null); if (!suited(width, height)) { throw new RuntimeException("size not allowed :" + width + "," + height); } this.halfWidth = width / 2; this.halfHeight = height / 2; this.bitmapWidth = width; this.bitmapHeight = height; Graphics2D g = null; if (c) { this.sheetRotationImages = GraphicsUtils.createImage(width * number + width, height, true); g = sheetRotationImages.createGraphics(); int x; for (int i = 0; i < number; i++) { x = i * width; double degrees = Math.toRadians(i * 360 / number); g.setTransform(AffineTransform.getRotateInstance(degrees, x + halfWidth, halfHeight)); g.drawImage(img, x, 0, null); } } else { RectBox[] lazyRotates = new RectBox[360]; for (int i = 0; i < number; i++) { int index = i * 360 / number; RectBox rect = MathUtils.getBounds(0, 0, width, height, index); lazyRotates[i] = rect; bitmapWidth = Math.max(bitmapWidth, rect.width); bitmapHeight = Math.max(bitmapHeight, rect.height); } this.sheetRotationImages = GraphicsUtils.createImage(bitmapWidth * number + bitmapWidth, bitmapHeight, true); g = sheetRotationImages.createGraphics(); int x = 0; for (int i = 0; i < number; i++) { double degrees = Math.toRadians(i * 360 / number); RectBox rect = lazyRotates[i]; x = (i * (bitmapWidth)); g.setTransform(AffineTransform.getRotateInstance(degrees, x + rect.width / 2, rect.height / 2)); g.drawImage(img, x + (rect.width - width) / 2, (rect.height - height) / 2, null); } lazyRotates = null; } if (g != null) { g.dispose(); g = null; } } public static boolean suited(int w, int h) { return (w == h || (w > 16 && w < 64 && h > 16 && h < 64)) && (w <= 256 && h <= 256); } public void draw(LGraphics g, int x, int y, double rotation) { if (sheetRotationImages != null) { synchronized (sheetRotationImages) { while (rotation < 0) { rotation += 360; } while (rotation > 360) { rotation -= 360; } int spriteIndex = (int) (rotation * number / 360); if (isCircle) { x = (int) x - halfWidth; y = (int) y - halfHeight; } else { double rotate = Math.toRadians(rotation); double sinA = Math.sin(rotate); double cosA = Math.cos(rotate); x = (int) (x - (halfWidth - (halfWidth * cosA - halfHeight * sinA))); y = (int) (y - (halfHeight - (halfHeight * cosA + halfWidth * sinA))); } g.drawImage(sheetRotationImages, x, y, x + bitmapWidth, y + bitmapHeight, spriteIndex * bitmapWidth, 0, (spriteIndex * bitmapWidth + bitmapWidth), bitmapHeight); } } } public void dispose() { if (sheetRotationImages != null) { synchronized (sheetRotationImages) { sheetRotationImages.flush(); sheetRotationImages = null; } } } public BufferedImage getSheetImage() { return sheetRotationImages; } public int getHeight() { return height; } public int getNumber() { return number; } public int getWidth() { return width; } }