ClickAndFollowQuickDef
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
 
import jp.digitalmuseum.mr.Matereal;
import jp.digitalmuseum.mr.entity.Robot;
import jp.digitalmuseum.mr.gui.*;
import jp.digitalmuseum.mr.gui.utils.VectorFieldPainter;
import jp.digitalmuseum.mr.hakoniwa.Hakoniwa;
import jp.digitalmuseum.mr.hakoniwa.HakoniwaRobotWithPen;
import jp.digitalmuseum.mr.message.Event;
import jp.digitalmuseum.mr.message.EventListener;
import jp.digitalmuseum.mr.message.ImageUpdateEvent;
import jp.digitalmuseum.mr.resource.Wheels;
import jp.digitalmuseum.mr.resource.WheelsController;
import jp.digitalmuseum.mr.task.Follow;
import jp.digitalmuseum.mr.task.Move;
import jp.digitalmuseum.mr.task.Task;
import jp.digitalmuseum.mr.task.VectorFieldTask;
import jp.digitalmuseum.utils.Location;
import jp.digitalmuseum.utils.Position;
import jp.digitalmuseum.utils.ScreenPosition;
import jp.digitalmuseum.utils.Vector2D;
 
/**
 * Click to navigate one robot. The other robot will follow him.
 * Test of assigning tasks to robots.
 *
 * @author Jun KATO
 */
public class ClickAndFollowQuickDef {
	private Hakoniwa hakoniwa;
	private VectorFieldTask follow;
	private ScreenPosition goal = null;
 
	public static void main(String[] args) {
		new ClickAndFollowQuickDef();
	}
 
	public ClickAndFollowQuickDef() {
 
		// Run hakoniwa.
		hakoniwa = new Hakoniwa();
		hakoniwa.start();
 
		final Robot followee;
		final Robot follower;
		followee = new HakoniwaRobotWithPen("followee", new Location(hakoniwa.getRealWidth()/2 - 30, hakoniwa.getRealHeight()/2, -Math.PI*3/4));
		follower = new HakoniwaRobotWithPen("follower", new Location(hakoniwa.getRealWidth()/2 + 30, hakoniwa.getRealHeight()/2, -Math.PI*3/4));
 
		follow = new VectorFieldTask() {
			public void getUniqueVectorOut(Position position, Vector2D vector) {
				Position destination = getLocationProvider().getLocation(followee).getRelativePosition(0, -70);
				vector.set(
						destination.getX()-position.getX(),
						destination.getY()-position.getY());
				vector.normalize();
				vector.mul(getMinimalNorm());
			}
		};
		follow.assign(follower);
		follow.start();
 
		// Make a window for showing captured image.
		final DrawableFrame frame = new DrawableFrame() {
			private static final long serialVersionUID = 1L;
			private transient final VectorFieldPainter vectorFieldPainter =
				new VectorFieldPainter(hakoniwa);
			private transient final Stroke stroke =
				new BasicStroke(5);
			private transient final AlphaComposite alphaComp =
				AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .3f);
			private transient final AlphaComposite alphaComp2 =
				AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .7f);
 
			@Override public void dispose() {
				super.dispose();
				Matereal.getInstance().dispose();
			}
 
			@Override
			public void paint2D(Graphics2D g) {
				final Task task = followee.getAssignedTask(WheelsController.class);
				g.setColor(Color.white);
				g.fillRect(0, 0, getFrameWidth(), getFrameHeight());
				final Composite comp = g.getComposite();
 
				// Draw vectors.
				g.setComposite(alphaComp);
				g.setColor(Color.red);
				vectorFieldPainter.paint(follow, g);
				g.setComposite(alphaComp2);
				g.setColor(Color.black);
				g.fillRect(0, 0, getFrameWidth(), 35);
 
				// Draw status.
				g.setComposite(comp);
				g.drawLine(0, 35, getFrameWidth(), 35);
				g.setColor(Color.white);
				if (goal == null) {
					g.drawString("Click to set the destination.", 10, 30);
				} else {
					if (task != null) {
						g.drawString("Status: "+task, 10, 30);
					} else {
						g.drawString("Status: Stopped", 10, 30);
					}
					Stroke s = g.getStroke();
					g.setStroke(stroke);
					g.setColor(Color.black);
					g.drawLine(
							goal.getX()-5,
							goal.getY()-5,
							goal.getX()+5,
							goal.getY()+5);
					g.drawLine(
							goal.getX()-5,
							goal.getY()+5,
							goal.getX()+5,
							goal.getY()-5);
					g.setStroke(s);
				}
				hakoniwa.drawImage(g);
			}
		};
		frame.setResizable(false);
		frame.setFrameSize(hakoniwa.getWidth(), hakoniwa.getHeight());
 
		// Bring the clicked object to the location in front of the user.
		frame.getPanel().addMouseListener(new MouseAdapter() {
			public void mouseReleased(MouseEvent e) {
				int x = e.getX(), y = e.getY();
				goal = new ScreenPosition(x, y);
 
				Task task = followee.getAssignedTask(Wheels.class);
				if (task != null) task.stop();
 
				Move move = new Move(hakoniwa.screenToReal(goal));
				if (move.assign(followee)) move.start();
			}
		});
 
		// Repaint the window every time the image is updated.
		hakoniwa.addEventListener(new EventListener() {
			public void eventOccurred(Event e) {
				if (e instanceof ImageUpdateEvent) {
					frame.repaint();
				}
			}
		});
	}
}