package uk.org.floop.epq3d; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; public class Screen extends JPanel implements ActionListener, KeyListener, MouseListener, MouseMotionListener { // __working variables__ public boolean initialised = false; public long lastTime = 0; // mouse private boolean captured = false; private final Point2D mouseRel = new Point2D(0,0); private final Cursor invisibleCursor; public ObjectCollection mainCollection; public JsonWriter json; // testing\ // private Line2d line = new Line2d( // new Point2D(200, 200), // new Point2D(1, 1), // true); // private Triangle Triangle = new Triangle( // new Point2D(200, 200), new Point2D(1, 1), new Point2D(400,200) // ,new boolean[]{false, false, false}, // null, // new Matrix(3, 3)); // private final Point3D[] points = new Point3D[]{ // new Point3D(10,10,-1), // new Point3D(-10, 10, -1), // new Point3D(-10, -10, -1), // new Point3D(10, -10, -1)}; // double ang = 0; // __config variables__ // controls the delay between each tick in ms private final int DELAY = 25; // controls the size of the board public static final int TILE_SIZE = 50; public static final int ROWS = 12; public static final int COLUMNS = 18; // suppress serialization warning private static final long serialVersionUID = 490905409104883233L; // keep a reference to the frameTimer object that triggers actionPerformed() in // case we need access to it in another method private final Timer frameTimer; private final Player player; public Screen(ObjectCollection _mainCollection) { mainCollection = _mainCollection; // set the game board size setPreferredSize(new Dimension(TILE_SIZE * COLUMNS, TILE_SIZE * ROWS)); // set the game board background color setBackground(new Color(232, 232, 232)); // hide the mouse cursor (https://stackoverflow.com/questions/191592/how-do-i-get-rid-of-the-mouse-cursor-in-full-screen-exclusive-mode) Toolkit toolkit = Toolkit.getDefaultToolkit(); Point hotSpot = new Point(0,0); BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TRANSLUCENT); invisibleCursor = toolkit.createCustomCursor(cursorImage, hotSpot, "InvisibleCursor"); // initialize the game state player = new Player(TILE_SIZE*COLUMNS, TILE_SIZE*ROWS); // this frameTimer will call the actionPerformed() method every DELAY ms frameTimer = new Timer(DELAY, this); frameTimer.start(); initialised = true; } @Override public void actionPerformed(ActionEvent e) { // run the tick of the player before the board is redrawn player.tick(get_mouse_rel()); // draw screen repaint(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); // when calling g.drawImage() we can use "this" for the ImageObserver // because Component implements the ImageObserver interface, and JPanel // extends from Component. So "this" Board instance, as a Component, can // react to imageUpdate() events triggered by g.drawImage() // draw graphics. drawScreen(g); // player.draw(g, this); // this smooths out animations on some systems Toolkit.getDefaultToolkit().sync(); } private void drawScreen(Graphics g) { BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB ); BufferedImage zBuf = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); BufferedImage debugImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); debugImg.createGraphics(); g.setColor(Color.white); // System.out.println(zBuf.getRGB(0,0)); // zBuf.setRGB(0,0, 100); // System.out.println(zBuf.getRGB(0,0)); // line.point2.x = 100*Math.sin(ang) + 200; // line.point2.y = 100*Math.cos(ang) + 200; // Triangle.point2.x = 100*Math.sin(ang+3) + 200; // Triangle.point2.y = 100*Math.cos(ang+3) + 200; // line.draw(img); /* ArrayList<Point3D> newPoints = new ArrayList<Point3D>(); for (Point3D point: points) { Point3D _new = new Point3D(0,0,0); player.camMatrix.multiplyPoint3to(point, _new); if(_new.z > .1) { newPoints.add(_new); } else{ newPoints.add(null); } } Triangle t1 = null; Triangle t2 = null; try { t1 = new Triangle( newPoints.get(0).project(player.FPDis, getWidth(), getHeight()), newPoints.get(1).project(player.FPDis, getWidth(), getHeight()), newPoints.get(2).project(player.FPDis, getWidth(), getHeight())); } catch(NullPointerException ignored){} try{ t2 = new Triangle( newPoints.get(0).project(player.FPDis, getWidth(), getHeight()), newPoints.get(2).project(player.FPDis, getWidth(), getHeight()), newPoints.get(3).project(player.FPDis, getWidth(), getHeight())); } catch(NullPointerException ignored){} try{t1.draw(img);}catch (NullPointerException ignored){} try{t2.draw(img);}catch (NullPointerException ignored){} ang += 0.02;*/ mainCollection.invalidate(true); mainCollection.draw(img, zBuf, debugImg, player.camMatrix, player.getPos(), player.frustumPlanes, player.Fpdis, getWidth(), getHeight()); g.drawImage(img, 0, 0, this); // DEBUG DRAWING { debugImg.getGraphics().drawString(Math.round(1000 / (float) (System.currentTimeMillis() - lastTime)) + " fps", 10, 10); debugImg.getGraphics().drawString("fpPos: " + String.format("%.2f", player.FPWorldPos.x) + " " + String.format("%.2f", player.FPWorldPos.y) + " " + String.format("%.2f", player.FPWorldPos.z) + " ", 100, 30); g.drawImage(debugImg, 0, 0, this); debugImg.getGraphics().drawString("playerPos: " + String.format("%.2f", player.getPos().x) + " " + String.format("%.2f", player.getPos().y) + " " + String.format("%.2f", player.getPos().z) + " ", 100, 50); debugImg.getGraphics().drawString("rotation: " + Math.round(Math.toDegrees(player.getRot().x)) + " " + Math.round(Math.toDegrees(player.getRot().y)) + " " + Math.round(Math.toDegrees(player.getRot().z)) + " ", 300, 50); debugImg.getGraphics().drawString("viewVec: " + String.format("%.2f", player.viewVector.x) + " " + String.format("%.2f", player.viewVector.y) + " " + String.format("%.2f", player.viewVector.z) + " ", 100, 70); for (int i = 0; i < 4; i += 1) { debugImg.getGraphics().drawString("camPoint " + i + ": " + String.format("%.2f", player.ScreenCornerPosS[i].getRotatedPoint().x) + " " + String.format("%.2f", player.ScreenCornerPosS[i].getRotatedPoint().y) + " " + String.format("%.2f", player.ScreenCornerPosS[i].getRotatedPoint().z), 10, 90 + 20 * i); } for (int i = 0; i < 6; i += 1) { debugImg.getGraphics().drawString("plane " + i + ": " + String.format("%.2f", player.frustumPlanes[i].mainPoint.x) + " " + String.format("%.2f", player.frustumPlanes[i].mainPoint.y) + " " + String.format("%.2f", player.frustumPlanes[i].mainPoint.z) + ", normal: " + String.format("%.2f", player.frustumPlanes[i].normalVector.x) + " " + String.format("%.2f", player.frustumPlanes[i].normalVector.y) + " " + String.format("%.2f", player.frustumPlanes[i].normalVector.z), 10, 170 + 20 * i); } // write debug overlay g.drawImage(debugImg, 0, 0, this); lastTime = System.currentTimeMillis(); } // HTTPPost post = new HTTPPost(); // // json WRITING // json = new JsonWriter(); // Point3D[] vertexList; // int[][] faceList; // // // camera object // vertexList = new Point3D[5]; // faceList = new int[][]{{0, 1, 2, 3}}; // for (int i = 0; i < 4; i += 1) { // vertexList[i] = player.ScreenCornerPosS[i].getRotatedPoint(); // } // vertexList[4] = player.FPWorldPos; // json.addBlenderObject(vertexList, faceList); // // post.invokePost(json); } @Override public void keyTyped(KeyEvent e) {} @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_ESCAPE){ captured = false; setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } // pass key-press to the player, so they can handle it as well player.keyPressed(key); } @Override public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); // pass key-release to the player, so they can handle it as well player.keyReleased(key); } // gets the relative position of the mouse since the last time this function was called public Point2D get_mouse_rel(){ Point2D rel; // this doesn't work if the mouse isn't captured. If I need it to, I can // probably make it, but I don't know what the functionality looks like. if (captured) { rel = new Point2D(MouseInfo.getPointerInfo().getLocation().x - getLocationOnScreen().x - getSize().width / 2 + mouseRel.x, MouseInfo.getPointerInfo().getLocation().y - getLocationOnScreen().y - getSize().height / 2 + mouseRel.y); mouseRel.set(0, 0); // set the position of the mouse back to (0,0) try { Robot robot = new Robot(); robot.mouseMove(getLocationOnScreen().x + getSize().width / 2, getLocationOnScreen().y + getSize().height / 2); } catch (AWTException ex) { ex.printStackTrace(); } } else{ rel = new Point2D(0,0); } return rel; } @Override public void mouseClicked(MouseEvent mouseEvent) { if (mouseEvent.getButton() == MouseEvent.BUTTON1){ captured = true; get_mouse_rel(); setCursor(invisibleCursor); } } @Override public void mousePressed(MouseEvent mouseEvent) {} @Override public void mouseReleased(MouseEvent mouseEvent) {} @Override public void mouseEntered(MouseEvent mouseEvent) {} @Override public void mouseExited(MouseEvent mouseEvent) { if (captured) { // add current mouse relative location to mouseRel so mouse movements are not lost mouseRel.x += mouseEvent.getX() - getSize().width / 2d; mouseRel.y += mouseEvent.getY() - getSize().height / 2d; // System.out.println(mouseEvent.getX() + " " + mouseEvent.getY()); // set the position of the mouse back to (0,0) try { Robot robot = new Robot(); robot.mouseMove(getLocationOnScreen().x + getSize().width / 2, getLocationOnScreen().y + getSize().height / 2); } catch (AWTException ex) { ex.printStackTrace(); } } } @Override public void mouseDragged(MouseEvent mouseEvent) {} @Override public void mouseMoved(MouseEvent mouseEvent) { } }