jeu-de-combat/src/engine/Engine.java
2021-06-23 18:06:23 +02:00

314 lines
8.7 KiB
Java

package engine;
import engine.camera.*;
import engine.gui.UIDummy;
import engine.input.*;
import engine.math.*;
import engine.object.*;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Engine {
private static long window;
private final List<ObjectGl> objectsGl;
public final List<UIDummy> uiElements;
private boolean running;
private final int width;
private final int height;
private final boolean fullscreen;
private float viewXPos;
private float viewYPos;
private Vector3f transformationView;
private final Camera camera;
private TrackingDummy tracking;
/*
Init Method
*/
/**
* Create the engine and initial attributes use .init() to start the engine
* Initial projection is -1000;1000 in width and -1000*aspectRatio; 1000*aspectRatio
* Initial Camera position is (0, 0, -1) //TODO vérifiez
*/
public Engine(int width, int height, boolean fullscreen, Vector3f aspectRatio) {
this.running = false;
this.objectsGl = new ArrayList<>();
this.uiElements = new ArrayList<>();
this.width = width;
this.height = height;
this.viewXPos = 0.0f;
this.viewYPos = 0.0f;
this.camera = new Camera(1000, aspectRatio, this);
ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f, 0.0f, 1.0f));
this.transformationView = new Vector3f();
this.tracking = null;
this.fullscreen = fullscreen;
}
/**
* Start the engine
* Create the window
* Set the color of the background
*/
public void init() {
if (!glfwInit()){
System.exit(-1);
}
this.running = true;
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //On utilise la version 3.3 d'openGL
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Compatible MAC
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Le core profile est l'interface 'avancé' d'openGL
int width = this.width;
int height = this.height;
if (fullscreen) {
this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", glfwGetPrimaryMonitor(), NULL));
} else {
this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL));
}
assert getWindow() != NULL;
// On récupère les informations du moniteur principal
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
assert vidmode != null;
// On met la fenêtre au centre de l'écran principale
glfwSetWindowPos(getWindow(), (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);
glfwSetKeyCallback(getWindow(), new KeyboardInput());
glfwSetInputMode(getWindow(), GLFW_STICKY_KEYS, GLFW_TRUE);
// Contexte = zone cible des rendus
glfwMakeContextCurrent(getWindow());
glfwShowWindow(getWindow());
GL.createCapabilities();
correctViewport(this.width, this.height);
glfwSetFramebufferSizeCallback(getWindow(), resizeWindow);
glEnable(GL_DEPTH_TEST); // Z-Buffer plus z est grand plus l'objet est proche de la camera limite à 100.0f au dela l'objet disparait
glEnable(GL_BLEND); // Transparence
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
System.out.println("OpenGL: " + glGetString(GL_VERSION));
}
/*
RENDER / UPDATE
*/
public void render() {
glEnable(GL_SCISSOR_TEST);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
objectsGl.sort(new SortZ());
for (ObjectGl objectGl : objectsGl) {
objectGl.render();
}
int error = glGetError();
if (error != GL_NO_ERROR) System.out.println(error);
glfwSwapBuffers(getWindow()); //Envoie le buffer vers le moniteur
}
/**
*
*/
public void update() {
glfwPollEvents();
// METS A JOUR LA POSITION DES ELEMENTS D'INTERFACE
for (UIDummy uiElement : this.uiElements){
uiElement.update();
}
}
/*
Window / Viewport Management
*/
public static void correctViewport(int width, int height){
int heightViewport, widthViewport, x, y;
if (width >= height * 4.0f/3.0f){
heightViewport = height;
widthViewport = (int) (height * 4.0f/3.0f);
y = 0;
x = (width - widthViewport)/2;
} else {
widthViewport = width;
heightViewport = (int) (width * 3.0f/4.0f);
y = (height - heightViewport)/2;
x = 0;
}
glScissor(x, y, widthViewport, heightViewport);
glViewport(x, y, widthViewport, heightViewport);
}
public boolean shouldClose() {
return glfwWindowShouldClose(getWindow());
}
/*
ObjectGl Management
*/
/**
* Add obj to the render queue
* @param obj ObjectGl to render
*/
public void add_objectGl(ObjectGl obj) {
this.objectsGl.add(obj);
}
public void add_objectsGl(List<ObjectGl> objs) {
this.objectsGl.addAll(objs);
}
public void remove_objectGl(ObjectGl obj) {
obj.delete();
this.objectsGl.remove(obj);
}
public void remove_objectsGl(List<ObjectGl> obj) {
this.objectsGl.removeAll(obj);
}
/*
UIElement Management
*/
public void add_uiElement(UIDummy uiElement) {
uiElement.init();
this.uiElements.add(uiElement);
}
public void remove_uiElement(UIDummy uiElement) {
this.uiElements.remove(uiElement);
uiElement.delete();
}
public void setUIElementZoomFactor(float scaleFactor){
for (UIDummy uiElement : this.uiElements){
uiElement.updateScalingFactor(scaleFactor);
}
}
/*
CAMERA
*/
public void translateView(Vector3f vec){
ObjectGl.view = ObjectGl.view.multiply(Matrix4f.translate(vec));
viewXPos += vec.x;
this.transformationView = this.transformationView.addXYZ(vec);
}
/**
* Translate la camera pour avoir obj au centre de l'image, comme le cadrage se fait sur le point en haut à gauche
* de l'objet un offset peut parfois être nécessaire
* @param obj l'objectGl que la camera va suivre
* @param xOffset un offSet sur l'axe X
*/
public void cameraTrackingObjectGl(ObjectGl obj, float xOffset){
Vector3f trackingVector = new Vector3f((- obj.getXPos() - this.viewXPos) + xOffset,0.0f ,0.0f);
this.translateView(trackingVector);
}
public void setCameraTrackingBetweenTwoObjectGl(ObjectGl obj1, ObjectGl obj2, float deadZone){
// obj2 est considéré à droite probablement à modifier
this.tracking = new TrackingTore(
deadZone,
obj1,
obj2,
this);
}
public void setCameraTrackingSF3ThirdStrike(ObjectGl obj1, ObjectGl obj2){
this.tracking = new TrackingSF3ThirdStrick(obj1, obj2, this);
}
public void cameraTracking(){
if (this.tracking == null) System.out.println("Define a tracking first");
else {
Vector3f trackingVector = this.tracking.getViewVector();
this.translateView(trackingVector);
}
}
/*
CALLBACK
*/
/**
* Est appelé à chaque modification de la taille de la fenêtre, et modifie la taille de la zone de rendu
* pour quelle corresponde à la taille de la fenêtre
*/
private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback() {
@Override
public void invoke(long window, int width, int height) {
correctViewport(width, height);
}
};
/*
GET/SET
*/
public boolean getRunning() {
return running;
}
public void setRunning(boolean b) {
running = b;
}
public float getViewXPos(){
return viewXPos;
}
public float getViewYPos(){
return viewYPos;
}
public Vector3f getTransformationView() {
return transformationView;
}
public Camera getCamera(){
return this.camera;
}
public static long getWindow() {
return window;
}
public void setWindow(long window) {
Engine.window = window;
}
}