first .osm format import
- import osm convert it to Drawing and use it as resolved path. - Not ready , first test over lab/valbonne_oct_2020.osm
This commit is contained in:
367
java/org/artisanlogiciel/games/maze/gui/MazeComponent.java
Normal file
367
java/org/artisanlogiciel/games/maze/gui/MazeComponent.java
Normal file
@@ -0,0 +1,367 @@
|
||||
package org.artisanlogiciel.games.maze.gui;
|
||||
|
||||
import org.artisanlogiciel.games.maze.*;
|
||||
import org.artisanlogiciel.games.maze.solve.DirectionPosition;
|
||||
import org.artisanlogiciel.games.maze.solve.MazeResolutionListener;
|
||||
import org.artisanlogiciel.graphics.Drawing;
|
||||
import org.artisanlogiciel.graphics.DrawingLine;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public 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<DirectionPosition> solvedPath = null;
|
||||
LinkedList<DirectionPosition> 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;
|
||||
|
||||
Date lastDrag = null;
|
||||
// FIXME HARCDODED delay after which a draging to draw a continous line is ended, a new line will then start.
|
||||
long dragTimeout = 200;
|
||||
|
||||
// not set by default for debug, will show any path
|
||||
boolean showAll = false;
|
||||
|
||||
StatusListener statusListener;
|
||||
|
||||
// for a given (x,y) pixel return cell position.
|
||||
// if rightmost position of view not (0,0) this is not working.
|
||||
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) {
|
||||
boolean add = ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0);
|
||||
Position newPosition = getPosition(e.getX(), e.getY());
|
||||
Date now = new Date(System.currentTimeMillis());
|
||||
if (lastDrag == null) {
|
||||
resetDrawingPath();
|
||||
} else {
|
||||
if (now.getTime() - lastDrag.getTime() > dragTimeout) {
|
||||
resetDrawingPath();
|
||||
statusListener.addStatus("move timeout");
|
||||
}
|
||||
}
|
||||
lastDrag = now;
|
||||
addPosition(newPosition, add);
|
||||
changed(null, null, map);
|
||||
}
|
||||
|
||||
public void resetDrawingPath() {
|
||||
drawingPath = null;
|
||||
}
|
||||
|
||||
public void addDrawing(Drawing drawing, boolean add) {
|
||||
for (DrawingLine line : drawing.getInternLines()) {
|
||||
addDrawingLine(line, add);
|
||||
}
|
||||
changed(null, null, map);
|
||||
}
|
||||
|
||||
public void addDrawingLine(DrawingLine line, boolean add) {
|
||||
resetDrawingPath();
|
||||
ArrayList<Point> points = line.getPoints();
|
||||
for (Point p : points) {
|
||||
addPosition(new Position(p.x, p.y), add);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPosition(Position newPosition, boolean add) {
|
||||
// should find the cell ...
|
||||
DirectionPosition last = null;
|
||||
short path = 0;
|
||||
if (drawingPath == null) {
|
||||
drawingPath = new LinkedList<>();
|
||||
last = new DirectionPosition((short) 0, newPosition);
|
||||
statusListener.addStatus("Mouse dragged Cell " + newPosition + " Button " + add);
|
||||
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 : rep lace with direction.
|
||||
if (add) {
|
||||
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);
|
||||
}
|
||||
statusListener.addStatus("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + add);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// addStatus("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;
|
||||
statusListener.addStatus(showAll ? "show all" : "X");
|
||||
}
|
||||
|
||||
void checkExit() {
|
||||
if ((sX == gX) && (sY == gY)) {
|
||||
statusListener.addStatus("Exit found by human !");
|
||||
}
|
||||
}
|
||||
|
||||
private void proceed() {
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
checkExit();
|
||||
}
|
||||
|
||||
void goNorth() {
|
||||
resetResolution();
|
||||
if (map.canMoveInDirection(sX, sY, Brick.UP)) {
|
||||
sY = sY - 1;
|
||||
proceed();
|
||||
}
|
||||
}
|
||||
|
||||
void goSouth() {
|
||||
resetResolution();
|
||||
if (map.canMoveInDirection(sX, sY, Brick.DOWN)) {
|
||||
sY = sY + 1;
|
||||
proceed();
|
||||
}
|
||||
}
|
||||
|
||||
void goEast() {
|
||||
resetResolution();
|
||||
if (map.canMoveInDirection(sX, sY, Brick.RIGHT)) {
|
||||
sX = sX + 1;
|
||||
proceed();
|
||||
}
|
||||
}
|
||||
|
||||
void goWest() {
|
||||
resetResolution();
|
||||
if (map.canMoveInDirection(sX, sY, Brick.LEFT)) {
|
||||
sX = sX - 1;
|
||||
proceed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* width, height of one cell,
|
||||
* offsetX, offsetY of upper left corner
|
||||
**/
|
||||
// public MazeComponent(WallsProvider map, MazeCellParameters cp)
|
||||
public MazeComponent(LabyModel map, MazeCellParameters cp, StatusListener statusListener) {
|
||||
super();
|
||||
this.cp = cp;
|
||||
this.map = map;
|
||||
setPreferredSize(cp.getDimension());
|
||||
gX = map.getWidth() - 1;
|
||||
gY = map.getHeight() - 1;
|
||||
this.statusListener = statusListener;
|
||||
}
|
||||
|
||||
// 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();
|
||||
/* what was this ?
|
||||
|
||||
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) {
|
||||
statusListener.addStatus("*");
|
||||
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<DirectionPosition> solvedPath) {
|
||||
LinkedList<DirectionPosition> newPath = new LinkedList<>(solvedPath);
|
||||
statusListener.addStatus("resolution completed");
|
||||
synchronized (lockChange) {
|
||||
this.solvedPath = newPath;
|
||||
}
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void resetResolution() {
|
||||
solvedPath = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user