Mercurial > hg > ristipolku
diff game/Piece.java @ 162:e8eeac403e5f
Backed out changeset fb33d3796942
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 01 Dec 2016 14:33:25 +0200 |
parents | src/Piece.java@fb33d3796942 |
children | 7bf508d363bd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/game/Piece.java Thu Dec 01 14:33:25 2016 +0200 @@ -0,0 +1,365 @@ +/* + * Ristipolku + * (C) Copyright 2011 Matti 'ccr' Hämäläinen <ccr@tnsp.org> + */ +package game; + +import java.awt.*; +import java.awt.geom.*; +import java.util.*; +import java.math.*; + + +public class Piece +{ + public enum RotateDir { LEFT, RIGHT } + + static final int numConnections = 8; + static final float maxTime = 50.0f; + + int currRotation; + int[] connections; + boolean[] states; + PieceType type, prevType; + + boolean rotationChanged, rotationActive, + typeChanged, typeActive, + stateChanged, stateActive, + active; + + float currAngle, rotationTime, rotationSpeed, + typeTime, typeValue, throbTime; + + Interpolate lerpRotation, + lerpScale, + lerpType; + + + public Piece(PieceType ptype) + { + // Initialize + connections = new int[numConnections]; + states = new boolean[numConnections]; + type = ptype; + + rotationChanged = false; + rotationActive = false; + currRotation = 4 * 5000; + currAngle = getAngle(currRotation); + + typeChanged = false; + typeActive = false; + + throbTime = 0; + + lerpType = new Interpolate(1.0f, 0.0f, maxTime); + lerpScale = new Interpolate(0.0f, (float) Math.PI, maxTime); + + // Initialize connections between endpoints of the paths inside the piece + for (int i = 0; i < numConnections; i++) + connections[i] = -1; + + + // Randomize connections in the piece + Random rnd = new Random(); + for (int i = 0; i < numConnections; i++) + { + while (connections[i] < 0) + { + int tmp = rnd.nextInt(numConnections); + if (tmp != i && connections[tmp] < 0) + { + connections[i] = tmp; + connections[tmp] = i; + } + } + } + } + + public Piece() + { + this(PieceType.NONE); + } + + + public void changed() + { + typeChanged = true; + } + + public void setType(PieceType ptype) + { +// typeChanged = (prevType != ptype) && (ptype == PieceType.LOCKED); + prevType = type; + type = ptype; + } + + public void clearStates() + { + for (int i = 0; i < numConnections; i++) + states[i] = false; + stateChanged = true; + } + + public int getRotation() + { + return currRotation % 4; + } + + public int getRotatedPoint(int in) + { + int point = (in - (getRotation() * 2)) % 8; + if (point < 0) point = 8 + point; + return point; + } + + public int getAntiRotatedPoint(int in) + { + int point = (in + (getRotation() * 2)) % 8; + if (point < 0) point = 8 + point; + return point; + } + + public int getMatchingPoint(int point) + { + switch (point) + { + case 0: return 5; + case 1: return 4; + + case 2: return 7; + case 3: return 6; + + case 4: return 1; + case 5: return 0; + + case 6: return 3; + case 7: return 2; + } + return -1; + } + + public void setConnectionState(int point, boolean state) + { + states[point] = state; + states[connections[point]] = state; + stateChanged = true; + } + + public int getConnection(int point) + { + return connections[point]; + } + + private float getAngle(float rotation) + { + return (float) ((rotation * Math.PI) / 2.0f); + } + + public void rotate(RotateDir dir) + { + // Only normal + if (type != PieceType.LOCKED && type != PieceType.ACTIVE) + return; + + currRotation = (currRotation + (dir == RotateDir.RIGHT ? 1 : -1)); + lerpRotation = new Interpolate(getAngle(currRotation), currAngle, maxTime); + rotationChanged = true; + } + + public Point2D getPointCoords(float x, float y, float dim, int index) + { + float ox = 0, oy = 0; + float step = dim / 10; + + switch (index) { + // Normal line starting and ending points + case 0: ox = 3.0f; oy = 0.4f; break; + case 1: ox = 7.0f; oy = 0.4f; break; + + case 2: ox = 9.6f; oy = 3.0f; break; + case 3: ox = 9.6f; oy = 7.0f; break; + + case 4: ox = 7.0f; oy = 9.6f; break; + case 5: ox = 3.0f; oy = 9.6f; break; + + case 6: ox = 0.4f; oy = 7.0f; break; + case 7: ox = 0.4f; oy = 3.0f; break; + + + // Matching control points for each point above (+8) + case 8: ox = 3.0f; oy = 2.5f; break; + case 9: ox = 7.0f; oy = 2.5f; break; + + case 10: ox = 7.5f; oy = 3.0f; break; + case 11: ox = 7.5f; oy = 7.0f; break; + + case 12: ox = 7.0f; oy = 7.5f; break; + case 13: ox = 3.0f; oy = 7.5f; break; + + case 14: ox = 2.5f; oy = 7.0f; break; + case 15: ox = 2.5f; oy = 3.0f; break; + } + + return new Point2D.Float(x + ox * step, y + oy * step); + } + + public PieceType getType() + { + return type; + } + + public void animate(float time) + { + active = false; + + if (rotationChanged) + { + rotationTime = time; + rotationActive = true; + rotationChanged = false; + rotationSpeed = 1.0f; + } + + if (typeChanged && type == PieceType.LOCKED) + { + rotationSpeed = 1.5f; + } + + if (rotationActive) + { + float t = (time - rotationTime) * rotationSpeed; + + if (t < maxTime) + { + currAngle = lerpRotation.getValue(t); + } + else + { + currAngle = lerpRotation.start; + rotationActive = false; + } + + active = true; + } + + if (typeChanged) + { + typeTime = time; + typeActive = true; + typeChanged = false; + } + + if (typeActive) + { + float t = (time - typeTime) * 2.0f; + + if (t < maxTime) + { + typeValue = lerpType.getValue(t); + } + else + { + typeValue = lerpType.start; + typeActive = false; + } + + + active = true; + } + + if (stateChanged) + { + } + + throbTime = (time % 100) / 100.0f; + } + + public void paint(Graphics2D g, float x, float y, float dim) + { + AffineTransform save = g.getTransform(); + Composite csave = g.getComposite(); + + + // Change compositing alpha for the whole piece drawing + // when the piece is being "introduced". + if (typeActive) + { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, typeValue)); + } + + + // Transform drawing by current angle + g.rotate(currAngle, x + dim / 2.0f, y + dim / 2.0f); + + // Color piece by type + switch (type) { + case LOCKED: g.setPaint(new Color(0.3f, 0.8f, 0.3f, 0.35f)); break; + case ACTIVE: g.setPaint(new Color(0.9f, 0.3f, 0.3f, 0.35f)); break; + case START: g.setPaint(new Color(1.0f, 0.6f, 0.0f, 0.95f)); break; + } + + float corner = dim / 10.0f; + g.fill(new RoundRectangle2D.Float(x, y, dim, dim, corner, corner)); + + // Start pieces (center piece) have a different kind of border + // and no connections drawn inside + if (type == PieceType.START) + { + // Draw piece border + g.setPaint(Color.black); + g.setStroke(new BasicStroke(2.0f)); + g.draw(new RoundRectangle2D.Float(x, y, dim, dim, corner, corner)); + } + else + { + // Active piece has a throbbing "ghost" border + if (type == PieceType.ACTIVE) + { + float offs1 = throbTime * 10.0f, + offs2 = throbTime * 20.0f; + + g.setPaint(new Color(0.0f, 0.0f, 0.0f, (float) (1.0f - throbTime) )); + g.setStroke(new BasicStroke(2.0f + throbTime * 2.0f)); + g.draw(new RoundRectangle2D.Float( + x - offs1, y - offs1, + dim + offs2, dim + offs2, + corner, corner)); + } + + // Draw piece border + g.setPaint(new Color(0.0f, 0.0f, 0.0f, 0.6f)); + g.setStroke(new BasicStroke(5.0f)); + g.draw(new RoundRectangle2D.Float(x, y, dim, dim, dim / 10, dim / 10)); + + // Draw the connections + g.setStroke(new BasicStroke(5.5f)); + CubicCurve2D curve = new CubicCurve2D.Float(); + boolean[] drawn = new boolean[numConnections]; + for (int i = 0; i < numConnections; i++) + if (!drawn[i]) + { + Point2D start, cp1, cp2, end; + boolean isActive = states[i] || states[connections[i]]; + + g.setPaint(isActive ? Color.white : Color.black); + + start = getPointCoords(x, y, dim, i); + end = getPointCoords(x, y, dim, connections[i]); + cp1 = getPointCoords(x, y, dim, i + 8); + cp2 = getPointCoords(x, y, dim, connections[i] + 8); + + curve.setCurve(start, cp1, cp2, end); + g.draw(curve); + + // Mark connection drawn, so we don't overdraw + drawn[i] = true; + drawn[connections[i]] = true; + } + + } // !PieceType.START + + g.setTransform(save); + g.setComposite(csave); + } +}