Package com.jcloisterzone.ui.grid.layer

Source Code of com.jcloisterzone.ui.grid.layer.MeepleLayer

package com.jcloisterzone.ui.grid.layer;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.swing.ImageIcon;

import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.pointer.FeaturePointer;
import com.jcloisterzone.event.MeepleEvent;
import com.jcloisterzone.feature.Bridge;
import com.jcloisterzone.feature.Feature;
import com.jcloisterzone.figure.BigFollower;
import com.jcloisterzone.figure.Follower;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.figure.SmallFollower;
import com.jcloisterzone.ui.ImmutablePoint;
import com.jcloisterzone.ui.grid.GridPanel;

public class MeepleLayer extends AbstractGridLayer {

    public static final double FIGURE_SIZE_RATIO = 0.35;

    /**
     * Corn circles allows multiple meeples on single feature.
     * In such case double meeple should be displayed after common ones.
     */
    private LinkedList<MeeplePositionedImage> images = new LinkedList<>();
    //TODO own layer ???
    private List<PositionedImage> permanentImages = new ArrayList<>();

    public MeepleLayer(GridPanel gridPanel) {
        super(gridPanel);
    }

    private void paintPositionedImage(Graphics2D g, PositionedImage mi, int boxSize) {
        ImmutablePoint scaledOffset = mi.getScaledOffset(boxSize);
        //TODO optimize also for scrolling
        if (mi.scaledImage == null) {
            int size = (int) (getSquareSize() * FIGURE_SIZE_RATIO);
            Image img = mi.sourceImage.getScaledInstance(size, size, Image.SCALE_SMOOTH);
            mi.scaledImage = new ImageIcon(img).getImage();
        }
        g.drawImage(mi.scaledImage, getOffsetX(mi.position) + scaledOffset.getX(), getOffsetY(mi.position) + scaledOffset.getY(), gridPanel);
    }

    @Override
    public void paint(Graphics2D g) {
        int boxSize = (int) (getSquareSize() * FIGURE_SIZE_RATIO); //TODO no resize - direct image resize???
        for (MeeplePositionedImage mi : images) {
            if (!mi.bridgePlacement) {
                paintPositionedImage(g, mi, boxSize);
            }
        }
        for (PositionedImage mi : permanentImages) {
            paintPositionedImage(g, mi, boxSize );
        }

    }

    public void paintMeeplesOnBridges(Graphics2D g) {
        int boxSize = (int) (getSquareSize() * FIGURE_SIZE_RATIO); //TODO no resize - direct image resize???
        for (MeeplePositionedImage mi : images) {
            if (mi.bridgePlacement) {
                paintPositionedImage(g, mi, boxSize );
            }
        }
    }

    @Override
    public void zoomChanged(int squareSize) {
        for (MeeplePositionedImage mi : images) {
            mi.scaledImage = null;
        }
        for (PositionedImage mi : permanentImages) {
            mi.scaledImage = null;
        }
        super.zoomChanged(squareSize);
    }

    private MeeplePositionedImage createMeepleImage(Class<? extends Meeple> type, Color c, FeaturePointer fp) {
        Feature feature = getGame().getBoard().get(fp);
        ImmutablePoint offset = getClient().getResourceManager().getMeeplePlacement(feature.getTile(), type, fp.getLocation());
        Image image = getClient().getFigureTheme().getFigureImage(type, c, getExtraDecoration(type, fp));
        if (fp.getLocation() == Location.ABBOT) {
            image = rotate(image, 90);
        }
        return new MeeplePositionedImage(type, fp, offset, image, feature instanceof Bridge);
    }

    private void rearrangeMeeples(FeaturePointer fp) {
        int order = 0;
        //small followers first
        for (MeeplePositionedImage mi : images) {
            if (mi.location == fp.getLocation() && mi.position.equals(fp.getPosition())) {
                if (mi.meepleType.equals(SmallFollower.class)) {
                    mi.order = order++;
                }
            }
        }
        //others on top
        for (MeeplePositionedImage mi : images) {
            if (mi.location == fp.getLocation() && mi.position.equals(fp.getPosition())) {
                if (!mi.meepleType.equals(SmallFollower.class)) {
                    mi.order = order++;
                }
            }
        }
    }

    public void meepleDeployed(MeepleEvent ev) {
        Color c = ev.getMeeple().getPlayer().getColors().getMeepleColor();
        images.add(createMeepleImage(ev.getMeeple().getClass(), c, ev.getTo()));
        rearrangeMeeples(ev.getTo());
    }

    public void meepleUndeployed(MeepleEvent ev) {
        Iterator<MeeplePositionedImage> iter = images.iterator();
        while (iter.hasNext()) {
            MeeplePositionedImage mi = iter.next();
            if (mi.match(ev.getMeeple().getClass(), ev.getFrom())) {
                iter.remove();
                break;
            }
        }
        rearrangeMeeples(ev.getFrom());
    }

    public void addPermanentImage(Position position, ImmutablePoint offset, Image image) {
        permanentImages.add(new PositionedImage(position, offset, image));
    }


    //TODO path from Theme
    public String getExtraDecoration(Class<? extends Meeple> type, FeaturePointer fp) {
        if (Follower.class.isAssignableFrom(type) && fp.getLocation().isFarmLocation()) {
            return "farm.png";
        }
        if (fp.getLocation() == Location.TOWER) {
            if (BigFollower.class.isAssignableFrom(type)) {
                return "big_tower.png";
            } else {
                return "tower.png";
            }
        }
        return null;
    }

    private class PositionedImage {
        public final Position position;
        public final ImmutablePoint offset;
        public final Image sourceImage;
        public Image scaledImage;

        public PositionedImage(Position position, ImmutablePoint offset, Image sourceImage) {
            this.position = position;
            this.offset = offset;
            this.sourceImage = sourceImage;
        }

        public ImmutablePoint getScaledOffset(int boxSize) {
            return offset.scale(getSquareSize(), boxSize);
        }
    }

    private class MeeplePositionedImage extends PositionedImage {
         public final Class<? extends Meeple> meepleType;
         public final Location location;
         public final boolean bridgePlacement;
         public int order;

         public MeeplePositionedImage(Class<? extends Meeple> meepleType, FeaturePointer fp, ImmutablePoint offset, Image sourceImage, boolean bridgePlacement) {
             super(fp.getPosition(), offset, sourceImage);
             this.meepleType = meepleType;
             location = fp.getLocation();
             this.bridgePlacement = bridgePlacement;
         }

         public ImmutablePoint getScaledOffset(int boxSize) {
             ImmutablePoint point = offset;
             if (order > 0) {
                 point = point.translate(10*order, 0);
             }
             return point.scale(getSquareSize(), boxSize);
         }

         public boolean match(Class<? extends Meeple> meepleType, FeaturePointer fp) {
             if (!meepleType.equals(this.meepleType)) return false;
             if (location != fp.getLocation()) return false;
             if (!position.equals(fp.getPosition())) return false;
             return true;
         }
    }

    //TODO better use affine transform while drawing
    @Deprecated
    public static Image rotate(Image img, double angle) {
        double sin = Math.abs(Math.sin(Math.toRadians(angle))),
               cos = Math.abs(Math.cos(Math.toRadians(angle)));

        int w = img.getWidth(null), h = img.getHeight(null);

        int neww = (int) Math.floor(w*cos + h*sin),
            newh = (int) Math.floor(h*cos + w*sin);

        BufferedImage bimg = new BufferedImage(neww, newh, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bimg.createGraphics();

        g.translate((neww-w)/2, (newh-h)/2);
        g.rotate(Math.toRadians(angle), w/2, h/2);
        g.drawRenderedImage(toBufferedImage(img), null);
        g.dispose();
        return bimg;
    }

    private static BufferedImage toBufferedImage(Image img)
    {
        if (img instanceof BufferedImage)
        {
            return (BufferedImage) img;
        }

        // Create a buffered image with transparency
        BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);

        // Draw the image on to the buffered image
        Graphics2D bGr = bimage.createGraphics();
        bGr.drawImage(img, 0, 0, null);
        bGr.dispose();

        // Return the buffered image
        return bimage;
    }

}
TOP

Related Classes of com.jcloisterzone.ui.grid.layer.MeepleLayer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.