package ch.bfh.sevennotseven; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; /** * FieldCanvas class, implements the field to draw upon. Draws the game field and handles mouse actions. * * @author timo */ public class FieldCanvas extends JPanel{ // private and static members private static final long serialVersionUID = 1L; static final int borderLeft = 5; static final int borderRight = 5; static final int borderTop = 5; static final int borderBottom = 5; //Colors to use to paint the blocks. Chosen with a color scheme designer public static final Color[] colors = { new Color(0xD66436), new Color(0x486F70), new Color(0xCBD840), new Color(0x8B2700), new Color(0x33CCCC) }; private Game game; private Point src; //Position of the Block that the user wants to move (can be null) private Point dst; //Destination Position (can be null) private List path; //Path that visualizes src->dst (can be null) private List blockedFields; //Fields that should be marked as blocked (can be null) private boolean freeMoveMode = false; //Whether or not we're in free moving mode /** * Constructor of FieldCanvas * * @author timo * @param g */ FieldCanvas(Game g){ MouseAdapter ad = new MouseAdapter(){ @Override public void mousePressed(MouseEvent e) { super.mousePressed(e); Point p = FieldCanvas.this.getClickPoint(e.getPoint()); if(p==null || game.getField()[p.x][p.y]==0) { //invalid click (outside of bounds or on empty position) src = null; } else { //valid click src = p; if(freeMoveMode) { blockedFields = game.getReachablePoints(src); } else { blockedFields = game.getUnreachablePoints(src); } repaint(); } } @Override public void mouseDragged(MouseEvent e) { super.mouseDragged(e); if(src!=null) { //we have a valid point that the users wants to move Point lastDst = dst; dst = FieldCanvas.this.getClickPoint(e.getPoint()); if(lastDst!=dst && dst!=null) { //hovered field changed if(freeMoveMode) { //Check if the target position is empty and we could not move the block there in normal mode if(!game.canMove(src, dst) && game.getField()[dst.x][dst.y]==0) { //Create fake path with only src and dst path = new ArrayList(); path.add(src); path.add(dst); } else { path= null; } } else { //not in freemove mode path= game.getPath(src, dst); //calculate path from src to dst (pathfinding) } repaint(); } } else { //no valid src dst = null; path = null; } }; @Override public void mouseReleased(MouseEvent e) { super.mouseReleased(e); dst = FieldCanvas.this.getClickPoint(e.getPoint()); path = null; //do no longer paint path if(freeMoveMode) { if(!game.canMove(src, dst)) { //if we couldn't move there in normal mode game.doFreeMove(src, dst); } } else { //not in freemove mode if(dst != null && src!=null && !src.equals(dst)) { //src and dst are valid System.out.println("Moving from "+src.toString()+ " to "+dst.toString()); game.doMove(src, dst); } } freeMoveMode = false; src = null; blockedFields = null; repaint(); } }; addMouseListener(ad); addMouseMotionListener(ad); this.game=g; } /** * Callback if button freeMove gets pressed. * * @author timo */ public void toggleFreeMove() { if(freeMoveMode) { freeMoveMode =false; } else if(game.getAvailFreeMoves()>0) { freeMoveMode = true; } repaint(); } /** * Callback if button undo gets pressed. * * @author timo */ public void doUndo() { if(game.getAvailUndo()>0) { game.doUndo(); repaint(); } } /** * Maps a mouse position to game coordinates * * @author timo * @param globalPos Position of clickevent * @return point in game coordinates */ private Point getClickPoint(Point globalPos) { int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight); int space = total/game.getSize(); globalPos.translate(-borderLeft, -borderTop); if(globalPos.x<0 || globalPos.x >total || globalPos.y < 0 || globalPos.y > total) return null; return new Point(globalPos.x/space,globalPos.y/space); } /** * Paint the game field. * * @author timo */ public void paintComponent(Graphics g) { super.paintComponent(g); if(game==null) return; //Draw field (background and lines) if(freeMoveMode) { g.setColor(Color.gray); } else { g.setColor(Color.lightGray); } g.translate(borderLeft, borderTop); int total = Math.min(this.getHeight()-borderTop-borderBottom,FieldCanvas.this.getWidth()-borderLeft-borderRight); int space = total/game.getSize(); total = space*game.getSize(); g.setClip(0, 0, total+1,total+1); g.fillRect(0, 0, total,total); g.setColor(Color.white); for(int i=0; i<=game.getSize(); i++) { g.drawLine(0,i*space,total,i*space); g.drawLine(i*space,0,i*space,total); } //Draw blocks for(int x=0; x