Terrain.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. package gui.simulator;
  2. import gui.simulator.Images.ImageType;
  3. import gui.simulator.SimulatorPane.Objects;
  4. import java.awt.BasicStroke;
  5. import java.awt.Color;
  6. import java.awt.Cursor;
  7. import java.awt.Dimension;
  8. import java.awt.Graphics;
  9. import java.awt.Graphics2D;
  10. import java.awt.Point;
  11. import java.awt.Rectangle;
  12. import java.awt.RenderingHints;
  13. import java.awt.Shape;
  14. import java.awt.TexturePaint;
  15. import java.awt.Toolkit;
  16. import java.awt.event.MouseAdapter;
  17. import java.awt.event.MouseEvent;
  18. import java.awt.event.MouseMotionAdapter;
  19. import java.awt.event.MouseWheelEvent;
  20. import java.awt.event.MouseWheelListener;
  21. import java.awt.geom.AffineTransform;
  22. import java.awt.geom.Area;
  23. import java.awt.geom.NoninvertibleTransformException;
  24. import java.awt.geom.Point2D;
  25. import java.awt.geom.Rectangle2D;
  26. import java.util.ArrayList;
  27. import java.util.LinkedList;
  28. import java.util.List;
  29. import javax.swing.JDialog;
  30. import javax.swing.JPanel;
  31. import javax.swing.SwingUtilities;
  32. import com.sun.xml.internal.stream.Entity;
  33. import agenda.Agenda;
  34. public class Terrain extends JPanel {
  35. private List<DrawEngine> entities;
  36. private Point2D oldPosition;
  37. private double oldRotation, oldScale;
  38. private DrawEngine dragObject, selectedObject;
  39. private ImageType background;
  40. private Sidebar sidebar;
  41. private Topbar topbar;
  42. private int festivalheight, festivalwidth;
  43. private int sideBarWidth = 200;
  44. private int pathgenerate, maxvisitors;
  45. private WalkingPath currentpath;
  46. Point2D cameraPoint = new Point2D.Double(festivalwidth/2,festivalheight/2);
  47. float cameraScale = 1;
  48. private boolean grid;
  49. private ArrayList<Visitor> visitors;
  50. private WalkingPathArrayList paths;
  51. Cursor rotate, pathpoint;
  52. Point2D lastClickPosition;
  53. Point lastMousePosition;
  54. Point2D lastMovedMousePosition;
  55. TexturePaint p;
  56. private Agenda agenda;
  57. public Terrain(int length, int width, SimulatorPane.Terrains terrain, Agenda agenda, SimulatorPane simulator){
  58. //get values
  59. maxvisitors = 30;
  60. setFestivalHeight(length);
  61. setFestivalWidth(width);
  62. visitors = new ArrayList<Visitor>();
  63. paths = new WalkingPathArrayList();
  64. createCustomCursors();
  65. //initialize sidebar & topbar
  66. sidebar = new Sidebar(sideBarWidth, 3000, this);
  67. topbar = new Topbar(this, simulator);
  68. addMouseListener(topbar);
  69. //set terrainbackground
  70. switch(terrain){
  71. case BEACH:
  72. background = Images.ImageType.Sand;
  73. break;
  74. case GRASS:
  75. background = Images.ImageType.Grass;
  76. break;
  77. case URBAN:
  78. background = Images.ImageType.Street;
  79. break;
  80. }
  81. p = new TexturePaint(Images.getImage(background), new Rectangle2D.Double(0, 0, 200, 200));
  82. this.entities = new LinkedList();
  83. this.initEntities();
  84. this.listeners();
  85. this.agenda = agenda;
  86. }
  87. private void listeners(){
  88. addMouseListener(new MouseAdapter() {
  89. @Override
  90. public void mousePressed(MouseEvent e) {
  91. Point2D clickPoint = getClickPoint(e.getPoint());
  92. lastClickPosition = clickPoint;
  93. lastMousePosition = e.getPoint();
  94. //if selected in sidebar
  95. sidebar.getFacility(e);
  96. //else selected in terrain
  97. if(e.getX() > sideBarWidth){
  98. for(DrawEngine drawObject: entities){
  99. if(drawObject.contains(clickPoint)){
  100. if(pathgenerate == 1){
  101. currentpath.addPoint(new Point((int)drawObject.getCenter().getX(), (int)drawObject.getCenter().getY()));
  102. currentpath.setObject1(drawObject);
  103. pathgenerate = 2;
  104. return;
  105. }else if(pathgenerate > 1){
  106. currentpath.addPoint(new Point((int)drawObject.getCenter().getX(), (int)drawObject.getCenter().getY()));
  107. currentpath.setObject2(drawObject);
  108. paths.add(currentpath);
  109. pathgenerate = 0;
  110. return;
  111. }else{
  112. setCursor(new Cursor(Cursor.MOVE_CURSOR));
  113. dragObject = drawObject;
  114. selectedObject = dragObject;
  115. oldPosition = new Point2D.Double(selectedObject.getX(), selectedObject.getY());
  116. oldRotation = selectedObject.getScale();
  117. oldScale = selectedObject.getScale();
  118. //double click
  119. if(e.getClickCount() == 2){
  120. //TODO open dialog
  121. JDialog dialog = new StageDialog(drawObject, agenda);
  122. //position
  123. Toolkit toolkit = Toolkit.getDefaultToolkit();
  124. Dimension screenSize = toolkit.getScreenSize();
  125. int x = (int) ((screenSize.getWidth() - dialog.getWidth()) / 2);
  126. int y = (int) ((screenSize.getHeight() - dialog.getHeight()) / 2);
  127. Point center = new Point(x, y);
  128. dialog.setLocation(center);
  129. dialog.pack();
  130. dialog.setVisible(true);
  131. }
  132. return;
  133. }
  134. }
  135. }
  136. if(pathgenerate == 1){
  137. if(SwingUtilities.isRightMouseButton(e)){
  138. pathgenerate = 0;
  139. }
  140. }else if(pathgenerate > 1){
  141. if(SwingUtilities.isRightMouseButton(e)){
  142. currentpath.removeLastPoint();
  143. if(currentpath.getPath().size() == 0){
  144. pathgenerate = 0;
  145. }
  146. }else{
  147. currentpath.addPoint(new Point((int)getClickPoint(e.getPoint()).getX(), (int)getClickPoint(e.getPoint()).getY()));
  148. }
  149. }
  150. }
  151. repaint();
  152. }
  153. @Override
  154. public void mouseReleased(MouseEvent e) {
  155. if(selectedObject != null){
  156. for(DrawEngine drawObject: entities){
  157. if(drawObject == selectedObject){
  158. continue;
  159. }
  160. if(intersection(selectedObject, drawObject)){
  161. //move back
  162. selectedObject.setX(oldPosition.getX());
  163. selectedObject.setY(oldPosition.getY());
  164. selectedObject.setRotation(oldRotation);
  165. selectedObject.setScale(oldScale);
  166. }
  167. }
  168. for(WalkingPath p:paths){
  169. p.reCalculate();
  170. }
  171. }
  172. setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  173. selectedObject = null;
  174. dragObject = null;
  175. repaint();
  176. }
  177. });
  178. addMouseMotionListener(new MouseMotionAdapter() {
  179. public void mouseMoved(MouseEvent e){
  180. lastMovedMousePosition = getClickPoint(e.getPoint());
  181. if(e.getX() < sidebar.getSideBarWidth()){
  182. setCursor(new Cursor(Cursor.HAND_CURSOR));
  183. }else if(pathgenerate >0){
  184. setCursor(pathpoint);
  185. }else if(topbar.containsMouse(e.getPoint())){
  186. setCursor(new Cursor(Cursor.HAND_CURSOR));
  187. }else{
  188. for(DrawEngine drawObject: entities){
  189. if(drawObject.contains(lastMovedMousePosition)){
  190. setCursor(new Cursor(Cursor.HAND_CURSOR));
  191. return;
  192. }
  193. }
  194. setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  195. }
  196. }
  197. @Override
  198. public void mouseDragged(MouseEvent e) {
  199. Point2D clickPoint = getClickPoint(e.getPoint());
  200. if(dragObject != null){
  201. if(SwingUtilities.isLeftMouseButton(e) && dragObject instanceof AccessPoint){
  202. dragObject.setX(-25);
  203. dragObject.setRotation(90);
  204. if(dragObject.getY()<80){
  205. dragObject.setY(80);
  206. } else if(dragObject.getY()>getFestivalHeight()-150){
  207. dragObject.setY(getFestivalHeight()-150);
  208. } else {
  209. dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY()));
  210. }
  211. }else if(SwingUtilities.isLeftMouseButton(e) && dragObject instanceof ExitPoint){
  212. dragObject.setX(getFestivalWidth()-200);
  213. dragObject.setRotation(90);
  214. if(dragObject.getY()<80){
  215. dragObject.setY(80);
  216. } else if(dragObject.getY()>getFestivalHeight()-150){
  217. dragObject.setY(getFestivalHeight()-150);
  218. } else {
  219. dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY()));
  220. }
  221. }else if(SwingUtilities.isLeftMouseButton(e)){
  222. setCursor(new Cursor(Cursor.MOVE_CURSOR));
  223. dragObject.setX(dragObject.getX() - (lastClickPosition.getX() - clickPoint.getX()));
  224. dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY()));
  225. }else if(SwingUtilities.isRightMouseButton(e)){
  226. setCursor(rotate);
  227. dragObject.setRotation(dragObject.getRotation() + (lastClickPosition.getX() - clickPoint.getX() + lastClickPosition.getY() - clickPoint.getY()));
  228. }
  229. for(WalkingPath p:paths){
  230. p.reCalculate();
  231. }
  232. }
  233. else
  234. {
  235. setCursor(new Cursor(Cursor.MOVE_CURSOR));
  236. cameraPoint = new Point2D.Double(
  237. cameraPoint.getX() + (lastMousePosition.getX() - e.getX()),
  238. cameraPoint.getY() + (lastMousePosition.getY() - e.getY())
  239. );
  240. }
  241. repaint();
  242. lastMousePosition = e.getPoint();
  243. lastClickPosition = clickPoint;
  244. }
  245. });
  246. addMouseWheelListener(new MouseWheelListener() {
  247. @Override
  248. public void mouseWheelMoved(MouseWheelEvent e) {
  249. Point2D clickPoint = getClickPoint(e.getPoint());
  250. for(DrawEngine object: entities){
  251. //if object selected, scale object
  252. if(object.contains(clickPoint)){
  253. double oldscale = object.getScale();
  254. if(oldscale < 0.3){
  255. if((e.getPreciseWheelRotation()/10.0) > 0){
  256. object.setScale(object.getScale() * 1 + (e.getPreciseWheelRotation()/10.0));
  257. }
  258. } else {
  259. object.setScale(object.getScale() * 1 + (e.getPreciseWheelRotation()/10.0));
  260. }
  261. //intersect
  262. for(DrawEngine draw: entities){
  263. if(draw != object){
  264. if(intersection(draw, object)){
  265. object.setScale(oldscale);
  266. }
  267. }
  268. }
  269. repaint();
  270. return;
  271. }
  272. }
  273. //scale camera
  274. cameraScale *= 1 - (e.getPreciseWheelRotation()/10.0);
  275. repaint();
  276. }
  277. });
  278. }
  279. /*
  280. * Add facilities on initializing
  281. */
  282. private void initEntities(){
  283. //this.entities.add(new Stage(300, 10, 0.5, 10));
  284. //this.entities.add(new Stage(400, 40, 2, 10));
  285. }
  286. public void paintComponent(Graphics g) {
  287. super.paintComponent(g);
  288. Graphics2D g2 = (Graphics2D) g;
  289. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
  290. topbar.draw(g2, getWidth());
  291. sidebar.draw(g2);
  292. //draw simulation field
  293. Area a1 = new Area(new Rectangle2D.Double(sideBarWidth, 0, getWidth()-sideBarWidth, getHeight()));
  294. Area a2 = new Area(topbar.getBackground());
  295. a2.transform(new AffineTransform().getTranslateInstance(1, 1.2));
  296. a1.subtract(a2);
  297. g2.setClip(a1);
  298. AffineTransform oldTransform = g2.getTransform();
  299. g2.translate(sideBarWidth,0);
  300. g2.setTransform(getCamera());
  301. g2.setPaint(p);
  302. g2.fill(new Rectangle2D.Double(0,0,festivalwidth,festivalheight));
  303. if(grid){
  304. g2.setColor(new Color(160,160,160,120));
  305. g2.setStroke(new BasicStroke(1));
  306. for(int i = 0; i < (getFestivalWidth()/10)+1; i++){
  307. g2.drawLine(i*10, 0, i*10, getFestivalHeight());
  308. };
  309. for(int i = 0; i < (getFestivalHeight()/10)+1; i++){
  310. g2.drawLine(0, i*10, getFestivalWidth(), i*10);
  311. };
  312. }
  313. if(pathgenerate > 1){
  314. currentpath.paint(g2);
  315. g2.drawLine((int)currentpath.get(currentpath.getPath().size()-1).getX(),(int)currentpath.get(currentpath.getPath().size()-1).getY(), (int)lastMovedMousePosition.getX(), (int)lastMovedMousePosition.getY());
  316. }
  317. for(WalkingPath path:paths){
  318. path.paint(g2);
  319. }
  320. for(Visitor v:visitors){
  321. v.paint(g2);
  322. }
  323. g2.setStroke(new BasicStroke(4));
  324. for(DrawEngine drawObject: entities){
  325. drawObject.draw(g2);
  326. if(pathgenerate > 0){
  327. g2.setColor(new Color(180,100,100,120));
  328. g2.fill(new Rectangle((int)drawObject.getCenter().getX()-20, (int)drawObject.getCenter().getY()-20, 40,40));
  329. }
  330. }
  331. //draw collide boxes
  332. if(this.selectedObject != null){
  333. Shape shape = this.selectedObject.getRect();
  334. g2.setColor(Color.RED);
  335. g2.draw(this.selectedObject.getAffineTransform().createTransformedShape(shape));
  336. boolean collide = false;
  337. for(DrawEngine drawEngine : entities){
  338. if(!drawEngine.equals(this.selectedObject)){
  339. if(intersection(this.selectedObject, drawEngine)){
  340. collide = true;
  341. }
  342. }
  343. }
  344. if(collide){
  345. g2.setColor(new Color(254, 0, 0, 128));
  346. }else{
  347. g2.setColor(new Color(0, 254, 0, 128));
  348. }
  349. g2.fill(this.selectedObject.getAffineTransform().createTransformedShape(this.selectedObject.getRect()));
  350. g2.setTransform(oldTransform);
  351. }
  352. g2.setClip(null);
  353. }
  354. private Rectangle drawDragRectangle(DrawEngine shape){
  355. Rectangle rectangle = null;
  356. rectangle = new Rectangle((int) (shape.getX() - shape.getDistanceToOtherObjects()), (int) (shape.getY() - shape.getDistanceToOtherObjects()), (int) (shape.getWidth() * shape.getScale() + (2 * shape.getDistanceToOtherObjects())), (int) (shape.getHeight() * shape.getScale() + (2 * shape.getDistanceToOtherObjects())));
  357. return rectangle;
  358. }
  359. private boolean intersection(DrawEngine d1, DrawEngine d2){
  360. Area area = new Area(d1.getAffineTransform().createTransformedShape(d1.getRect()));
  361. Area area2 = new Area(d2.getAffineTransform().createTransformedShape(d2.getRect()));
  362. area.intersect(area2);
  363. return !area.isEmpty();
  364. }
  365. public Point2D getClickPoint(Point point) {
  366. try {
  367. return getCamera().inverseTransform(point, null);
  368. } catch (NoninvertibleTransformException e1) {
  369. e1.printStackTrace();
  370. }
  371. return null;
  372. }
  373. private AffineTransform getCamera() {
  374. AffineTransform tx = new AffineTransform();
  375. //start field in top left corner, next to sidebar
  376. tx.translate(-cameraPoint.getX() + sideBarWidth, -cameraPoint.getY());
  377. //start field in middle of screen
  378. //tx.translate(-cameraPoint.getX() + getWidth()/2, -cameraPoint.getY() + getHeight()/2);
  379. tx.scale(cameraScale, cameraScale);
  380. return tx;
  381. }
  382. public void calculate(){
  383. for(Visitor v:visitors){
  384. v.update(visitors, entities,paths);
  385. }
  386. if(Math.random()*500 <200){
  387. Point2D startpoint = null;
  388. for(DrawEngine e:entities){
  389. if(e.type == Objects.ENTRANCE){
  390. startpoint = e.getCenter();
  391. }
  392. }
  393. if(startpoint == null || visitors.size() >= maxvisitors) return; //No entrance found OR to many visitors, stop adding people.
  394. visitors.add(new Visitor(new Point2D.Double(-100-Math.random()*200, getFestivalHeight()-Math.random()*getFestivalHeight()), startpoint));
  395. }
  396. topbar.recalculate();
  397. }
  398. public void setFestivalHeight(int height){
  399. this.festivalheight = height;
  400. }
  401. public void setFestivalWidth(int width){
  402. this.festivalwidth = width;
  403. }
  404. public int getFestivalHeight(){
  405. return festivalheight;
  406. }
  407. public int getFestivalWidth(){
  408. return festivalwidth;
  409. }
  410. //getters and setters for sidebar
  411. public void setDragObject(DrawEngine dragObject){
  412. this.dragObject = dragObject;
  413. }
  414. public DrawEngine getDragObject(){
  415. return dragObject;
  416. }
  417. public void addEntity(DrawEngine dragObject){
  418. entities.add(dragObject);
  419. }
  420. public void createCustomCursors(){
  421. Toolkit toolkit = Toolkit.getDefaultToolkit();
  422. Images.ImageType image;
  423. image = Images.ImageType.RotateCursor;
  424. rotate = toolkit.createCustomCursor(Images.getImage(image), new Point(14,14), "Rotate");
  425. image = Images.ImageType.PathCursor;
  426. pathpoint = toolkit.createCustomCursor(Images.getImage(image), new Point(14,14), "Pathpoint");
  427. }
  428. public void toggleGrid(){
  429. grid = !grid;
  430. }
  431. public void newWalkingPath(Images.ImageType imagetype){
  432. if(pathgenerate == 0){
  433. currentpath = new WalkingPath(imagetype);
  434. pathgenerate = 1;
  435. }
  436. }
  437. public List<DrawEngine> getEntities() {
  438. return entities;
  439. }
  440. public void clearVisitors(){
  441. visitors.clear();
  442. }
  443. public void setMaxVisitors(int v){
  444. this.maxvisitors = v;
  445. }
  446. public int getMaxVisitors(){
  447. return maxvisitors;
  448. }
  449. }