package uk.org.floop.epq3d;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class Screen extends JPanel implements ActionListener, KeyListener, MouseListener, MouseMotionListener {
// __working variables__
public boolean initialised;
public long lastTime = 0;
// mouse
private boolean captured = false;
private final Point2D mouseRel = new Point2D(0,0);
private final Cursor invisibleCursor;
// uber class for storing all draw data which needs to be passed to functions
public final drawData drawData;
// mainCollection stores all the background information in the scene
public ObjectCollection mainCollection;
// stores the skybox
public Object3d skyBox;
// 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
// 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;
// initialise drawData
drawData = new drawData("config.json");
// set the game board size
setPreferredSize(new Dimension(drawData.scrX, drawData.scrY));
// 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(drawData);
lastTime = System.currentTimeMillis();
// this frameTimer will call the actionPerformed() method every DELAY ms
frameTimer = new Timer(drawData.delay, this);
frameTimer.start();
initialised = true;
}
@Override
public void actionPerformed(ActionEvent e) {
// get mouse rel
drawData.mouseRel = get_mouse_rel();
// run the tick of the player before the board is redrawn
player.tick(drawData);
// 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) {
// 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;*/
drawData.lastFrameTime = System.currentTimeMillis()- lastTime;
lastTime = System.currentTimeMillis();
mainCollection.invalidate(true);
ArrayList<Integer> FrustumInfo = new ArrayList<>();
for(int i = 0; i<6; i += 1){FrustumInfo.add(i);}
mainCollection.draw(drawData, FrustumInfo);
// DEBUG DRAWING
{
//debugImg.getGraphics().drawString(Math.round(1000 / (float) (System.currentTimeMillis() - lastTime)) + " fps", 10, 10);
drawData.debugImg.getGraphics().drawString("FrameTime: " + (System.currentTimeMillis() - lastTime) + " millis", 10, 10);
if(drawData.debugHud) {
drawData.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(drawData.debugImg, 0, 0, this);
drawData.debugImg.getGraphics().drawString("playerPos: " +
String.format("%.2f", player.getPos().x) + " " +
String.format("%.2f", player.getPos().y) + " " +
String.format("%.2f", player.getPos().z) + " ", 100, 50);
drawData.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);
drawData.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) {
drawData.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) {
drawData.debugImg.getGraphics().drawString("plane " + i + ": " +
String.format("%.2f", drawData.frustumPlanes[i].mainPoint.x) + " " +
String.format("%.2f", drawData.frustumPlanes[i].mainPoint.y) + " " +
String.format("%.2f", drawData.frustumPlanes[i].mainPoint.z) + ", normal: " +
String.format("%.2f", drawData.frustumPlanes[i].normalVector.x) + " " +
String.format("%.2f", drawData.frustumPlanes[i].normalVector.y) + " " +
String.format("%.2f", drawData.frustumPlanes[i].normalVector.z), 10, 170 + 20 * i);
}
}
// write debug overlay
for(int x = 0; x < drawData.scrX; x +=1){
for(int y = 0; y < drawData.scrY; y += 1){
if(drawData.drawZBuffer){
drawData.bufImg.setRGB(x, y, Color.getHSBColor(0, 0, (float)drawData.zBuf[x][y]/2147483648f).getRGB());
} else {
drawData.bufImg.setRGB(x, y, drawData.drawImg[x][y]);
}
drawData.drawImg[x][y] = 0;
drawData.zBuf[x][y] = 0;
}
}
g.drawImage(drawData.bufImg, 0, 0, this);
g.drawImage(drawData.debugImg, 0, 0, this);
for(int x = 0; x < drawData.scrX; x +=1){
for(int y = 0; y < drawData.scrY; y += 1){
drawData.debugImg.setRGB(x, y, 0);
}
}
}
// 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) {
}
}