diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..763ac98
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/.idea/
+/.gitignore
+/jeu-de-combat.iml
+/target/
+/bin/
diff --git a/.idea/jeu-de-combat.iml b/.idea/jeu-de-combat.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/jeu-de-combat.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..90e6b95
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/Architecture_Moteur_V1.pdf b/docs/Architecture_Moteur_V1.pdf
new file mode 100644
index 0000000..32d5633
Binary files /dev/null and b/docs/Architecture_Moteur_V1.pdf differ
diff --git a/shaders/ObjectGl/frag.glsl b/shaders/ObjectGl/frag.glsl
new file mode 100644
index 0000000..f76853f
--- /dev/null
+++ b/shaders/ObjectGl/frag.glsl
@@ -0,0 +1,10 @@
+#version 330 core
+
+out vec4 FragColor;
+
+uniform float time;
+
+void main()
+{
+ FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+}
\ No newline at end of file
diff --git a/shaders/ObjectGl/vert.glsl b/shaders/ObjectGl/vert.glsl
new file mode 100644
index 0000000..58be87a
--- /dev/null
+++ b/shaders/ObjectGl/vert.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+
+layout (location = 0) in vec3 aPos;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 transform;
+
+void main()
+{
+ gl_Position = projection * view * transform * vec4(aPos, 1.0);
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlColor/frag.glsl b/shaders/ObjectGlColor/frag.glsl
new file mode 100644
index 0000000..3a1ca99
--- /dev/null
+++ b/shaders/ObjectGlColor/frag.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+
+in vec3 color;
+
+out vec4 FragColor;
+
+uniform float time;
+
+void main()
+{
+ FragColor = vec4(color, 1.0f);
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlColor/vert.glsl b/shaders/ObjectGlColor/vert.glsl
new file mode 100644
index 0000000..2a867f6
--- /dev/null
+++ b/shaders/ObjectGlColor/vert.glsl
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec3 aColor;
+
+out vec3 color;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 transform;
+
+void main()
+{
+ gl_Position = projection * view * transform * vec4(aPos, 1.0);
+ color = aColor;
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlTex/frag.glsl b/shaders/ObjectGlTex/frag.glsl
new file mode 100644
index 0000000..a13c996
--- /dev/null
+++ b/shaders/ObjectGlTex/frag.glsl
@@ -0,0 +1,13 @@
+#version 410 core
+
+out vec4 FragColor;
+
+in vec2 texCoord;
+
+uniform sampler2D texture1;
+uniform float time;
+
+void main()
+{
+ FragColor = texture(texture1, texCoord);
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlTex/vert.glsl b/shaders/ObjectGlTex/vert.glsl
new file mode 100644
index 0000000..64f4b92
--- /dev/null
+++ b/shaders/ObjectGlTex/vert.glsl
@@ -0,0 +1,16 @@
+#version 410 core
+
+layout (location = 0) in vec3 aPos;
+layout (location = 2) in vec2 aTexCoord;
+
+out vec2 texCoord;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 transform;
+
+void main()
+{
+ gl_Position = projection * view * transform * vec4(aPos, 1.0);
+ texCoord = aTexCoord;
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlTexColor/frag.glsl b/shaders/ObjectGlTexColor/frag.glsl
new file mode 100644
index 0000000..2f6e845
--- /dev/null
+++ b/shaders/ObjectGlTexColor/frag.glsl
@@ -0,0 +1,19 @@
+#version 410 core
+
+out vec4 FragColor;
+
+in vec4 color;
+in vec2 texCoord;
+
+uniform sampler2D texture1;
+uniform float time;
+
+void main()
+{
+ vec4 tex = texture(texture1, texCoord);
+ if (tex.a == 0.0){
+ FragColor = tex;
+ } else{
+ FragColor = mix(tex, color, 0.5);
+ }
+}
\ No newline at end of file
diff --git a/shaders/ObjectGlTexColor/vert.glsl b/shaders/ObjectGlTexColor/vert.glsl
new file mode 100644
index 0000000..d1e7488
--- /dev/null
+++ b/shaders/ObjectGlTexColor/vert.glsl
@@ -0,0 +1,19 @@
+#version 410 core
+
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec3 aColor;
+layout (location = 2) in vec2 aTexCoord;
+
+out vec2 texCoord;
+out vec4 color;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 transform;
+
+void main()
+{
+ gl_Position = projection * view * transform * vec4(aPos, 1.0);
+ color = vec4(aColor, 1.0f);
+ texCoord = aTexCoord;
+}
\ No newline at end of file
diff --git a/shaders/StylishShaders/BasicVert.glsl b/shaders/StylishShaders/BasicVert.glsl
new file mode 100644
index 0000000..625b793
--- /dev/null
+++ b/shaders/StylishShaders/BasicVert.glsl
@@ -0,0 +1,21 @@
+#version 410 core
+
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec3 aColor;
+layout (location = 2) in vec2 aTexCoord;
+
+out vec2 fragCoord;
+out vec2 texCoord;
+out vec4 color;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 transform;
+
+void main()
+{
+ gl_Position = projection * view * transform * vec4(aPos, 1.0);
+ color = vec4(aColor, 1.0f);
+ texCoord = aTexCoord;
+ fragCoord = aPos.xy;
+}
\ No newline at end of file
diff --git a/shaders/StylishShaders/EnergyWave.glsl b/shaders/StylishShaders/EnergyWave.glsl
new file mode 100644
index 0000000..a550c6b
--- /dev/null
+++ b/shaders/StylishShaders/EnergyWave.glsl
@@ -0,0 +1,21 @@
+#version 410
+
+out vec4 FragColor;
+
+in vec4 color;
+in vec2 fragCoord;
+in vec2 texCoord;
+
+uniform sampler2D texture1;
+uniform float time;
+
+void main()
+{ // Pas fini c'est moche
+ vec4 colorPoweredUp = abs(vec4(color.xyz * sin(fragCoord.y + time*20), 1.0));
+ vec4 tex = texture(texture1, texCoord);
+ if (tex.a == 0.0){
+ FragColor = tex;
+ } else{
+ FragColor = mix(tex, colorPoweredUp, 0.5);
+ }
+}
diff --git a/src/Main.java b/src/Main.java
index 7c9120e..601def5 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -7,8 +7,8 @@
*
*/
-import launcher.Launcher;
import engine.Engine;
+import launcher.Launcher;
import javafx.application.Application;
public class Main {
diff --git a/src/engine/Engine.java b/src/engine/Engine.java
index 2195c4e..505ac5a 100644
--- a/src/engine/Engine.java
+++ b/src/engine/Engine.java
@@ -1,14 +1,305 @@
-/**
- * CLASS ENGINE
- *
- * Classe principale du moteur de jeu
- *
- * @author François Autin
- *
- */
-
package engine;
+import engine.math.*;
+import engine.object.*;
+
+import org.lwjgl.glfw.GLFW;
+import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
+import org.lwjgl.glfw.GLFWVidMode;
+import org.lwjgl.opengl.GL;
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+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 objectsGl;
+
+ private static boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1);
+
+ private boolean running;
+
+ /**
+ * Create the engine and initial attributes use .init() to start the engine
+ */
+ public Engine() {
+ this.running = false;
+ this.objectsGl = new ArrayList<>();
+ float width = 1280.0f;
+ ObjectGl.projection = Matrix4f.orthographic(-width, width, -width * 9.0f / 16.0f, width * 9.0f / 16.0f, 0.1f, 100.0f);
+ ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f,0.0f,1.0f));
+ }
+
+ /**
+ * Start the engine
+ * Create the window
+ * Set the color of the background
+ */
+ public void init() {
+ glfwInit();
+
+ 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 = 1280;
+ int height = 720;
+ this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL));
+ assert getWindow() != NULL;
+
+
+ System.out.println(present);
+
+ // 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 Input());
+ glfwSetInputMode(getWindow(), GLFW_STICKY_KEYS, GLFW_TRUE);
+
+ // Contexte = zone cible des rendus
+ glfwMakeContextCurrent(getWindow());
+ glfwShowWindow(getWindow());
+ GL.createCapabilities();
+
+ 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));
+ }
+
+ /**
+ *
+ */
+ public void update(){
+ glfwPollEvents();
+ }
+
+ /**
+ *
+ */
+ public void render(){
+
+ 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
+ }
+
+ /**
+ * Add obj to the render queue
+ * @param obj
+ */
+ public void add_objectGl(ObjectGl obj){
+ objectsGl.add(obj);
+ }
+
+ public void remove_objectGl(ObjectGl obj){
+ objectsGl.remove(obj);
+ }
+
+ public boolean isRunning(){
+ return running;
+ }
+
+ public void setRunning(boolean b){
+ running = b;
+ }
+
+ public boolean shouldClose(){
+ return glfwWindowShouldClose(getWindow());
+ }
+
+ public static long getWindow() {
+ return window;
+ }
+
+ public void setWindow(long window) {
+ Engine.window = window;
+ }
+
+ /**
+ * Est appelé à a 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){
+ glViewport(0,0,width,height);
+ }
+ };
+
+ public static void main(String[] args) {
+ Engine engine = new Engine();
+ int speed = 10 ; //vitesse déplacement Object
+ engine.init();
+
+ // Add objects to render
+ String path = "textures/zangief_sprite.png";
+
+ String path2 = "textures/awesomeface.png";
+
+ ObjectGl zangief = new ObjectGl(0f,60f,80f,10f, path, null);
+ zangief.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
+ engine.add_objectGl(zangief);
+ zangief.translate(new Vector3f(-5000.0f,500.0f,10.0f));
+ zangief.setColor(new Vector3f(0.0f, 0.0f, 1.0f));
+ zangief.useTime = true;
+ zangief.setShader("shaders/StylishShaders/BasicVert.glsl","shaders/StylishShaders/EnergyWave.glsl");
+
+// ObjectGl smiley2 = new ObjectGl(0.0f,500.0f,500.0f, 1f, path2, null);
+// engine.add_objectGl(smiley2);
+// smiley2.translate(new Vector3f(0.0f,0.0f,5.0f));
+
+ long timer = System.currentTimeMillis();
+ long lastFrame;
+ int frame = 0;
+ boolean nextFrame = false;
+
+ while(engine.isRunning()){
+ lastFrame = System.currentTimeMillis();
+ // Game logic should fit here
+
+ if (present) {
+ gamepadInput(zangief, speed);
+ }
+
+ input(zangief, speed);
+// input(smiley2, speed);
+
+ /*
+ ********************
+ * essential part v *
+ ********************
+ */
+ engine.update();
+ engine.render();
+
+ frame++;
+
+ if (System.currentTimeMillis() - timer > 1000) {
+ timer += 1000;
+ System.out.println("FPS: " + frame);
+ frame = 0;
+ }
+
+ while(!nextFrame){
+ nextFrame = System.currentTimeMillis() - lastFrame >= 16.66f;
+ }
+
+ nextFrame = false;
+ if(engine.shouldClose()) engine.setRunning(false);
+ }
+ }
+
+ private static void gamepadInput(ObjectGl token, int speed) {
+ ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1);
+ FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1);
+
+ assert gamepadAxes != null;
+ assert gamepadButton != null;
+
+ String name = GLFW.glfwGetJoystickName(GLFW_JOYSTICK_1);
+ System.out.println("GamePad Name :" + name);
+// for (int i =0 ; i < gamepadAxes.capacity(); i++) {
+// System.out.println(i + " :" + gamepadAxes.get(i));
+// }
+
+
+ if (gamepadButton.get(0) ==1 ) { // appuie sur croix(PlayStation) A (Xbox)
+ token.translate(new Vector3f ( 0.0f, speed * 5.0f, 0.0f));
+ }
+ if ( (gamepadAxes.get(2) < -0.1 || gamepadAxes.get(2) > 0.1) ) { // de droite à gauche //joystick gauche
+ token.translate(new Vector3f (5*speed * gamepadAxes.get(2), 0.0f, 0.0f));
+ if ( gamepadAxes.get(2) < -0.1 ){
+ token.setTextureWrap(121,0,57,80, ObjectGl.DEFAULT);
+ }else if (gamepadAxes.get(2) > 0.1) {
+ token.setTextureWrap(178,0,62,82, ObjectGl.DEFAULT);
+ }
+ }
+
+ if ( (gamepadAxes.get(3) < -0.1 || gamepadAxes.get(3) > 0.1) ) { // de haut en bas //joystick gauche
+ token.translate(new Vector3f (0.0f, -5* speed * gamepadAxes.get(3), 0.0f));
+
+ }
+
+ /* Buttons
+ 0 : Croix / A
+ 1: rond /B
+ 2: carré / X
+ 3: triangle / Y
+ 4: L1 / LB
+ 5: R1 / RB
+ 6:select
+ 7:start
+ 8:L3
+ 9:R3
+ 10: haut
+ 11: droite
+ 12: bas
+ 13: gauche
+ */
+
+ /* Axes
+ 0 : left X axe ( right : 1 left -1)
+ 1: left Y axe ( down : 1 , Up -1)
+ 2: right X axe ( right : 1 left -1)
+ 3: right Y axe ( down : 1 , Up -1)
+ 4:L2 / LT : 1 active, -1 unactive
+ 5: R2 /RT : 1 active, -1 unactive
+ */
+
+ }
+
+ public static void input(ObjectGl token, int speed) {
+ boolean keyPressed = false;
+ if (Input.isKeyDown(GLFW.GLFW_KEY_S)) {
+ token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM);
+ keyPressed = true;
+ } else if (Input.isKeyDown(GLFW.GLFW_KEY_W)) {
+// token.translate(new Vector3f (0.0f, speed * 5.0f, 0.0f));
+ keyPressed = true;
+ }
+ if (Input.isKeyDown(GLFW.GLFW_KEY_A)) {
+ token.translate(new Vector3f (speed *-5.0f, 0.0f, 0.0f));
+// token.setTextureWrap(121,0,57,80, ObjectGl.STICK_TOP);
+ token.setTextureWrap(121,0,57,82, ObjectGl.STICK_TOP);
+ keyPressed = true;
+ }
+ else if (Input.isKeyDown(GLFW.GLFW_KEY_D)) {
+ token.translate(new Vector3f (speed * 5.0f, 0.0f, 0.0f));
+// token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
+ token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
+ keyPressed = true;
+ }
+// if (!keyPressed) token.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
+ if (!keyPressed) token.setTextureWrap(58,0,62,82, ObjectGl.STICK_TOP);
+ }
}
diff --git a/src/engine/Input.java b/src/engine/Input.java
new file mode 100644
index 0000000..194335c
--- /dev/null
+++ b/src/engine/Input.java
@@ -0,0 +1,26 @@
+package engine;
+
+import org.lwjgl.glfw.GLFW;
+import org.lwjgl.glfw.GLFWKeyCallback;
+
+import static org.lwjgl.glfw.GLFW.*;
+import static org.lwjgl.opengl.GL11.*;
+
+public class Input extends GLFWKeyCallback {
+
+ public static boolean[] keys = new boolean[65536];
+
+ @Override
+ public void invoke(long window, int key, int scancode, int action, int mods) {
+ keys[key] = action != GLFW.GLFW_RELEASE;
+ if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
+ glfwSetWindowShouldClose(window, true);
+ else if(key == GLFW_KEY_SPACE && action == GLFW_PRESS) //Switch to wireframe
+ if (glGetInteger(GL_POLYGON_MODE) == GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ public static boolean isKeyDown(int keyCode) {
+ return glfwGetKey(Engine.getWindow(), keyCode) == 1;
+ }
+
+}
diff --git a/src/engine/graphics/Shader.java b/src/engine/graphics/Shader.java
new file mode 100644
index 0000000..19ae290
--- /dev/null
+++ b/src/engine/graphics/Shader.java
@@ -0,0 +1,75 @@
+package engine.graphics;
+
+import engine.math.Matrix4f;
+import engine.utils.ShaderUtils;
+import engine.math.Vector3f;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.lwjgl.opengl.GL20.*;
+
+public class Shader {
+
+ private boolean enabled = false;
+
+ //Identifiant du programme resultat de la compilation des shaders
+ private final int ID;
+ private Map locationCache = new HashMap();
+
+ /*
+ Crée le fragment et le vertex shader les lie dans un programme dont il renvoie l'identifiant.
+ */
+ public Shader(String vertex, String fragment) {
+ ID = ShaderUtils.load(vertex, fragment);
+ }
+
+ public int getUniform(String name){
+ if (locationCache.containsKey(name)) return locationCache.get(name);
+ int result = glGetUniformLocation(ID, name);
+ if (result == -1) System.err.println("Could not find uniform variable " + name);
+ else locationCache.put(name, result);
+ return result;
+ }
+
+ public void setUniform1i(String name, int value) {
+ if (!enabled) enable();
+ glUniform1i(getUniform(name), value);
+ }
+
+ public void setUniform1f(String name, float value) {
+ if (!enabled) enable();
+ glUniform1f(getUniform(name), value);
+ }
+
+ public void setUniform2f(String name, float x, float y) {
+ if (!enabled) enable();
+ glUniform2f(getUniform(name), x, y);
+ }
+
+ public void setUniform3f(String name, Vector3f vector) {
+ if (!enabled) enable();
+ glUniform3f(getUniform(name), vector.x, vector.y, vector.z);
+ }
+
+ public void setUniform4f(String name, float x, float y, float z, float w) {
+ if (!enabled) enable();
+ glUniform4f(getUniform(name), x, y, z, w);
+ }
+
+ public void setUniformMat4f(String name, Matrix4f matrix){
+ if (!enabled) enable();
+ glUniformMatrix4fv(getUniform(name), false, matrix.toFloatBuffer());
+ }
+
+ public void enable() {
+ glUseProgram(ID);
+ enabled = true;
+ }
+
+ public void disable() {
+ glUseProgram(0);
+ enabled = false;
+ }
+
+}
diff --git a/src/engine/graphics/Texture.java b/src/engine/graphics/Texture.java
new file mode 100644
index 0000000..4f06db9
--- /dev/null
+++ b/src/engine/graphics/Texture.java
@@ -0,0 +1,75 @@
+package engine.graphics;
+
+import engine.utils.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.image.BufferedImage;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL30.*;
+
+public class Texture {
+
+ private int width, height;
+ private int texture;
+ private int index;
+
+ public Texture(String path, int index) {
+ this.index = index;
+ texture = load(path);
+ }
+
+ private int load(String path) {
+ int[] pixels = null;
+ try {
+ BufferedImage image = ImageIO.read(new FileInputStream(path));
+ width = image.getWidth();
+ height = image.getHeight();
+ pixels = new int[width * height];
+ image.getRGB(0, 0, width, height, pixels, 0, width);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ int[] data = new int[width * height];
+ for (int i = 0; i < width * height; i++) {
+ int a = (pixels[i] & 0xff000000) >> 24;
+ int r = (pixels[i] & 0xff0000) >> 16;
+ int g = (pixels[i] & 0xff00) >> 8;
+ int b = (pixels[i] & 0xff);
+
+ data[i] = a << 24 | b << 16 | g << 8 | r;
+ }
+
+ int result = glGenTextures();
+ glBindTexture(GL_TEXTURE_2D, result);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, BufferUtils.createIntBuffer(data));
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return result;
+ }
+
+ public void bind() {
+ glActiveTexture(GL_TEXTURE0 + this.index);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ }
+
+ public void unbind() {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ public int getWidth(){
+ return width;
+ }
+
+ public int getHeight(){
+ return height;
+ }
+
+}
diff --git a/src/engine/graphics/VertexArray.java b/src/engine/graphics/VertexArray.java
new file mode 100644
index 0000000..a8dc154
--- /dev/null
+++ b/src/engine/graphics/VertexArray.java
@@ -0,0 +1,89 @@
+package engine.graphics;
+
+import engine.utils.BufferUtils;
+
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.GL30.*;
+
+public class VertexArray {
+
+ private int VAO ,VBO, EBO, CBO, TBO;
+ private int count;
+
+ public VertexArray(float[] vertices, byte[] indices, float[] color, float[] texture) {
+ count = indices.length;
+ // VERTEX ARRAY OBJECT
+ VAO = glGenVertexArrays();
+ glBindVertexArray(VAO);
+
+ glEnableVertexAttribArray(0);
+
+ // VERTEX BUFFER OBJECT
+ createVertexBufferObject(vertices);
+ // COLOR BUFFER OBJECT
+ if (color != null) createColorBufferObject(color);
+ // TEXTURE BUFFER OBJECT
+ if (texture != null) createTextureBufferObject(texture);
+
+ EBO = glGenBuffers();
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ }
+
+ private void createVertexBufferObject(float[] vertices){
+ VBO = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
+ glEnableVertexAttribArray(0);
+ }
+
+ private void createColorBufferObject(float[] color){
+ CBO = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, CBO);
+ glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(color), GL_STATIC_DRAW);
+ glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
+ glEnableVertexAttribArray(1);
+ }
+
+ private void createTextureBufferObject(float[] texture){
+ TBO = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, TBO);
+ glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
+ glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
+ glEnableVertexAttribArray(2);
+ }
+
+ public void swapVertexBufferObject(float[] vertices){
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
+ }
+
+ public void swapTextureBufferObject(float [] texture){
+ glBindBuffer(GL_ARRAY_BUFFER, TBO);
+ glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
+ }
+
+ public void bind(){
+ glBindVertexArray(this.VAO);
+ }
+
+ public void unbind(){
+ glBindVertexArray(0);
+ }
+
+ public void draw(){
+ glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0);
+ }
+
+ public void render(){
+ bind();
+ draw();
+ unbind();
+ }
+
+}
diff --git a/src/engine/math/Matrix4f.java b/src/engine/math/Matrix4f.java
new file mode 100644
index 0000000..6291eb9
--- /dev/null
+++ b/src/engine/math/Matrix4f.java
@@ -0,0 +1,123 @@
+package engine.math;
+
+import engine.utils.BufferUtils;
+
+import java.nio.FloatBuffer;
+
+public class Matrix4f {
+
+ public static final int SIZE = 4 * 4;
+ public float[] elements = new float[4 * 4];
+
+ public Matrix4f(){
+
+ }
+
+ public static Matrix4f identity(){
+ Matrix4f result = new Matrix4f();
+ for (int i = 0; i < SIZE; i++){
+ result.elements[i] = 0.0f;
+ }
+ result.elements[0 + 0 * 4] = 1.0f;
+ result.elements[1 + 1 * 4] = 1.0f;
+ result.elements[2 + 2 * 4] = 1.0f;
+ result.elements[3 + 3 * 4] = 1.0f;
+ return result;
+ }
+
+ public static Matrix4f orthographic(float left, float right, float bottom, float top, float near, float far){
+ Matrix4f result = identity();
+
+ result.elements[0 + 0 * 4] = 2.0f / (right - left);
+ result.elements[1 + 1 * 4] = 2.0f / (top - bottom);
+ result.elements[2 + 2 * 4] = 2.0f / (near - far);
+
+ result.elements[0 + 3 * 4] = (left + right) / (left - right);
+ result.elements[1 + 3 * 4] = (bottom + top) / (bottom - top);
+ result.elements[2 + 3 * 4] = (far + near) / (far - near);
+
+ return result;
+ }
+
+ public static Matrix4f translate(Vector3f vector){
+ Matrix4f result= identity();
+ result.elements[0 + 3*4] = vector.x;
+ result.elements[1 + 3*4] = vector.y;
+ result.elements[2 + 3*4] = vector.z;
+
+ return result;
+ }
+
+ public static Matrix4f scale(Vector3f vector){
+ Matrix4f result= identity();
+ result.elements[0 + 0*4] = vector.x;
+ result.elements[1 + 1*4] = vector.y;
+ result.elements[2 + 2*4] = vector.z;
+
+ return result;
+ }
+
+ public static Matrix4f rotateX(float angle){
+ Matrix4f result = identity();
+ float r = (float) Math.toRadians(angle);
+ float cos = (float) Math.cos(r);
+ float sin = (float) Math.sin(r);
+
+ result.elements[1 + 1 * 4] = cos;
+ result.elements[2 + 1 * 4] = -sin;
+
+ result.elements[1 + 2 * 4] = sin;
+ result.elements[2 + 2 * 4] = cos;
+
+ return result;
+ }
+
+ public static Matrix4f rotateY(float angle){
+ Matrix4f result = identity();
+ float r = (float) Math.toRadians(angle);
+ float cos = (float) Math.cos(r);
+ float sin = (float) Math.sin(r);
+
+ result.elements[0 + 0 * 4] = cos;
+ result.elements[2 + 0 * 4] = sin;
+
+ result.elements[0 + 2 * 4] = -sin;
+ result.elements[2 + 2 * 4] = cos;
+
+ return result;
+ }
+
+ public static Matrix4f rotateZ(float angle){
+ Matrix4f result = identity();
+ float r = (float) Math.toRadians(angle);
+ float cos = (float) Math.cos(r);
+ float sin = (float) Math.sin(r);
+
+ result.elements[0 + 0 * 4] = cos;
+ result.elements[1 + 0 * 4] = -sin;
+
+ result.elements[0 + 1 * 4] = sin;
+ result.elements[1 + 1 * 4] = cos;
+
+ return result;
+ }
+
+ public Matrix4f multiply(Matrix4f matrix){
+ Matrix4f result = new Matrix4f();
+ for (int y = 0; y< 4; y++){
+ for (int x = 0; x< 4; x++){
+ float sum = 0.0f;
+ for (int e = 0; e< 4; e++){
+ sum += this.elements[x + e * 4] * matrix.elements[e + y * 4];
+ }
+ result.elements[x + y * 4] = sum;
+ }
+ }
+ return result;
+ }
+
+ public FloatBuffer toFloatBuffer() {
+ return BufferUtils.createFloatBuffer(elements);
+ }
+
+}
diff --git a/src/engine/math/Primitive.java b/src/engine/math/Primitive.java
new file mode 100644
index 0000000..56f2f95
--- /dev/null
+++ b/src/engine/math/Primitive.java
@@ -0,0 +1,38 @@
+package engine.math;
+
+import engine.math.Vector3f;
+
+public class Primitive {
+
+ public static float[] createRectangle(float z, float w, float h){
+ return new float[] {
+ 0 , 0 , z, // Haut gauche
+ 0 + w, 0 , z, // Haut droit
+ 0 + w, 0 - h, z, // Bas droit
+ 0 , 0 - h, z // Bas gauche
+ };
+ }
+
+ /**
+ * Chaque point correspond à un vertex de la primite le reste est interpolé
+ */
+ public static float[] stdTexWrap = new float[] {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f
+ };
+
+ public static float[] upperHalfTexWrap = new float[] {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.5f,
+ 0.0f, 0.5f
+ };
+
+ public static byte[] rectangle_indices = new byte[] {
+ 0, 1, 3,
+ 1, 2, 3
+ };
+
+}
diff --git a/src/engine/math/Vector3f.java b/src/engine/math/Vector3f.java
new file mode 100644
index 0000000..4f7c98b
--- /dev/null
+++ b/src/engine/math/Vector3f.java
@@ -0,0 +1,24 @@
+package engine.math;
+
+public class Vector3f {
+
+ public float x, y, z;
+
+ public Vector3f(){
+ x = 0.0f;
+ y = 0.0f;
+ z = 0.0f;
+ }
+
+ public Vector3f(float x, float y, float z){
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public void divXY(float div){
+ this.x /= div;
+ this.y /= div;
+ }
+
+}
diff --git a/src/engine/object/ObjectGl.java b/src/engine/object/ObjectGl.java
new file mode 100644
index 0000000..723cc2d
--- /dev/null
+++ b/src/engine/object/ObjectGl.java
@@ -0,0 +1,237 @@
+package engine.object;
+
+import engine.graphics.*;
+import engine.math.*;
+
+import static org.lwjgl.glfw.GLFW.glfwGetTime;
+
+/**
+ *
+ */
+public class ObjectGl {
+
+ /**
+ * STATE CONST DECLARATION
+ */
+ public static final int DEFAULT = 0, STICK_BOTTOM = 1, STICK_TOP = 2;
+
+ private int stick_state;
+
+ protected VertexArray vertexArray;
+ protected Shader shader;
+ protected Matrix4f transform;
+
+ /**
+ * Projection and view matrix are set by the engine do not modify
+ */
+ public static Matrix4f projection;
+ public static Matrix4f view;
+
+ private float zPos;
+ private float width; // To be used in setTextureWrap
+ private float height;
+ private float scalingFactor;
+
+ public boolean useTime;
+
+ private Texture texture;
+
+ /**
+ * Create a rectangle shape, use setTextureWrap to correctly align the texture with the model
+ * @param z depth of your model the larger it is the more it will be "close" to the camera
+ * @param w height of the rectangle
+ * @param h width of the rectangle
+ * @param size scaling factor of the rectangle, the model could not show up because this value is too small or too large, a good compromise is between 2 and 15
+ * @param tex set to null if you don't want a tex on your model
+ * @param color set to null if you don't want a Color on your model
+ */
+ public ObjectGl(float z, float w, float h, float size, String tex, Vector3f color){
+ float[] colorBuffer = null;
+ // Check des options
+ if (color != null){
+ colorBuffer = new float[] {
+ color.x, color.y, color.z,
+ color.x, color.y, color.z,
+ color.x, color.y, color.z,
+ color.x, color.y, color.z
+ };
+ }
+
+ if (tex != null){
+ this.texture = new Texture(tex, 0);
+ }
+
+ this.zPos = z;
+ this.height = h;
+ this.width = w;
+
+ this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
+
+ this.scalingFactor = size;
+ this.transform = Matrix4f.identity();
+ this.scale(new Vector3f(size, size,1f));
+ this.stick_state = DEFAULT;
+ this.useTime = false;
+
+ // use different shader for each set of option
+ if (tex == null && color == null){
+ this.shader = new Shader("shaders/ObjectGl/vert.glsl","shaders/ObjectGl/frag.glsl");
+ } else if (tex == null){
+ this.shader = new Shader("shaders/ObjectGlColor/vert.glsl","shaders/ObjectGlColor/frag.glsl");
+ } else if (color == null){
+ this.shader = new Shader("shaders/ObjectGlTex/vert.glsl","shaders/ObjectGlTex/frag.glsl");
+ } else {
+ this.shader = new Shader("shaders/ObjectGlTexColor/vert.glsl","shaders/ObjectGlTexColor/frag.glsl");
+ }
+ }
+
+ /**
+ * Reset the transform matrix, the model will appear at the 0.0.0 coordinate, his scaleFactor will be set to zero
+ * Because the model is at position 0 on the z axis he will not show up on screen
+ */
+ public void resetTransform(){
+ this.transform = Matrix4f.identity();
+ this.scalingFactor = 1;
+ }
+
+ /**
+ * Move the object according to vec, direction can change if rotation method have been used
+ * @param vec Vector3f
+ */
+ public void translate(Vector3f vec){
+ vec.divXY(this.scalingFactor);
+ this.transform = this.transform.multiply(Matrix4f.translate(vec));
+ this.zPos += vec.z;
+ }
+
+ /**
+ * Scale the model with the vec vector, the x component is used to mitigate size modification in the behavior of other transformation method
+ * @param vec Vector3f
+ */
+ public void scale(Vector3f vec){
+ this.scalingFactor *= vec.x;
+ this.transform = this.transform.multiply(Matrix4f.scale(vec));
+ }
+
+ /**
+ * rotate the model by angle degree on the local x axis, beware this will change the behavior of the translate method
+ * @param angle in degree
+ */
+ public void rotateX(float angle){
+ this.transform = this.transform.multiply(Matrix4f.rotateX(angle));
+ }
+
+ /**
+ * rotate the model by angle degree on the local y axis, beware this will change the behavior of the translate method
+ * @param angle in degree
+ */
+ public void rotateY(float angle){
+ this.transform = this.transform.multiply(Matrix4f.rotateY(angle));
+ }
+
+ /**
+ * rotate the model by angle degree on the local z axis, beware this will change the behavior of the translate method
+ * @param angle in degree
+ */
+ public void rotateZ(float angle){
+ this.transform = this.transform.multiply(Matrix4f.rotateZ(angle));
+ }
+
+ /**
+ * Set a new texture to be used on the model. You may need to use setTextureWrap tp get the correct wrap
+ * @param texPath path to the new texture
+ */
+ public void setTexture(String texPath){
+ this.texture = new Texture(texPath, 0);
+ }
+
+ /**
+ * Change the wrapping coordinate
+ * @param x starting wrapping on the horizontal axis
+ * @param y starting wrapping on the vertical axis
+ * @param w the length of the wrapping on the horizontal axis
+ * @param h the length of the wrapping on the vertical axis
+ */
+ public void setTextureWrap(float x, float y, float w, float h, int sticky){
+ // TODO set sticky property + precision issue
+ if (this.stick_state != sticky){ // Check if we're using a new dimension
+ if (sticky == STICK_BOTTOM){
+ this.stick_state = STICK_BOTTOM;
+ this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
+ } else if (sticky == STICK_TOP){
+ this.stick_state = STICK_TOP;
+ this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
+ } else {
+ this.stick_state = DEFAULT;
+ }
+ }
+ this.height = h;
+ this.width = w;
+ this.vertexArray.swapVertexBufferObject(Primitive.createRectangle(this.zPos, w, h));
+ int texWidth = this.texture.getWidth();
+ int texHeight = this.texture.getHeight();
+ x /= texWidth;
+ w /= texWidth;
+ y /= texHeight;
+ h /= texHeight;
+ float[] result = {
+ x , y ,
+ x + w , y ,
+ x + w , y + h ,
+ x , y + h ,
+ };
+ this.setTextureWrap(result);
+ }
+
+ /**
+ * Set a new shader to be used by this object
+ * @param vert path to glsl Vertex Shader
+ * @param frag path to glsl Fragment Shader
+ */
+ public void setShader(String vert, String frag){
+ this.shader = new Shader(vert, frag);
+ }
+
+ /**
+ * Set a new Color for the object if the shader do not use the color attrib this will make no change.
+ * @param color Vector3f r,g,b format
+ */
+ public void setColor(Vector3f color){
+ float[] colorBuffer = new float[] {
+ color.x, color.y, color.z,
+ color.x, color.y, color.z,
+ color.x, color.y, color.z,
+ color.x, color.y, color.z
+ };
+ this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
+ }
+
+ private void setTextureWrap(float[] texture){
+ this.vertexArray.swapTextureBufferObject(texture);
+ }
+
+ public float getZPos(){
+ return zPos;
+ }
+
+ /**
+ * Do shader binding, texture binding and vertexArray drawing
+ */
+ public void render(){
+
+ this.shader.enable();
+ if (this.texture != null) this.texture.bind();
+
+ if (this.useTime) this.shader.setUniform1f("time", (float) glfwGetTime());
+
+ this.shader.setUniformMat4f("projection", projection);
+ this.shader.setUniformMat4f("view", view);
+ this.shader.setUniformMat4f("transform", this.transform);
+
+ this.vertexArray.render();
+
+ if (this.texture != null) this.texture.unbind();
+ this.shader.disable();
+ }
+
+}
diff --git a/src/engine/object/SortZ.java b/src/engine/object/SortZ.java
new file mode 100644
index 0000000..5b9cd33
--- /dev/null
+++ b/src/engine/object/SortZ.java
@@ -0,0 +1,11 @@
+package engine.object;
+
+import java.util.Comparator;
+
+public class SortZ implements Comparator
+{
+ public int compare(ObjectGl a, ObjectGl b)
+ {
+ return (int) (a.getZPos() - b.getZPos());
+ }
+}
\ No newline at end of file
diff --git a/src/engine/utils/BufferUtils.java b/src/engine/utils/BufferUtils.java
new file mode 100644
index 0000000..d420b8e
--- /dev/null
+++ b/src/engine/utils/BufferUtils.java
@@ -0,0 +1,32 @@
+package engine.utils;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+public class BufferUtils {
+
+ private BufferUtils() {
+
+ }
+
+ public static ByteBuffer createByteBuffer(byte[] array){
+ ByteBuffer result = ByteBuffer.allocateDirect(array.length).order(ByteOrder.nativeOrder());
+ result.put(array).flip();
+ return result;
+ }
+
+ public static FloatBuffer createFloatBuffer(float[] array){
+ FloatBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ result.put(array).flip();
+ return result;
+ }
+
+ public static IntBuffer createIntBuffer(int[] array){
+ IntBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
+ result.put(array).flip();
+ return result;
+ }
+
+}
diff --git a/src/engine/utils/FileUtils.java b/src/engine/utils/FileUtils.java
new file mode 100644
index 0000000..4f82877
--- /dev/null
+++ b/src/engine/utils/FileUtils.java
@@ -0,0 +1,29 @@
+package engine.utils;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class FileUtils {
+
+ private FileUtils() {
+
+ }
+
+ public static String loadAsString(String file){
+ StringBuilder result = new StringBuilder();
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(file));
+ String buffer = "";
+ while ((buffer = reader.readLine()) != null) {
+ result.append(buffer +"\n");
+ }
+ reader.close();
+ } catch (IOException e){
+ e.printStackTrace();
+ }
+ return result.toString();
+ }
+
+}
diff --git a/src/engine/utils/ShaderUtils.java b/src/engine/utils/ShaderUtils.java
new file mode 100644
index 0000000..69879ba
--- /dev/null
+++ b/src/engine/utils/ShaderUtils.java
@@ -0,0 +1,60 @@
+package engine.utils;
+
+import engine.utils.FileUtils;
+
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL20.*;
+
+public class ShaderUtils {
+
+ private ShaderUtils(){
+
+ }
+
+ public static int load(String vertPath, String fragPath){
+ String vert = FileUtils.loadAsString(vertPath);
+ String frag = FileUtils.loadAsString(fragPath);
+ return create(vert, frag);
+ }
+
+ public static int create(String vert, String frag){
+ // On crée et compile le vertex et le fragment shader
+ int vertID = glCreateShader(GL_VERTEX_SHADER);
+ int fragID = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(vertID, vert);
+ glShaderSource(fragID, frag);
+
+ glCompileShader(vertID);
+ if (glGetShaderi(vertID, GL_COMPILE_STATUS) == GL_FALSE){
+ System.err.println("Failed to compile vertex shader");
+ System.err.println(glGetShaderInfoLog(vertID));
+ return -1;
+ }
+
+ glCompileShader(fragID);
+ if (glGetShaderi(fragID, GL_COMPILE_STATUS) == GL_FALSE){
+ System.err.println("Failed to compile fragment shader");
+ System.err.println(glGetShaderInfoLog(fragID));
+ return -1;
+ }
+ //on lie les shaders au programme
+ int program = glCreateProgram();
+ glAttachShader(program, vertID);
+ glAttachShader(program, fragID);
+ glLinkProgram(program);
+
+ if(glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) {
+ System.err.println("Failed to link vertex and fragment shader");
+ System.err.println(glGetShaderInfoLog(program));
+ return -1;
+ }
+
+ glValidateProgram(program);
+
+ glDeleteShader(vertID);
+ glDeleteShader(fragID);
+
+ return program;
+ }
+
+}
diff --git a/textures/awesomeface.png b/textures/awesomeface.png
new file mode 100644
index 0000000..c7bfec6
Binary files /dev/null and b/textures/awesomeface.png differ
diff --git a/textures/container.jpg b/textures/container.jpg
new file mode 100644
index 0000000..d07bee4
Binary files /dev/null and b/textures/container.jpg differ
diff --git a/textures/zangief_sprite.png b/textures/zangief_sprite.png
new file mode 100644
index 0000000..862b9fb
Binary files /dev/null and b/textures/zangief_sprite.png differ