package org.artisanlogiciel.games; import java.awt.BorderLayout; import java.awt.image.BufferedImage; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.LinkedList; import java.util.Locale; import java.util.Scanner; import java.util.ResourceBundle; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.artisanlogiciel.games.stl.Wall3d; import org.artisanlogiciel.util.UTF8Control; import org.artisanlogiciel.graphics.Drawing; import org.artisanlogiciel.graphics.DrawingLine; import org.artisanlogiciel.graphics.SvgWriter; /** * Display is Main JFrame for this tool **/ public class Display extends JFrame { // to please eclipse, not supposed to be serialized private static final long serialVersionUID = 8500214871372184418L; final static ResourceBundle labels = ResourceBundle.getBundle("LabelsBundle", Locale.getDefault(), Display.class.getClassLoader(), new UTF8Control()); MazeComponent maze; MazeControler controler; LabyModel model; JPanel controlPanel; boolean autoSize; MazeParams params = null; Drawing drawing = new Drawing(); Display(LabyModel model,int W, int H, MazeParams params) { super(labels.getString("title")); if (params != null) { // fixedParams = new MazeParamsFixed(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth()); this.params = params; } this.model = model; maze = createMazeComponent(model,W,H); Container con = this.getContentPane(); JScrollPane scrollableMaze = new JScrollPane(maze); scrollableMaze.addMouseMotionListener(maze); con.add(scrollableMaze, BorderLayout.CENTER); controler = new MazeControler(params); con.add(controler.getMoveControl(), BorderLayout.NORTH); con.add(controler.getGenerationControl(), BorderLayout.SOUTH); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { if ( autoSize ) { maze.getAutoSize(); } } }); model.setMazeListener(maze); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(W, H, W, H); setVisible(true); } private static MazeComponent createMazeComponent(LabyModel model, int W, int H) { MazeCellParameters cp = new MazeCellParameters(model.getWidth(),model.getHeight(), W, H, 3, 3); MazeComponent comp = new MazeComponent(model, cp); return comp; } void recreateModel() { // recreate labyrinth if (params != null) { params = controler.getSettings().getParams(); // keep current model... // model = new LabyModel(params, new java.util.Random()); maze.resetWallsProvider(model); model.setMazeListener(maze); model.reset(); // we are in GUI event thread, need to release it and do it outside. new Thread() { public void run() { model.generateWithEntry(0, 0); model.addEntryOrExit(-1, 0); model.addEntryOrExit(params.getWidth(), params.getHeight() - 1); } }.start(); } } void resetModel() { // recreate labyrinth if (params != null) { params = controler.getSettings().getParams(); model = new LabyModel(params, new java.util.Random()); maze.resetWallsProvider(model); model.setMazeListener(maze); // we are in GUI event thread, need to release it and do it outside. new Thread() { public void run() { maze.changed(null,null,model); } }.start(); } } void resolve() { model.reset(); model.resolve(model.getWidth() - 1, model.getHeight() - 1, maze); } void goNorth() { maze.goNorth(); } void goSouth() { maze.goSouth(); } void goEast() { maze.goEast(); } void goWest() { maze.goWest(); } void setWallSize(int size) { maze.setWallSize(size); } void setAutoSize(boolean autoSize) { this.autoSize = autoSize; if ( autoSize ) { maze.getAutoSize(); } } void addWallInDrawing(int pX, int pY, Drawing d) { short walls = model.getWalls(pX,pY); short wdrawn = 0; // todo int w = 2; int h = 2; int ox=0; int oy=0; int x = ox + (int) (pX * w); int y = oy + (int) (pY * h); DrawingLine dl = new DrawingLine(); // order matters since all points are linked if ( (pY == 0) && LabyModel.isFlagSet(walls,Brick.UP) ) { dl.addPoint(new Point(x, y)); dl.addPoint(new Point(x + (int) w, y)); wdrawn |= Brick.UP; } if (LabyModel.isFlagSet(walls,Brick.RIGHT)) { if ( ! LabyModel.isFlagSet(wdrawn,Brick.UP) ) { dl.addPoint(new Point(x + (int) w, y)); } dl.addPoint(new Point(x + (int) w, y + (int) h)); wdrawn |= Brick.RIGHT; } if (LabyModel.isFlagSet(walls,Brick.DOWN)) { if ( ! LabyModel.isFlagSet(wdrawn,Brick.RIGHT) ) { if (wdrawn != 0) { d.addLine(dl); dl = new DrawingLine(); } dl.addPoint(new Point(x + (int) w, y + (int) h)); } dl.addPoint(new Point(x, y + (int) h)); wdrawn |= Brick.DOWN; } if ( (pX == 0 ) && LabyModel.isFlagSet(walls,Brick.LEFT)) { if ( ! LabyModel.isFlagSet(wdrawn,Brick.DOWN) ) { if (wdrawn != 0) { d.addLine(dl); dl = new DrawingLine(); } dl.addPoint(new Point(x, y + (int) h)); } dl.addPoint(new Point(x, y)); wdrawn |= Brick.LEFT; } if (wdrawn != 0) { d.addLine(dl); } } Drawing createDrawing() { Drawing d = new Drawing(); { short walls; // draw all walls within clip bounds horiz first then lines for (int y = 0; y < model.getHeight(); y++) { for (int x = 0; x < model.getWidth(); x ++) { addWallInDrawing(x,y,d); } } } return d; } // to allow to log / write somewher into screen... void writeSentence(String pSentence) { // TODO System.out.println( pSentence); } void writeError(String pError) { System.err.println(pError); } void saveImc() { Drawing d = createDrawing(); if ( d != null ) { File outfile = new File(params.getSaveDir(), params.getName() + ".imc"); writeSentence("Saving to " + outfile + " ..."); try { DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile)); d.saveLinesKompressed(out); out.flush(); out.close(); writeSentence("... Done."); } catch (IOException io) { io.printStackTrace(System.err); } } } void saveSvg() { Drawing d = createDrawing(); if ( d != null ) { File outfile = new File(params.getSaveDir(), params.getName() + ".svg"); writeSentence("Saving to " + outfile + " ..."); try { DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile)); SvgWriter writer = new SvgWriter(d.getInternLines()); writer.writeTo(out); out.flush(); out.close(); writeSentence("... Done."); } catch (IOException io) { io.printStackTrace(System.err); } } else { writeError("drawing creation failed"); } } void savePng() { File file = new File("snapshot.png"); // BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_ARGB); BufferedImage bi = new BufferedImage(maze.getSize().width, maze.getSize().height, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.createGraphics(); // this.paint(g); maze.paint(g); g.dispose(); try{ ImageIO.write(bi,"png",file); }catch (Exception e) { e.printStackTrace(); } } private class MazeSettings extends JPanel { MazeParams params; JTextField textWidth = null; JTextField textHeight = null; JTextField textDepth = null; // TODO set width and height and depth of maze with gui public MazeSettings(MazeParams params) { super(); this.params = params; createSettingsGui(); } void createSettingsGui() { if ( params != null ) { JButton buttonCreate = new JButton(labels.getString("create")); buttonCreate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { recreateModel(); } }); add(buttonCreate); JButton buttonReset = new JButton("reset");//labels.getString("reset")); buttonReset.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { resetModel(); } }); add(buttonReset); } if ( params != null ) { JLabel widthLabel = new JLabel(labels.getString("width")); textWidth = new JTextField("0" + params.getWidth()); add(widthLabel); add(textWidth); JLabel heightLabel = new JLabel(labels.getString("height")); textHeight = new JTextField("0" + params.getHeight()); add(heightLabel); add(textHeight); JLabel depthLabel = new JLabel(labels.getString("depth")); textDepth = new JTextField("0" + params.getMaxDepth()); add(depthLabel); add(textDepth); } } public MazeParams getParams() { return new MazeParamsFixed(params.getSaveDir(), Integer.parseInt(textWidth.getText()), Integer.parseInt(textHeight.getText()), Integer.parseInt(textDepth.getText())); } } private static class MazeParamsFixed implements MazeParams { int width; int height; int maxdepth; File labdir; String name; public MazeParamsFixed() { } public MazeParamsFixed(MazeParams params) { setParams(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth()); } public void setParams(File saveDir, int W, int H, int MD) { labdir = saveDir; width=W; height=H; maxdepth=MD; } public MazeParamsFixed(File saveDir, int W, int H, int MD) { name = null; setParams(saveDir,W,H,MD); } public int getWidth() { return width; } public int getHeight() { return height; } public int getMaxDepth() { return maxdepth; } public void setName(String n) { name = n; } public String getName() { if (name == null) { name = "lab" + width + "x" + height; } return name; } public File getSaveDir() { return labdir; } } private class MazeControler extends JPanel { /** * */ private static final long serialVersionUID = 1L; private MazeSettings settings = null; private JPanel resizecontrol = null; public MazeControler(MazeParams params) { super(new BorderLayout()); controlPanel = new JPanel(new BorderLayout()); settings = new MazeSettings(params); JButton button = new JButton(labels.getString("resolve")); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // System.out.println("Resolving"); resolve(); } }); @SuppressWarnings("serial") Action goNorth = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("go North"); goNorth(); } }; JButton north = addDirection(this, labels.getString("north"), "UP", goNorth); @SuppressWarnings("serial") Action goEast = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("go East"); goEast(); } }; JButton east = addDirection(this, labels.getString("east"), "RIGHT", goEast); @SuppressWarnings("serial") Action goWest = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("go West"); goWest(); } }; JButton west = addDirection(this, labels.getString("west"), "LEFT", goWest); @SuppressWarnings("serial") Action goSouth = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("go South"); goSouth(); } }; JButton south = addDirection(this, labels.getString("south"), "DOWN", goSouth); controlPanel.add(button, BorderLayout.CENTER); controlPanel.add(north, BorderLayout.NORTH); controlPanel.add(west, BorderLayout.WEST); controlPanel.add(east, BorderLayout.EAST); controlPanel.add(south, BorderLayout.SOUTH); add(controlPanel, BorderLayout.NORTH); // control display panel contains controls for display // zoom , autozoom. final JPanel controlDisplayPanel = new JPanel(new BorderLayout()); final JCheckBox showAll = new JCheckBox("show all"); showAll.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { maze.setShowAll( showAll.isSelected()); } }); final JSlider slider = new JSlider(2, 40); slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { setWallSize(slider.getValue()); } }); final JCheckBox autoSlide = new JCheckBox("autoslide"); autoSlide.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { setAutoSize( autoSlide.isSelected()); } }); final JTextField saveName = new JTextField("newlaby "); final JButton savePngButton = new JButton(labels.getString("save") +" png"); Action savePngAction = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("save png"); savePng(); } }; savePngButton.addActionListener(savePngAction); final JButton saveSvgButton = new JButton(labels.getString("save") +" svg"); Action saveSvgAction = new AbstractAction() { public void actionPerformed(ActionEvent evt) { writeSentence("save png"); saveSvg(); } }; saveSvgButton.addActionListener(saveSvgAction); final JButton saveButton = new JButton(labels.getString("save") +" raw"); Action saveAction = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("save"); MazeParamsFixed p = (MazeParamsFixed) params; p.setName(saveName.getText()); save(p,model); } }; saveButton.addActionListener(saveAction); final JButton saveImcButton = new JButton(labels.getString("save") +" imc"); Action saveImcAction = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("save imc"); /* MazeParamsFixed p = (MazeParamsFixed) params; p.setName(saveName.getText()); save(p,model); */ saveImc(); } }; saveImcButton.addActionListener(saveImcAction); final JButton quitButton = new JButton(labels.getString("quit")); Action quitAction = new AbstractAction() { public void actionPerformed(ActionEvent evt) { // System.out.println("quit"); System.exit(0); } }; quitButton.addActionListener(quitAction); resizecontrol = new JPanel(new FlowLayout()); resizecontrol.add(showAll); resizecontrol.add(slider); resizecontrol.add(autoSlide); // todo dedicate a panel for save JPanel savePanel = resizecontrol; savePanel.add(saveName); savePanel.add(saveSvgButton); savePanel.add(savePngButton); savePanel.add(saveButton); savePanel.add(saveImcButton); resizecontrol.add(quitButton); add(controlDisplayPanel, BorderLayout.SOUTH); add(resizecontrol,BorderLayout.WEST); add(settings,BorderLayout.EAST); } private JPanel getMoveControl() { return this; } private JPanel getResizeControl() { return resizecontrol; } private JPanel getGenerationControl() { return settings; } public MazeSettings getSettings() { return settings; } } private JButton addDirection(final JPanel panel, final String direction, String key, Action goAction) { String actionName = "go" + direction; JButton button = new JButton(direction); button.addActionListener(goAction); KeyStroke keystroke = KeyStroke.getKeyStroke(key); // attach keys to maze maze.getInputMap().put(keystroke, actionName); maze.getActionMap().put(actionName, goAction); return button; } private static class MazeCellParameters { double width = 10; // width of one cell double height = 10; // height of one cell int offsetX = 5; // x offset of upper corner left int offsetY = 5; // y offset of upper corner left int mapWidth = 0; int mapHeight = 0; public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y) { double w = ( W - x )/ mapw; double h = ( H - y )/ maph; mapWidth = mapw; mapHeight = maph; if (w < 5) w = 5; if (h < 5) h = 5; setCellSize(w,h); offsetX = x; offsetY = y; } public void resetMazeWidthHeight(int mapw, int maph) { mapWidth = mapw; mapHeight = maph; } public void adaptTo(double W, double H) { double w = ( W - offsetX ) / mapWidth; double h = ( H - offsetY ) / mapHeight; mapWidth = mapWidth; mapHeight = mapHeight; if (w < 5) w = 5; if (h < 5) h = 5; setCellSize(w,h); } public void setCellSize(double w, double h) { width = w; height = h; } public double getWidth() { return width; } public double getHeight() { return height; } public int getOffsetX() { return offsetX; } public int getOffsetY() { return offsetY; } public Dimension getDimension() { return new Dimension(offsetX + (int) (mapWidth * width), offsetY + (int) (mapHeight * height)); } public void drawWalls(Graphics g, int pX, int pY, short walls) { int x = offsetX + (int) (pX * width); int y = offsetY + (int) (pY * height); if ( (pY == 0) && ((walls & Brick.UP) == Brick.UP)) g.drawLine(x, y, x + (int) width, y); if ((walls & Brick.DOWN) == Brick.DOWN) g.drawLine(x, y + (int) height, x + (int) width, y + (int) height); if ((walls & Brick.RIGHT) == Brick.RIGHT) g.drawLine(x + (int) width, y, x + (int) width, y + (int) height); if ( (pX == 0 ) && ((walls & Brick.LEFT) == Brick.LEFT)) g.drawLine(x, y, x, y + (int) height); } public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY) { if ( dp != null ) { Position dot = dp.getPosition(); if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) { int x = offsetX + (int) (dot.getX() * width); int y = offsetY + (int) (dot.getY() * height); short path = dp.getDirection(); int xm = x+ (int) (width / 2); int ym = y+ (int) (height / 2); if ( (path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) { if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE ) { g.drawLine(xm, ym, x + (int) width, ym); g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym); } // LEFT /_ if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE ) { g.drawLine(x, ym, xm, ym); g.drawLine(x, ym, xm, ym - (int) (height / 4)); } } if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) { if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE ) { g.drawLine(xm, ym, xm , y + (int) height); g.drawLine(xm - (int) (width / 4), ym , xm, y + (int) height); } // UP |\ if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE ) { g.drawLine(xm, ym, xm , y); g.drawLine(xm + (int) (width /4), ym , xm , y); } } } } } public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) { double radius = (height > width) ? width : height; int a = (int) ( radius / 4 ); if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) { int x = offsetX + (int) (dot.getX() * width); int y = offsetY + (int) (dot.getY() * height); int r2 = (int) ( (radius * 3)/4 ); g.drawOval(x + 1, y + 1, r2, r2); // g.drawLine(x+a,y+a,x+width-a,y+height-a); // g.drawLine(x+a,y+height-a,x+width-a,y+a); } else { int x = offsetX + (int) (pX * width); int y = offsetY + (int) (pY * height); g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1); } } } private static class MazeComponent extends JComponent implements MazeCreationListener, MazeResolutionListener, MouseMotionListener { private static final long serialVersionUID = 3163272907991176390L; // WallsProvider map; LabyModel map; final MazeCellParameters cp; Position current = null; LinkedList solvedPath = null; LinkedList drawingPath = null; final Object lockChange = new Object(); // current postion of human resolving int sX = 0; int sY = 0; // goal exit int gX = -1; int gY = -1; // not set by default for debug, will show any path boolean showAll = false; // for a given (x,y) pixel return cell position. Position getPosition(int x, int y) { int pX = (int) ((double) (x - cp.getOffsetX()) / cp.getWidth()); int pY = (int) ((double) (y - cp.getOffsetY()) / cp.getHeight()); return new Position(pX,pY); } @Override public void mouseDragged(MouseEvent e) { // should find the cell ... DirectionPosition last = null; short path = 0; Position newPosition = getPosition(e.getX(),e.getY()); if (drawingPath == null ) { drawingPath = new LinkedList<>(); last = new DirectionPosition((short) 0,newPosition); System.out.println("Mouse dragged Cell " + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK); drawingPath.addLast(last); } else { // setShowAll(true); DirectionPosition first = drawingPath.getLast(); last = first; // construct as many move form last to new position as needed. while ( ! last.getPosition().equals(newPosition)) { path=LabyModel.getDirection(last.getPosition(),newPosition); last.setDirection(path); // button 1 : add direction; button 2 : replace with direction. if ( ( e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK ) != 0 ) { map.addDirection(last.getPosition().getX(),last.getPosition().getY(),path); } else { map.setDirection(last.getPosition().getX(),last.getPosition().getY(),path); } last = last.moveToAdjacentDirection(); drawingPath.addLast(last); } System.out.println("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK); } changed(null,null,map); } @Override public void mouseMoved(MouseEvent e) { // System.out.println("Mouse moved (" + e.getX() + ',' + e.getY() + ')'); Position newPosition = getPosition(e.getX(),e.getY()); if ( ( newPosition.getX() >= 0 ) && ( newPosition.getY() >= 0 ) ) { requestFocus(); } } public void setShowAll(boolean showall ) { this.showAll = showall; System.out.println(showAll ? "show all" : "X"); } void checkExit() { if ((sX == gX) && (sY == gY)) { System.out.println("Exit found by human !"); } } void goNorth() { resetResolution(); if ((map.getWalls(sX, sY) & Brick.UP) == 0) { sY = sY - 1; // should redraw ... invalidate(); repaint(); checkExit(); } } void goSouth() { resetResolution(); if ((map.getWalls(sX, sY) & Brick.DOWN) == 0) { sY = sY + 1; // should redraw ... invalidate(); repaint(); checkExit(); } } void goEast() { resetResolution(); if ((map.getWalls(sX, sY) & Brick.RIGHT) == 0) { sX = sX + 1; // should redraw ... invalidate(); repaint(); checkExit(); } } void goWest() { resetResolution(); if ((map.getWalls(sX, sY) & Brick.LEFT) == 0) { sX = sX - 1; // should redraw ... invalidate(); repaint(); checkExit(); } } /** width, height of one cell, offsetX, offsetY of upper left corner **/ // public MazeComponent(WallsProvider map, MazeCellParameters cp) public MazeComponent(LabyModel map, MazeCellParameters cp) { super(); this.cp = cp; this.map = map; setPreferredSize(cp.getDimension()); gX = map.getWidth() - 1; gY = map.getHeight() - 1; } // public void resetWallsProvider(WallsProvider map) public void resetWallsProvider(LabyModel map) { this.map = map; solvedPath=null; // could be kept drawingPath=null; sX=0; sY=0; cp.resetMazeWidthHeight(map.getWidth(),map.getHeight()); setPreferredSize(cp.getDimension()); } public void setWallSize(int size) { cp.setCellSize((double) size,(double) size); // should redraw ... invalidate(); repaint(); } public int getAutoSize() { Rectangle r = getBounds(); cp.adaptTo((int) r.getWidth(),(int) r.getHeight()); // should redraw ... invalidate(); repaint(); return 50; } public void changed(Position cl, Position cr, WallsProvider map) { // should redraw ... invalidate(); repaint(); Object waiter = new Object(); synchronized (waiter) { try { waiter.wait(10); } catch (InterruptedException e) { System.err.println("Interrupted !"); } } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int x = 0; int y = 0; short walls = 0; short path = 0; // try to display only visible part... // should compute pX, pY, mX, mY based on clip... // Shape s=g.getClip(); Rectangle r = g.getClipBounds(); int mX = (int) ((double) r.getWidth() / cp.getWidth()); int mY = (int) ((double) r.getHeight() / cp.getHeight()); int pX = (int) ((double) (r.getX() - cp.getOffsetX()) / cp.getWidth()); int pY = (int) ((double) (r.getY() - cp.getOffsetY()) / cp.getHeight()); if (pX < 0) pX = 0; if (pY < 0) pY = 0; if (pX >= map.getWidth()) return; if (pY >= map.getHeight()) return; mX = mX + pX; mY = mY + pY; if (mX > map.getWidth()) { mX = map.getWidth(); } if (mY > map.getHeight()) { mY = map.getHeight(); } if ((sX == gX) && (sY == gY)) { g.setColor(Color.red); } else { g.setColor(Color.green); cp.drawDot(g, new Position(gX, gY), pX, pY, mX, mY); g.setColor(Color.blue); } cp.drawDot(g, new Position(sX, sY), pX, pY, mX, mY); synchronized (lockChange) { g.setColor(Color.red); if (current != null) { cp.drawDot(g, current, pX, pY, mX, mY); } if (solvedPath != null) { for (DirectionPosition resolved : solvedPath) { // cp.drawDot(g, resolved.getPosition(), pX, pY, mX, mY); cp.drawPath(g,resolved, pX, pY, mX, mY); } } } int aX = pX; int aY = pY; g.setColor(Color.black); // draw all walls within clip bounds horiz first then lines for (; pY < mY; pY++) { for (pX = 0; pX < mX; pX++) { walls = map.getWalls(pX, pY); cp.drawWalls(g, pX, pY, walls); } } if (this.showAll) { System.out.println("*"); pX = aX; pY = aY; // draw all path within clip bounds horiz first then lines for (; pY < mY; pY++) { for (pX = 0; pX < mX; pX++) { path = map.getPath(pX,pY); if ( ( path & LabyModel.SOLVED ) == LabyModel.SOLVED ) { g.setColor(Color.green); } else { g.setColor(Color.blue); } if ( path != 0 ) { DirectionPosition dp = new DirectionPosition(path,new Position(pX,pY)); cp.drawPath(g,dp,pX,pY,pX+1,pY+1); } } } } } public boolean notifySearch(DirectionPosition pPosition) { synchronized (lockChange) { current = pPosition.getPosition(); } // should redraw ... invalidate(); repaint(); return true; } public void notifySearchError(String error) { System.err.println(error); } public void notifyCompletion(LinkedList solvedPath) { LinkedList newPath = new LinkedList<>(solvedPath); System.out.println("resolution completed"); synchronized (lockChange) { this.solvedPath = newPath; } // should redraw ... invalidate(); repaint(); } public void resetResolution() { solvedPath = null; } } private static void setupDisplay(LabyModel model, int W, int H, MazeParams params) { Display display = new Display(model, W,H,params); } public static void save(MazeParamsFixed params,LabyModel model) { File outfile = new File(params.getSaveDir(), params.getName() + ".raw"); if (!outfile.exists()) { System.out.println("Saving to " + outfile + " ..."); try { FileOutputStream out = new FileOutputStream(outfile); model.streamOut("raw", out); out.flush(); out.close(); System.out.println("... Done."); } catch (IOException io) { io.printStackTrace(System.err); } } else { System.out.println("" + outfile + " already exists"); } outfile = new File(params.getSaveDir(), params.getName() + ".stl"); if (!outfile.exists()) { System.out.println("Saving to " + outfile + " ..."); try { FileOutputStream out = new FileOutputStream(outfile); Wall3d.streamWallsOut(params.getName(), (WallsProvider) model, out); out.flush(); out.close(); System.out.println("... Done."); } catch (IOException io) { io.printStackTrace(System.err); } } else { System.out.println("" + outfile + " already exists"); } } public static void main(String pArgs[]) { LabyModel model = null; int W = 600; int H = 400; System.out.println("Default Locale " + Locale.getDefault()); if ( (pArgs.length > 0) && (pArgs[0].length() > 0)) { try { model = new LabyModel("raw", new FileInputStream(pArgs[0])); } catch (IOException io) { io.printStackTrace(System.err); System.exit(1); } setupDisplay(model, W,H,null); } else { MazeParamsFixed params = new MazeParamsFixed(new File("lab"),20,20,12); model = new LabyModel(params, new java.util.Random()); setupDisplay(model,W,H,params); /* model.generateWithEntry(0, 0); model.addEntryOrExit(-1, 0); model.addEntryOrExit(params.getWidth(), params.getHeight() - 1); System.out.println("Generation completed"); */ /* */ } } }