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);
+    }
+}