From 4f8a32d5a447414735ab56e93fe5a3feba3db736 Mon Sep 17 00:00:00 2001 From: Antoine Date: Sat, 29 May 2021 02:49:33 +0200 Subject: [PATCH 01/32] SoundManager update --- src/engine/Engine.java | 26 ++++++++++- src/engine/sound/SoundManager.java | 69 ++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 342552d..7eb9a04 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -2,6 +2,7 @@ package engine; import engine.math.*; import engine.object.*; +import engine.sound.*; import org.lwjgl.glfw.GLFWFramebufferSizeCallback; import org.lwjgl.glfw.GLFWVidMode; @@ -158,7 +159,27 @@ public class Engine { } }; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { + /* + OpenAl TEST + */ + SoundManager soundManager = new SoundManager(); + soundManager.init(); + + SoundListener soundListener = new SoundListener(); + + soundManager.setListener(soundListener); + +// SoundBuffer jumpSoundBuffer = new SoundBuffer("sound/jump.ogg"); EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff893802818, pid=1788, tid=4548 +// SoundSource soundSource = new SoundSource(true, false); +// soundSource.setBuffer(jumpSoundBuffer.getBufferId()); +// +// soundManager.addSoundSource("jump", soundSource); +// soundManager.playSoundSource("jump"); + + /* + Engine Init + */ Engine engine = new Engine(1280, 720, 9.0f / 16.0f); int speed = 10; //vitesse déplacement Object engine.init(); @@ -219,5 +240,8 @@ public class Engine { nextFrame = false; if (engine.shouldClose()) engine.setRunning(false); } + + soundManager.cleanup(); + } } diff --git a/src/engine/sound/SoundManager.java b/src/engine/sound/SoundManager.java index a087be8..45cb69c 100644 --- a/src/engine/sound/SoundManager.java +++ b/src/engine/sound/SoundManager.java @@ -1,6 +1,9 @@ +// Source : https://github.com/lwjglgamedev/lwjglbook/blob/master/chapter28/src/main/java/org/lwjglb/engine/sound/SoundManager.java + package engine.sound; import engine.math.Matrix4f; +import engine.math.Vector3f; import org.lwjgl.openal.*; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -9,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.lwjgl.openal.AL10.*; import static org.lwjgl.openal.ALC10.*; import static org.lwjgl.system.MemoryUtil.NULL; @@ -46,4 +50,69 @@ public class SoundManager { alcMakeContextCurrent(context); AL.createCapabilities(deviceCaps); } + + public void addSoundSource(String name, SoundSource soundSource) { + this.soundSourceMap.put(name, soundSource); + } + + public SoundSource getSoundSource(String name) { + return this.soundSourceMap.get(name); + } + + public void playSoundSource(String name) { + SoundSource soundSource = this.soundSourceMap.get(name); + if (soundSource != null && !soundSource.isPlaying()) { + soundSource.play(); + } + } + + public void removeSoundSource(String name) { + this.soundSourceMap.remove(name); + } + + public void addSoundBuffer(SoundBuffer soundBuffer) { + this.soundBufferList.add(soundBuffer); + } + + public SoundListener getListener() { + return this.listener; + } + + public void setListener(SoundListener listener) { + this.listener = listener; + } + +// Camera Statique de notre côté pas besoin de "corriger" cette fonction +// public void updateListenerPosition(Camera camera) { +// // Update camera matrix with camera data +// Transformation.updateGenericViewMatrix(camera.getPosition(), camera.getRotation(), cameraMatrix); +// +// listener.setPosition(camera.getPosition()); +// Vector3f at = new Vector3f(); +// cameraMatrix.positiveZ(at).negate(); +// Vector3f up = new Vector3f(); +// cameraMatrix.positiveY(up); +// listener.setOrientation(at, up); +// } + + public void setAttenuationModel(int model) { + alDistanceModel(model); + } + + public void cleanup() { + for (SoundSource soundSource : soundSourceMap.values()) { + soundSource.cleanup(); + } + soundSourceMap.clear(); + for (SoundBuffer soundBuffer : soundBufferList) { + soundBuffer.cleanup(); + } + soundBufferList.clear(); + if (context != NULL) { + alcDestroyContext(context); + } + if (device != NULL) { + alcCloseDevice(device); + } + } } From 09562c42160f93d29e5ec93c95ca6388ef7399c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Sun, 30 May 2021 19:06:15 +0200 Subject: [PATCH 02/32] added input package test for control binding --- .classpath | 36 +++++++++++++++++-------------- src/engine/Engine.java | 21 ++++++++++++------ src/engine/{ => input}/Input.java | 7 +++--- 3 files changed, 38 insertions(+), 26 deletions(-) rename src/engine/{ => input}/Input.java (96%) diff --git a/.classpath b/.classpath index 675385c..3c22bac 100644 --- a/.classpath +++ b/.classpath @@ -1,16 +1,20 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 7eb9a04..8198830 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -1,9 +1,12 @@ package engine; +import engine.input.Input; +import engine.input.gamepadInput; import engine.math.*; import engine.object.*; import engine.sound.*; + import org.lwjgl.glfw.GLFWFramebufferSizeCallback; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; @@ -21,7 +24,7 @@ public class Engine { private final List objectsGl; - private static boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); + private boolean running; @@ -61,8 +64,8 @@ public class Engine { this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL)); assert getWindow() != NULL; - - System.out.println(present); + boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); + System.out.println("Manette détectée : " + present); // On récupère les informations du moniteur principal GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); @@ -205,14 +208,20 @@ public class Engine { long lastFrame; int frame = 0; boolean nextFrame = false; + boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); + + int buttonA=0; + int buttonB=1; + int buttonX=3; + int buttonY=4; while (engine.isRunning()) { lastFrame = System.currentTimeMillis(); // Game logic should fit here - if (present) { - Input.gamepadInput(zangief, speed); - } + if (present) { + gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); + } Input.keyboardInput(zangief, speed); // input(smiley2, speed); diff --git a/src/engine/Input.java b/src/engine/input/Input.java similarity index 96% rename from src/engine/Input.java rename to src/engine/input/Input.java index 8d88645..e734f2d 100644 --- a/src/engine/Input.java +++ b/src/engine/input/Input.java @@ -1,5 +1,6 @@ -package engine; +package engine.input; +import engine.Engine; import engine.math.Vector3f; import engine.object.ObjectGl; import org.lwjgl.glfw.GLFW; @@ -38,9 +39,7 @@ public class Input extends GLFWKeyCallback { 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) From fbd690f4275af2f3a42548769c53d9bcda2eb75e Mon Sep 17 00:00:00 2001 From: Indy Date: Mon, 31 May 2021 12:25:39 +0200 Subject: [PATCH 03/32] update pom + reso json --- pom.xml | 73 ++++++++++++++++++++--------------- src/configuration/config.json | 11 ++++++ 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 4c4995f..12d77b7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,28 +1,30 @@ - - + + 4.0.0 - + jeu-de-combat jeu-de-combat 0.0.1-SNAPSHOT Boulevard Combattant Jeu de combat inspiré de Street Fighter 3: Third Strike. Projet de fin d'année de L3. https://gitlab.istic.univ-rennes1.fr/fautin/jeu-de-combat - + - + src - + - + src/launcher/ui - + - + - + maven-compiler-plugin 3.8.1 @@ -30,21 +32,21 @@ 11 - + - + - + - + 3.2.3 natives-windows 11 - + - + org.lwjgl @@ -54,92 +56,99 @@ pom - + - + org.lwjgl lwjgl - + org.lwjgl lwjgl-assimp - + org.lwjgl lwjgl-glfw - + org.lwjgl lwjgl-openal - + org.lwjgl lwjgl-opengl - + org.lwjgl lwjgl-stb - + org.lwjgl lwjgl ${lwjgl.natives} - + org.lwjgl lwjgl-assimp ${lwjgl.natives} - + org.lwjgl lwjgl-glfw ${lwjgl.natives} - + org.lwjgl lwjgl-openal ${lwjgl.natives} - + org.lwjgl lwjgl-opengl ${lwjgl.natives} - + org.lwjgl lwjgl-stb ${lwjgl.natives} - - + + org.openjfx javafx-controls ${javafx.version} - + org.openjfx javafx-fxml ${javafx.version} + + + org.json + json + 20210307 + + \ No newline at end of file diff --git a/src/configuration/config.json b/src/configuration/config.json index 028c17f..4c4b7fd 100644 --- a/src/configuration/config.json +++ b/src/configuration/config.json @@ -1,4 +1,5 @@ { + "test": "test valide", "arena": [ "arena1.png", "arena2.png", @@ -25,5 +26,15 @@ "1680 x 1050", "1920 x 1080", "800 x 600" + ], + "button": [ + "up", + "down", + "rigth", + "left", + "a", + "b", + "c", + "d" ] } From f2b2fa9e9bf687e549bce535c05cc2854657d0b1 Mon Sep 17 00:00:00 2001 From: Indy Date: Mon, 31 May 2021 15:01:39 +0200 Subject: [PATCH 04/32] parser json to java --- src/configuration/JsonToJava.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/configuration/JsonToJava.java diff --git a/src/configuration/JsonToJava.java b/src/configuration/JsonToJava.java new file mode 100644 index 0000000..5f2961b --- /dev/null +++ b/src/configuration/JsonToJava.java @@ -0,0 +1,23 @@ +package configuration; + +import java.io.*; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +public class JsonToJava { + public static void main(String args[]) { + JSONParser jsonP = new JSONParser(); + try { + JSONObject jsonO = (JSONObject)jsonP.parse(new FileReader("src/configuration/config.json")); + + String test = (String) jsonO.get("test"); + System.out.println("Name :"+ test); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file From 888e5825ba1877a15aaab22d2bf78e52acecfa95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Mon, 31 May 2021 15:36:40 +0200 Subject: [PATCH 05/32] added gamepadInputClass --- src/engine/Engine.java | 9 ++-- src/engine/input/Input.java | 10 ++-- src/engine/input/gamepadInput.java | 76 ++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 src/engine/input/gamepadInput.java diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 8198830..8401f7f 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -24,7 +24,7 @@ public class Engine { private final List objectsGl; - + private final static int buttonA=0, buttonB=1, buttonX=3, buttonY=4; private boolean running; @@ -210,16 +210,13 @@ public class Engine { boolean nextFrame = false; boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); - int buttonA=0; - int buttonB=1; - int buttonX=3; - int buttonY=4; + while (engine.isRunning()) { lastFrame = System.currentTimeMillis(); // Game logic should fit here - if (present) { + if (present) { //sprite //bindings gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); } diff --git a/src/engine/input/Input.java b/src/engine/input/Input.java index e734f2d..9af2b1e 100644 --- a/src/engine/input/Input.java +++ b/src/engine/input/Input.java @@ -15,6 +15,7 @@ import static org.lwjgl.opengl.GL11.*; public class Input extends GLFWKeyCallback { public static boolean[] keys = new boolean[65536]; + public static boolean keyPressed = false; @Override public void invoke(long window, int key, int scancode, int action, int mods) { @@ -37,9 +38,6 @@ public class Input extends GLFWKeyCallback { assert gamepadAxes != null; assert gamepadButton != null; - String name = GLFW.glfwGetJoystickName(GLFW_JOYSTICK_1); - System.out.println("GamePad Name :" + name); - if (gamepadButton.get(0) ==1 ) { // appuie sur croix(PlayStation) A (Xbox) @@ -48,9 +46,9 @@ public class Input extends GLFWKeyCallback { 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); + token.setTextureWrap(121,0,57,80, ObjectGl.STICK_TOP); }else if (gamepadAxes.get(2) > 0.1) { - token.setTextureWrap(178,0,62,82, ObjectGl.DEFAULT); + token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP); } } @@ -88,7 +86,7 @@ public class Input extends GLFWKeyCallback { } public static void keyboardInput(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; diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/gamepadInput.java new file mode 100644 index 0000000..da7818c --- /dev/null +++ b/src/engine/input/gamepadInput.java @@ -0,0 +1,76 @@ +package engine.input; + +import engine.math.Vector3f; +import engine.object.ObjectGl; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWKeyCallback; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.opengl.GL11.*; +/* 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 class gamepadInput{ + //à définir //à définir + public static void gamepadInput(ObjectGl token, int speed,int jump, int attack, int act3, int act4) { //to update for more controlBinding + ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); + FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); + + assert gamepadAxes != null; + assert gamepadButton != null; + + if (gamepadButton.get(jump)==1 ) { // appuie sur croix(PlayStation) A (Xbox) + jump( token,speed); + } + + if (gamepadButton.get(attack)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + attack( token,speed); + } + + if (gamepadAxes.get(3) > 0.1) { + crouch(token,speed); + } + + + } + + public static void jump(ObjectGl token,int speed) { + token.translate(new Vector3f( 0.0f, speed * 20.0f, 0.0f)); + + } + + public static void attack(ObjectGl token,int speed) { + + } + + public static void crouch(ObjectGl token,int speed) { + token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM); + } + +} From 00a19177c7657aea4cc322b8735cdbdc8d10568b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Mon, 31 May 2021 16:54:02 +0200 Subject: [PATCH 06/32] gamepadInput updated --- src/engine/Engine.java | 7 ++++- src/engine/input/gamepadInput.java | 47 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 8401f7f..536fa32 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -24,7 +24,7 @@ public class Engine { private final List objectsGl; - private final static int buttonA=0, buttonB=1, buttonX=3, buttonY=4; + private final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, L_JoystickClick = 8, R_JoystickClick =9, Up = 10, right = 11, down = 12, left = 13; private boolean running; @@ -218,6 +218,11 @@ public class Engine { if (present) { //sprite //bindings gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); + + System.out.println( " \n A :" + gamepadInput.buttonA_pressed + + " \n B :" + gamepadInput.buttonB_pressed + + " \n Y :" + gamepadInput.buttonY_pressed + + " \n X :" + gamepadInput.buttonX_pressed); } Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/gamepadInput.java index da7818c..6c44f13 100644 --- a/src/engine/input/gamepadInput.java +++ b/src/engine/input/gamepadInput.java @@ -37,40 +37,41 @@ import static org.lwjgl.opengl.GL11.*; */ public class gamepadInput{ + + public static boolean buttonA_pressed = false; + public static boolean buttonB_pressed = false; + public static boolean buttonY_pressed = false; + public static boolean buttonX_pressed = false; //à définir //à définir - public static void gamepadInput(ObjectGl token, int speed,int jump, int attack, int act3, int act4) { //to update for more controlBinding + public static void gamepadInput(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY) { //to update for more controlBinding ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); assert gamepadAxes != null; assert gamepadButton != null; - if (gamepadButton.get(jump)==1 ) { // appuie sur croix(PlayStation) A (Xbox) - jump( token,speed); - } + + + + if (gamepadButton.get(ButtonA)==1 ) { // appuie sur croix(PlayStation) A (Xbox) + buttonA_pressed = true; + }else buttonA_pressed = false; + + if (gamepadButton.get(ButtonB)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + buttonB_pressed = true; + }else buttonB_pressed = false; + + if (gamepadButton.get(ButtonY)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + buttonY_pressed = true; + }else buttonY_pressed = false; + + if (gamepadButton.get(ButtonX)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + buttonX_pressed = true; + }else buttonX_pressed = false; - if (gamepadButton.get(attack)==1 ) { // appuie sur rond(PlayStation) B (Xbox) - attack( token,speed); - } - if (gamepadAxes.get(3) > 0.1) { - crouch(token,speed); - } } - - public static void jump(ObjectGl token,int speed) { - token.translate(new Vector3f( 0.0f, speed * 20.0f, 0.0f)); - - } - - public static void attack(ObjectGl token,int speed) { - - } - - public static void crouch(ObjectGl token,int speed) { - token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM); - } } From bd587a55870c59681ba6ddc11605fc9ffa3a57cc Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 31 May 2021 18:45:38 +0200 Subject: [PATCH 07/32] SoundManager, SoundBuffer Fixed, BufferUtils.java rename to BufferUtilsEngine.java to avoid conflict with org.lwjgl.BufferUtils Le son fonctionne yay --- src/configuration/JsonToJava.java | 1 - src/engine/Engine.java | 17 +++++------ src/engine/graphics/Texture.java | 4 +-- src/engine/graphics/VertexArray.java | 14 +++++----- src/engine/input/Input.java | 10 ++++--- src/engine/math/Matrix4f.java | 4 +-- src/engine/sound/SoundBuffer.java | 10 +++---- ...ufferUtils.java => BufferUtilsEngine.java} | 11 ++++---- src/engine/utils/FileUtils.java | 28 +++++++++++++++---- 9 files changed, 59 insertions(+), 40 deletions(-) rename src/engine/utils/{BufferUtils.java => BufferUtilsEngine.java} (83%) diff --git a/src/configuration/JsonToJava.java b/src/configuration/JsonToJava.java index 5f2961b..c497b50 100644 --- a/src/configuration/JsonToJava.java +++ b/src/configuration/JsonToJava.java @@ -9,7 +9,6 @@ public class JsonToJava { JSONParser jsonP = new JSONParser(); try { JSONObject jsonO = (JSONObject)jsonP.parse(new FileReader("src/configuration/config.json")); - String test = (String) jsonO.get("test"); System.out.println("Name :"+ test); } catch (FileNotFoundException e) { diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 536fa32..5bd7717 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -1,6 +1,7 @@ package engine; import engine.input.Input; +//import engine.input.gamepadInput; import engine.input.gamepadInput; import engine.math.*; import engine.object.*; @@ -173,12 +174,12 @@ public class Engine { soundManager.setListener(soundListener); -// SoundBuffer jumpSoundBuffer = new SoundBuffer("sound/jump.ogg"); EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff893802818, pid=1788, tid=4548 -// SoundSource soundSource = new SoundSource(true, false); -// soundSource.setBuffer(jumpSoundBuffer.getBufferId()); -// -// soundManager.addSoundSource("jump", soundSource); -// soundManager.playSoundSource("jump"); + SoundBuffer jumpSoundBuffer = new SoundBuffer("sound/jump.ogg"); + SoundSource soundSource = new SoundSource(true, false); + soundSource.setBuffer(jumpSoundBuffer.getBufferId()); + + soundManager.addSoundSource("jump", soundSource); + soundManager.playSoundSource("jump"); /* Engine Init @@ -217,7 +218,7 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); + gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); System.out.println( " \n A :" + gamepadInput.buttonA_pressed + " \n B :" + gamepadInput.buttonB_pressed + @@ -225,7 +226,7 @@ public class Engine { " \n X :" + gamepadInput.buttonX_pressed); } - Input.keyboardInput(zangief, speed); +// Input.keyboardInput(zangief, speed); // input(smiley2, speed); /* diff --git a/src/engine/graphics/Texture.java b/src/engine/graphics/Texture.java index 4f06db9..15e5a19 100644 --- a/src/engine/graphics/Texture.java +++ b/src/engine/graphics/Texture.java @@ -1,6 +1,6 @@ package engine.graphics; -import engine.utils.BufferUtils; +import engine.utils.BufferUtilsEngine; import org.lwjgl.opengl.GL11; import java.awt.image.BufferedImage; @@ -49,7 +49,7 @@ public class Texture { 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)); + GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, BufferUtilsEngine.createIntBuffer(data)); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); return result; diff --git a/src/engine/graphics/VertexArray.java b/src/engine/graphics/VertexArray.java index a8dc154..a3626be 100644 --- a/src/engine/graphics/VertexArray.java +++ b/src/engine/graphics/VertexArray.java @@ -1,6 +1,6 @@ package engine.graphics; -import engine.utils.BufferUtils; +import engine.utils.BufferUtilsEngine; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL15.*; @@ -28,7 +28,7 @@ public class VertexArray { EBO = glGenBuffers(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtilsEngine.createByteBuffer(indices), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); @@ -37,7 +37,7 @@ public class VertexArray { private void createVertexBufferObject(float[] vertices){ VBO = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, BufferUtilsEngine.createFloatBuffer(vertices), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); glEnableVertexAttribArray(0); } @@ -45,7 +45,7 @@ public class VertexArray { private void createColorBufferObject(float[] color){ CBO = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, CBO); - glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(color), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, BufferUtilsEngine.createFloatBuffer(color), GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); glEnableVertexAttribArray(1); } @@ -53,19 +53,19 @@ public class VertexArray { private void createTextureBufferObject(float[] texture){ TBO = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, TBO); - glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, BufferUtilsEngine.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); + glBufferData(GL_ARRAY_BUFFER, BufferUtilsEngine.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); + glBufferData(GL_ARRAY_BUFFER, BufferUtilsEngine.createFloatBuffer(texture), GL_STATIC_DRAW); } public void bind(){ diff --git a/src/engine/input/Input.java b/src/engine/input/Input.java index 9af2b1e..e734f2d 100644 --- a/src/engine/input/Input.java +++ b/src/engine/input/Input.java @@ -15,7 +15,6 @@ import static org.lwjgl.opengl.GL11.*; public class Input extends GLFWKeyCallback { public static boolean[] keys = new boolean[65536]; - public static boolean keyPressed = false; @Override public void invoke(long window, int key, int scancode, int action, int mods) { @@ -38,6 +37,9 @@ public class Input extends GLFWKeyCallback { assert gamepadAxes != null; assert gamepadButton != null; + String name = GLFW.glfwGetJoystickName(GLFW_JOYSTICK_1); + System.out.println("GamePad Name :" + name); + if (gamepadButton.get(0) ==1 ) { // appuie sur croix(PlayStation) A (Xbox) @@ -46,9 +48,9 @@ public class Input extends GLFWKeyCallback { 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.STICK_TOP); + token.setTextureWrap(121,0,57,80, ObjectGl.DEFAULT); }else if (gamepadAxes.get(2) > 0.1) { - token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP); + token.setTextureWrap(178,0,62,82, ObjectGl.DEFAULT); } } @@ -86,7 +88,7 @@ public class Input extends GLFWKeyCallback { } public static void keyboardInput(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; diff --git a/src/engine/math/Matrix4f.java b/src/engine/math/Matrix4f.java index 6291eb9..d3d2388 100644 --- a/src/engine/math/Matrix4f.java +++ b/src/engine/math/Matrix4f.java @@ -1,6 +1,6 @@ package engine.math; -import engine.utils.BufferUtils; +import engine.utils.BufferUtilsEngine; import java.nio.FloatBuffer; @@ -117,7 +117,7 @@ public class Matrix4f { } public FloatBuffer toFloatBuffer() { - return BufferUtils.createFloatBuffer(elements); + return BufferUtilsEngine.createFloatBuffer(elements); } } diff --git a/src/engine/sound/SoundBuffer.java b/src/engine/sound/SoundBuffer.java index 01cfa03..cfe1640 100644 --- a/src/engine/sound/SoundBuffer.java +++ b/src/engine/sound/SoundBuffer.java @@ -5,6 +5,7 @@ package engine.sound; +import engine.utils.FileUtils; import org.lwjgl.stb.STBVorbisInfo; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; @@ -13,7 +14,6 @@ import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; -import static engine.utils.BufferUtils.StringToByteBuffer; import static org.lwjgl.openal.AL10.*; import static org.lwjgl.stb.STBVorbis.*; import static org.lwjgl.system.MemoryUtil.NULL; @@ -56,19 +56,19 @@ public class SoundBuffer { /** * Source : https://github.com/lwjglgamedev/lwjglbook/blob/master/chapter28/src/main/java/org/lwjglb/engine/sound/SoundBuffer.java * lis un fichier .ogg et le convertis en .pcm seul format lisible par openAl - * @param resource le fichier .ogg + * @param path chemin vers un fichier .ogg * @param info STBVorbisInfo * @return pcm * @throws Exception MemoryStack.stackPush() */ - private ShortBuffer readVorbis(String resource, STBVorbisInfo info) throws Exception { + private ShortBuffer readVorbis(String path, STBVorbisInfo info) throws Exception { try (MemoryStack stack = MemoryStack.stackPush()) { - vorbis = StringToByteBuffer(resource); + this.vorbis = FileUtils.loadAsByteBuffer(path); IntBuffer error = stack.mallocInt(1); long decoder = stb_vorbis_open_memory(vorbis, error, null); if (decoder == NULL) { throw new RuntimeException("Failed to open Ogg Vorbis file. Error: " + error.get(0)); - } + } //Failed to open Ogg Vorbis file. Error: 30 / 34 stb_vorbis_get_info(decoder, info); diff --git a/src/engine/utils/BufferUtils.java b/src/engine/utils/BufferUtilsEngine.java similarity index 83% rename from src/engine/utils/BufferUtils.java rename to src/engine/utils/BufferUtilsEngine.java index 50a2ddb..14ccc53 100644 --- a/src/engine/utils/BufferUtils.java +++ b/src/engine/utils/BufferUtilsEngine.java @@ -1,13 +1,16 @@ package engine.utils; +import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.nio.channels.FileChannel; -public class BufferUtils { +public class BufferUtilsEngine { - private BufferUtils() { + private BufferUtilsEngine() { } @@ -29,8 +32,4 @@ public class BufferUtils { return result; } - public static ByteBuffer StringToByteBuffer(String msg){ - return ByteBuffer.wrap(msg.getBytes()); - } - } diff --git a/src/engine/utils/FileUtils.java b/src/engine/utils/FileUtils.java index 4f82877..13d8017 100644 --- a/src/engine/utils/FileUtils.java +++ b/src/engine/utils/FileUtils.java @@ -1,9 +1,13 @@ package engine.utils; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; +import org.lwjgl.BufferUtils; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class FileUtils { @@ -17,13 +21,27 @@ public class FileUtils { BufferedReader reader = new BufferedReader(new FileReader(file)); String buffer = ""; while ((buffer = reader.readLine()) != null) { - result.append(buffer +"\n"); + result.append(buffer).append("\n"); } reader.close(); } catch (IOException e){ e.printStackTrace(); + System.exit(1); } return result.toString(); } + public static ByteBuffer loadAsByteBuffer(String file) throws IOException{ + ByteBuffer buffer; + + Path path = Paths.get(file); + + try (SeekableByteChannel fc = Files.newByteChannel(path)) { + buffer = BufferUtils.createByteBuffer((int) fc.size() + 1); + while (fc.read(buffer) != -1) ; + } + + buffer.flip(); + return buffer; + } } From db05036c014080b6af2370dfece0f1b67c224dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Mon, 31 May 2021 19:09:07 +0200 Subject: [PATCH 08/32] detection of all gamepad buttons (except RT LT) --- src/engine/Engine.java | 2 +- src/engine/input/gamepadInput.java | 78 +++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 5bd7717..32c5061 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -218,7 +218,7 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - gamepadInput.gamepadInput(zangief, speed, buttonA, buttonB, buttonX, buttonY); + gamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start ,L_JoystickClick , R_JoystickClick , Up , right , down , left); System.out.println( " \n A :" + gamepadInput.buttonA_pressed + " \n B :" + gamepadInput.buttonB_pressed + diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/gamepadInput.java index 6c44f13..6f99326 100644 --- a/src/engine/input/gamepadInput.java +++ b/src/engine/input/gamepadInput.java @@ -42,34 +42,96 @@ public class gamepadInput{ public static boolean buttonB_pressed = false; public static boolean buttonY_pressed = false; public static boolean buttonX_pressed = false; - //à définir //à définir - public static void gamepadInput(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY) { //to update for more controlBinding + + public static boolean LB_pressed = false; + public static boolean RB_pressed = false; + + public static boolean select_pressed = false; + public static boolean start_pressed = false; + + public static boolean R_JoyClick_pressed = false; + public static boolean L_JoyClick_pressed = false; + + public static boolean up_pressed = false; + public static boolean down_pressed = false; + public static boolean left_pressed = false; + public static boolean right_pressed = false; + + public static void gamepad(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , int select , int start ,int L_JoyClick ,int R_JoyClick ,int Up ,int right ,int down , int left) { //to update for more controlBinding ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); assert gamepadAxes != null; assert gamepadButton != null; - - - if (gamepadButton.get(ButtonA)==1 ) { // appuie sur croix(PlayStation) A (Xbox) + // A B X Y + if (gamepadButton.get(ButtonA)==1 ) { buttonA_pressed = true; }else buttonA_pressed = false; - if (gamepadButton.get(ButtonB)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + if (gamepadButton.get(ButtonB)==1 ) { buttonB_pressed = true; }else buttonB_pressed = false; - if (gamepadButton.get(ButtonY)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + if (gamepadButton.get(ButtonY)==1 ) { buttonY_pressed = true; }else buttonY_pressed = false; - if (gamepadButton.get(ButtonX)==1 ) { // appuie sur rond(PlayStation) B (Xbox) + if (gamepadButton.get(ButtonX)==1 ) { buttonX_pressed = true; }else buttonX_pressed = false; + // LB RB + if (gamepadButton.get(LB)==1 ) { + LB_pressed = true; + }else LB_pressed = false; + if (gamepadButton.get(RB)==1 ) { + RB_pressed = true; + }else RB_pressed = false; + + + //start select + if (gamepadButton.get(start)==1 ) { + start_pressed = true; + }else start_pressed = false; + + if (gamepadButton.get(select)==1 ) { + select_pressed = true; + }else select_pressed = false; + + + //R & L JoystickClick + if (gamepadButton.get(R_JoyClick)==1 ) { + R_JoyClick_pressed = true; + }else R_JoyClick_pressed = false; + if (gamepadButton.get(L_JoyClick)==1 ) { + L_JoyClick_pressed = true; + }else L_JoyClick_pressed = false; + + + //up, down, left, right + if (gamepadButton.get(select)==1 ) { + up_pressed = true; + }else up_pressed = false; + + if (gamepadButton.get(select)==1 ) { + down_pressed = true; + }else down_pressed = false; + + if (gamepadButton.get( left)==1 ) { + left_pressed = true; + }else left_pressed = false; + + if (gamepadButton.get(right)==1 ) { + right_pressed = true; + }else right_pressed = false; + + + + + } From ccdbbfb2799b11041234caa38627e7fe0e479fbe Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 31 May 2021 19:39:11 +0200 Subject: [PATCH 09/32] Son de test --- sound/jump.ogg | Bin 0 -> 8494 bytes sound/jump.wav | Bin 0 -> 47686 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 sound/jump.ogg create mode 100644 sound/jump.wav diff --git a/sound/jump.ogg b/sound/jump.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9a15e596589ba77ae2090f5ac9bb0fff06910c1a GIT binary patch literal 8494 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 literal 0 HcmV?d00001 From a069067c9c1bca9d6d92c9b96dd7df9c92775e58 Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 31 May 2021 19:48:42 +0200 Subject: [PATCH 10/32] Loop --- src/configuration/JsonToJava.java | 40 +++++++++++++++---------------- src/engine/Engine.java | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/configuration/JsonToJava.java b/src/configuration/JsonToJava.java index c497b50..f9c927e 100644 --- a/src/configuration/JsonToJava.java +++ b/src/configuration/JsonToJava.java @@ -1,22 +1,22 @@ package configuration; -import java.io.*; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -public class JsonToJava { - public static void main(String args[]) { - JSONParser jsonP = new JSONParser(); - try { - JSONObject jsonO = (JSONObject)jsonP.parse(new FileReader("src/configuration/config.json")); - String test = (String) jsonO.get("test"); - System.out.println("Name :"+ test); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file +//import java.io.*; +//import org.json.simple.JSONObject; +//import org.json.simple.parser.JSONParser; +//import org.json.simple.parser.ParseException; +//public class JsonToJava { +// public static void main(String args[]) { +// JSONParser jsonP = new JSONParser(); +// try { +// JSONObject jsonO = (JSONObject)jsonP.parse(new FileReader("src/configuration/config.json")); +// String test = (String) jsonO.get("test"); +// System.out.println("Name :"+ test); +// } catch (FileNotFoundException e) { +// e.printStackTrace(); +// } catch (IOException e) { +// e.printStackTrace(); +// } catch (ParseException e) { +// e.printStackTrace(); +// } +// } +//} \ No newline at end of file diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 32c5061..497b607 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -175,7 +175,7 @@ public class Engine { soundManager.setListener(soundListener); SoundBuffer jumpSoundBuffer = new SoundBuffer("sound/jump.ogg"); - SoundSource soundSource = new SoundSource(true, false); + SoundSource soundSource = new SoundSource(false, false); soundSource.setBuffer(jumpSoundBuffer.getBufferId()); soundManager.addSoundSource("jump", soundSource); From 8d5d19dffd312cf59dd2abe282163e8bea038d0f Mon Sep 17 00:00:00 2001 From: Boyeau Indy Date: Mon, 31 May 2021 18:37:02 +0000 Subject: [PATCH 11/32] print json file --- src/configuration/JsonToJava.java | 76 ++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/configuration/JsonToJava.java b/src/configuration/JsonToJava.java index f9c927e..f0d0d8f 100644 --- a/src/configuration/JsonToJava.java +++ b/src/configuration/JsonToJava.java @@ -1,22 +1,54 @@ -package configuration; - -//import java.io.*; -//import org.json.simple.JSONObject; -//import org.json.simple.parser.JSONParser; -//import org.json.simple.parser.ParseException; -//public class JsonToJava { -// public static void main(String args[]) { -// JSONParser jsonP = new JSONParser(); -// try { -// JSONObject jsonO = (JSONObject)jsonP.parse(new FileReader("src/configuration/config.json")); -// String test = (String) jsonO.get("test"); -// System.out.println("Name :"+ test); -// } catch (FileNotFoundException e) { -// e.printStackTrace(); -// } catch (IOException e) { -// e.printStackTrace(); -// } catch (ParseException e) { -// e.printStackTrace(); -// } -// } -//} \ No newline at end of file +package configuration; + +import java.io.*; +import org.json.simple.*; +import org.json.simple.parser.*; + +public class JsonToJava { + + public static void main(String args[]) { + + // initialize the parser + JSONParser jsonP = new JSONParser(); + try { + // read the json document + JSONObject jsonO = (JSONObject) jsonP.parse(new FileReader("src/configuration/config.json")); + + //to print all values + //System.out.println(jsonO.values()); + + // isolate the "test" part and print it + // String test = (String) jsonO.get("test"); + // System.out.println("ceci est un test :" + test); + + + //select an element on the list + JSONArray arene = (JSONArray) jsonO.get("arena"); + //print a case of this element + System.out.println(arene.get(1)); + + JSONArray nb_players = (JSONArray) jsonO.get("nb_players"); + System.out.println(nb_players.get(1)); + + JSONArray character1 = (JSONArray) jsonO.get("character1"); + System.out.println(character1.get(1)); + + JSONArray character2 = (JSONArray) jsonO.get("character2"); + System.out.println(character2.get(1)); + + JSONArray resolution = (JSONArray) jsonO.get("resolution"); + System.out.println(resolution.get(1)); + + JSONArray button = (JSONArray) jsonO.get("button"); + System.out.println(button); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + + } + } +} From b6b0d2bbc8115d991b6ee9b011db306c741f0e1a Mon Sep 17 00:00:00 2001 From: Boyeau Indy Date: Mon, 31 May 2021 18:38:03 +0000 Subject: [PATCH 12/32] Update pom.xml (dependecy) --- pom.xml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 12d77b7..e07f740 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,9 @@ jeu-de-combat 0.0.1-SNAPSHOT Boulevard Combattant - Jeu de combat inspiré de Street Fighter 3: Third Strike. Projet de fin d'année de L3. + Jeu de combat inspiré de Street Fighter 3: Third Strike. + Projet de fin d'année de L3. + https://gitlab.istic.univ-rennes1.fr/fautin/jeu-de-combat @@ -141,14 +143,14 @@ javafx-fxml ${javafx.version} - - + + - org.json - json - 20210307 + com.googlecode.json-simple + json-simple + 1.1.1 - \ No newline at end of file + From 8682d99578c07d39cc2363bb5a8f588f9eab8d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Tue, 1 Jun 2021 15:53:04 +0200 Subject: [PATCH 13/32] detection of all of the inputs ( joysticks included) --- src/engine/Engine.java | 16 +++++--- src/engine/input/gamepadInput.java | 64 +++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 497b607..ee1372b 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -25,7 +25,9 @@ public class Engine { private final List objectsGl; - private final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, L_JoystickClick = 8, R_JoystickClick =9, Up = 10, right = 11, down = 12, left = 13; + private final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, + L_JoystickClick = 8, R_JoystickClick =9, Up = 10, right = 11, down = 12, left = 13, + leftJoyX_Axe = 0, leftJoyY_Axe = 1, rightJoyX_Axe = 2, rightJoyY_Axe = 3, LT = 4, RT = 5; private boolean running; @@ -218,12 +220,14 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - gamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start ,L_JoystickClick , R_JoystickClick , Up , right , down , left); + gamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , + L_JoystickClick , R_JoystickClick , Up , right , down , left, + leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); - System.out.println( " \n A :" + gamepadInput.buttonA_pressed + - " \n B :" + gamepadInput.buttonB_pressed + - " \n Y :" + gamepadInput.buttonY_pressed + - " \n X :" + gamepadInput.buttonX_pressed); + System.out.println( " \n left :" + gamepadInput.leftJoyLeft + + " \n right :" + gamepadInput.leftJoyRight + + " \n down :" + gamepadInput.leftJoyDown + + " \n up :" + gamepadInput.leftJoyUp); } // Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/gamepadInput.java index 6f99326..64d546b 100644 --- a/src/engine/input/gamepadInput.java +++ b/src/engine/input/gamepadInput.java @@ -56,8 +56,25 @@ public class gamepadInput{ public static boolean down_pressed = false; public static boolean left_pressed = false; public static boolean right_pressed = false; + + public static boolean leftJoyRight = false; + public static boolean leftJoyLeft = false; + public static boolean leftJoyDown = false; + public static boolean leftJoyUp = false; + + public static boolean rightJoyLeft = false; + public static boolean rightJoyRight = false; + public static boolean rightJoyDown = false; + public static boolean rightJoyUp = false; + + public static boolean LT_pressed = false; + public static boolean RT_pressed = false; + + - public static void gamepad(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , int select , int start ,int L_JoyClick ,int R_JoyClick ,int Up ,int right ,int down , int left) { //to update for more controlBinding + public static void gamepad(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , + int select , int start ,int L_JoyClick ,int R_JoyClick ,int up ,int right ,int down , int left, + int leftJoyX_Axe, int leftJoyY_Axe, int rightJoyX_Axe, int rightJoyY_Axe, int LT, int RT) { //to update for more controlBinding ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); @@ -69,15 +86,12 @@ public class gamepadInput{ if (gamepadButton.get(ButtonA)==1 ) { buttonA_pressed = true; }else buttonA_pressed = false; - if (gamepadButton.get(ButtonB)==1 ) { buttonB_pressed = true; }else buttonB_pressed = false; - if (gamepadButton.get(ButtonY)==1 ) { buttonY_pressed = true; }else buttonY_pressed = false; - if (gamepadButton.get(ButtonX)==1 ) { buttonX_pressed = true; }else buttonX_pressed = false; @@ -96,7 +110,6 @@ public class gamepadInput{ if (gamepadButton.get(start)==1 ) { start_pressed = true; }else start_pressed = false; - if (gamepadButton.get(select)==1 ) { select_pressed = true; }else select_pressed = false; @@ -112,25 +125,56 @@ public class gamepadInput{ //up, down, left, right - if (gamepadButton.get(select)==1 ) { + if (gamepadButton.get(up)==1 ) { up_pressed = true; }else up_pressed = false; - - if (gamepadButton.get(select)==1 ) { + if (gamepadButton.get(down)==1 ) { down_pressed = true; }else down_pressed = false; - if (gamepadButton.get( left)==1 ) { left_pressed = true; }else left_pressed = false; - if (gamepadButton.get(right)==1 ) { right_pressed = true; }else right_pressed = false; + //Left Joystick + if (gamepadAxes.get(leftJoyX_Axe)> 0.1 ) { + leftJoyRight = true; + }else leftJoyRight = false; + if (gamepadAxes.get(leftJoyX_Axe)<-0.1 ) { + leftJoyLeft = true; + }else leftJoyLeft = false; + if (gamepadAxes.get(leftJoyY_Axe)> 0.1 ) { + leftJoyDown = true; + }else leftJoyDown = false; + if (gamepadAxes.get(leftJoyY_Axe)<-0.1 ) { + leftJoyUp = true; + }else leftJoyUp = false; + //Right Joystick + if (gamepadAxes.get(rightJoyX_Axe)> 0.1 ) { + rightJoyRight = true; + }else rightJoyRight = false; + if (gamepadAxes.get(rightJoyX_Axe)<-0.1 ) { + rightJoyLeft = true; + }else rightJoyLeft = false; + if (gamepadAxes.get(rightJoyY_Axe)> 0.1 ) { + rightJoyDown = true; + }else rightJoyDown = false; + if (gamepadAxes.get(rightJoyY_Axe)<-0.1 ) { + rightJoyUp = true; + }else rightJoyUp = false; + + //LT RT + if (gamepadButton.get(LT)==1 ) { + LT_pressed = true; + }else LT_pressed = false; + if (gamepadButton.get(RT)==1 ) { + RT_pressed = true; + }else RT_pressed = false; From b276f1eca41e79318e21dd4b6bcdf00097ff3058 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 16:11:36 +0200 Subject: [PATCH 14/32] Simplification des conditionnels de gamepadInput.java --- src/engine/input/gamepadInput.java | 96 ++++++++---------------------- 1 file changed, 24 insertions(+), 72 deletions(-) diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/gamepadInput.java index 64d546b..b00e1a9 100644 --- a/src/engine/input/gamepadInput.java +++ b/src/engine/input/gamepadInput.java @@ -83,98 +83,50 @@ public class gamepadInput{ // A B X Y - if (gamepadButton.get(ButtonA)==1 ) { - buttonA_pressed = true; - }else buttonA_pressed = false; - if (gamepadButton.get(ButtonB)==1 ) { - buttonB_pressed = true; - }else buttonB_pressed = false; - if (gamepadButton.get(ButtonY)==1 ) { - buttonY_pressed = true; - }else buttonY_pressed = false; - if (gamepadButton.get(ButtonX)==1 ) { - buttonX_pressed = true; - }else buttonX_pressed = false; + buttonA_pressed = gamepadButton.get(ButtonA) == 1; + buttonB_pressed = gamepadButton.get(ButtonB) == 1; + buttonY_pressed = gamepadButton.get(ButtonY) == 1; + buttonX_pressed = gamepadButton.get(ButtonX) == 1; // LB RB - if (gamepadButton.get(LB)==1 ) { - LB_pressed = true; - }else LB_pressed = false; - if (gamepadButton.get(RB)==1 ) { - RB_pressed = true; - }else RB_pressed = false; + LB_pressed = gamepadButton.get(LB) == 1; + RB_pressed = gamepadButton.get(RB) == 1; //start select - if (gamepadButton.get(start)==1 ) { - start_pressed = true; - }else start_pressed = false; - if (gamepadButton.get(select)==1 ) { - select_pressed = true; - }else select_pressed = false; + start_pressed = gamepadButton.get(start) == 1; + select_pressed = gamepadButton.get(select) == 1; //R & L JoystickClick - if (gamepadButton.get(R_JoyClick)==1 ) { - R_JoyClick_pressed = true; - }else R_JoyClick_pressed = false; - if (gamepadButton.get(L_JoyClick)==1 ) { - L_JoyClick_pressed = true; - }else L_JoyClick_pressed = false; + R_JoyClick_pressed = gamepadButton.get(R_JoyClick) == 1; + L_JoyClick_pressed = gamepadButton.get(L_JoyClick) == 1; //up, down, left, right - if (gamepadButton.get(up)==1 ) { - up_pressed = true; - }else up_pressed = false; - if (gamepadButton.get(down)==1 ) { - down_pressed = true; - }else down_pressed = false; - if (gamepadButton.get( left)==1 ) { - left_pressed = true; - }else left_pressed = false; - if (gamepadButton.get(right)==1 ) { - right_pressed = true; - }else right_pressed = false; + up_pressed = gamepadButton.get(up) == 1; + down_pressed = gamepadButton.get(down) == 1; + left_pressed = gamepadButton.get(left) == 1; + right_pressed = gamepadButton.get(right) == 1; //Left Joystick - if (gamepadAxes.get(leftJoyX_Axe)> 0.1 ) { - leftJoyRight = true; - }else leftJoyRight = false; - if (gamepadAxes.get(leftJoyX_Axe)<-0.1 ) { - leftJoyLeft = true; - }else leftJoyLeft = false; - if (gamepadAxes.get(leftJoyY_Axe)> 0.1 ) { - leftJoyDown = true; - }else leftJoyDown = false; - if (gamepadAxes.get(leftJoyY_Axe)<-0.1 ) { - leftJoyUp = true; - }else leftJoyUp = false; + leftJoyRight = gamepadAxes.get(leftJoyX_Axe) > 0.1; + leftJoyLeft = gamepadAxes.get(leftJoyX_Axe) < -0.1; + leftJoyDown = gamepadAxes.get(leftJoyY_Axe) > 0.1; + leftJoyUp = gamepadAxes.get(leftJoyY_Axe) < -0.1; //Right Joystick - if (gamepadAxes.get(rightJoyX_Axe)> 0.1 ) { - rightJoyRight = true; - }else rightJoyRight = false; - if (gamepadAxes.get(rightJoyX_Axe)<-0.1 ) { - rightJoyLeft = true; - }else rightJoyLeft = false; - if (gamepadAxes.get(rightJoyY_Axe)> 0.1 ) { - rightJoyDown = true; - }else rightJoyDown = false; - if (gamepadAxes.get(rightJoyY_Axe)<-0.1 ) { - rightJoyUp = true; - }else rightJoyUp = false; + rightJoyRight = gamepadAxes.get(rightJoyX_Axe) > 0.1; + rightJoyLeft = gamepadAxes.get(rightJoyX_Axe) < -0.1; + rightJoyDown = gamepadAxes.get(rightJoyY_Axe) > 0.1; + rightJoyUp = gamepadAxes.get(rightJoyY_Axe) < -0.1; //LT RT - if (gamepadButton.get(LT)==1 ) { - LT_pressed = true; - }else LT_pressed = false; - if (gamepadButton.get(RT)==1 ) { - RT_pressed = true; - }else RT_pressed = false; + LT_pressed = gamepadButton.get(LT) == 1; + RT_pressed = gamepadButton.get(RT) == 1; From 6dcd7feda577d16ecd7ce0be49ba0950f58d9db2 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 17:59:04 +0200 Subject: [PATCH 15/32] GamepadInput --- src/engine/Engine.java | 12 ++++----- src/engine/input/Button.java | 26 +++++++++++++++++++ .../{gamepadInput.java => GamepadInput.java} | 4 +-- 3 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 src/engine/input/Button.java rename src/engine/input/{gamepadInput.java => GamepadInput.java} (95%) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index ee1372b..933c1e5 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -2,7 +2,7 @@ package engine; import engine.input.Input; //import engine.input.gamepadInput; -import engine.input.gamepadInput; +import engine.input.GamepadInput; import engine.math.*; import engine.object.*; import engine.sound.*; @@ -220,14 +220,14 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - gamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , + GamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , L_JoystickClick , R_JoystickClick , Up , right , down , left, leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); - System.out.println( " \n left :" + gamepadInput.leftJoyLeft + - " \n right :" + gamepadInput.leftJoyRight + - " \n down :" + gamepadInput.leftJoyDown + - " \n up :" + gamepadInput.leftJoyUp); + System.out.println( " \n left :" + GamepadInput.leftJoyLeft + + " \n right :" + GamepadInput.leftJoyRight + + " \n down :" + GamepadInput.leftJoyDown + + " \n up :" + GamepadInput.leftJoyUp); } // Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/Button.java b/src/engine/input/Button.java new file mode 100644 index 0000000..ccef189 --- /dev/null +++ b/src/engine/input/Button.java @@ -0,0 +1,26 @@ +package engine.input; + +import java.util.List; + +public class Button { + + public String name; + private final List buttons; + + public Button(String name, List buttons, GamepadInput controller){ + this.name = name; + this.buttons = buttons; + } + + public void addButton(int key){ + this.buttons.add(key); + } + + public boolean isButtonPressed(){ + for (int i : buttons){ + GamepadInput.checkPressed(i); + } + } + + +} diff --git a/src/engine/input/gamepadInput.java b/src/engine/input/GamepadInput.java similarity index 95% rename from src/engine/input/gamepadInput.java rename to src/engine/input/GamepadInput.java index b00e1a9..27c7662 100644 --- a/src/engine/input/gamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -36,7 +36,7 @@ import static org.lwjgl.opengl.GL11.*; 5: R2 /RT : 1 active, -1 unactive */ -public class gamepadInput{ +public class GamepadInput { public static boolean buttonA_pressed = false; public static boolean buttonB_pressed = false; @@ -128,8 +128,6 @@ public class gamepadInput{ LT_pressed = gamepadButton.get(LT) == 1; RT_pressed = gamepadButton.get(RT) == 1; - - } } From b63ee09571d13d4fef63d7dca34de94606d3eec8 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 18:04:33 +0200 Subject: [PATCH 16/32] Classe Button.java --- src/engine/Engine.java | 6 +++--- src/engine/input/Button.java | 9 ++++----- src/engine/input/GamepadInput.java | 23 +++++++++++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 933c1e5..78679a3 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -220,9 +220,9 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - GamepadInput.gamepad(zangief, speed, buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , - L_JoystickClick , R_JoystickClick , Up , right , down , left, - leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); + GamepadInput.inputRefresh(buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , + L_JoystickClick , R_JoystickClick , Up , right , down , left, + leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); System.out.println( " \n left :" + GamepadInput.leftJoyLeft + " \n right :" + GamepadInput.leftJoyRight + diff --git a/src/engine/input/Button.java b/src/engine/input/Button.java index ccef189..942b13f 100644 --- a/src/engine/input/Button.java +++ b/src/engine/input/Button.java @@ -6,20 +6,19 @@ public class Button { public String name; private final List buttons; + private final GamepadInput controller; public Button(String name, List buttons, GamepadInput controller){ this.name = name; this.buttons = buttons; - } - - public void addButton(int key){ - this.buttons.add(key); + this.controller = controller; } public boolean isButtonPressed(){ for (int i : buttons){ - GamepadInput.checkPressed(i); + if (controller.checkPressed(i)) return true; } + return false; } diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 27c7662..a8b4c94 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -1,15 +1,9 @@ package engine.input; -import engine.math.Vector3f; -import engine.object.ObjectGl; -import org.lwjgl.glfw.GLFW; -import org.lwjgl.glfw.GLFWKeyCallback; - import java.nio.ByteBuffer; import java.nio.FloatBuffer; import static org.lwjgl.glfw.GLFW.*; -import static org.lwjgl.opengl.GL11.*; /* Buttons 0 : Croix / A 1: rond /B @@ -72,9 +66,9 @@ public class GamepadInput { - public static void gamepad(ObjectGl token, int speed,int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , - int select , int start ,int L_JoyClick ,int R_JoyClick ,int up ,int right ,int down , int left, - int leftJoyX_Axe, int leftJoyY_Axe, int rightJoyX_Axe, int rightJoyY_Axe, int LT, int RT) { //to update for more controlBinding + public static void inputRefresh(int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , + int select , int start , int L_JoyClick , int R_JoyClick , int up , int right , int down , int left, + int leftJoyX_Axe, int leftJoyY_Axe, int rightJoyX_Axe, int rightJoyY_Axe, int LT, int RT) { //to update for more controlBinding ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); @@ -127,7 +121,16 @@ public class GamepadInput { //LT RT LT_pressed = gamepadButton.get(LT) == 1; RT_pressed = gamepadButton.get(RT) == 1; - } + + public boolean checkPressed(int keyCode){ + ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); + FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); + + assert gamepadAxes != null; + assert gamepadButton != null; + + return gamepadButton.get(keyCode) == 1; + } } From 611894537a7513effc89e9ba0678910d20fd0f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Tue, 1 Jun 2021 19:23:33 +0200 Subject: [PATCH 17/32] constructor for gamepadInput --- src/engine/Engine.java | 11 ++-- src/engine/input/GamepadInput.java | 81 ++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 78679a3..cd3d754 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -220,14 +220,15 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - GamepadInput.inputRefresh(buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , + GamepadInput gamepad1 = new GamepadInput(false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); + gamepad1.inputRefresh(buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , L_JoystickClick , R_JoystickClick , Up , right , down , left, leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); - System.out.println( " \n left :" + GamepadInput.leftJoyLeft + - " \n right :" + GamepadInput.leftJoyRight + - " \n down :" + GamepadInput.leftJoyDown + - " \n up :" + GamepadInput.leftJoyUp); + System.out.println( " \n left :" + gamepad1.leftJoyLeft + + " \n right :" + gamepad1.leftJoyRight + + " \n down :" + gamepad1.leftJoyDown + + " \n up :" + gamepad1.leftJoyUp); } // Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index a8b4c94..d3ee603 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -32,41 +32,70 @@ import static org.lwjgl.glfw.GLFW.*; public class GamepadInput { - public static boolean buttonA_pressed = false; - public static boolean buttonB_pressed = false; - public static boolean buttonY_pressed = false; - public static boolean buttonX_pressed = false; + public boolean buttonA_pressed ; + public boolean buttonB_pressed ; + public boolean buttonY_pressed ; + public boolean buttonX_pressed; - public static boolean LB_pressed = false; - public static boolean RB_pressed = false; + public boolean LB_pressed ; + public boolean RB_pressed ; - public static boolean select_pressed = false; - public static boolean start_pressed = false; + public boolean select_pressed; + public boolean start_pressed; - public static boolean R_JoyClick_pressed = false; - public static boolean L_JoyClick_pressed = false; + public boolean R_JoyClick_pressed; + public boolean L_JoyClick_pressed; - public static boolean up_pressed = false; - public static boolean down_pressed = false; - public static boolean left_pressed = false; - public static boolean right_pressed = false; + public boolean up_pressed ; + public boolean down_pressed; + public boolean left_pressed ; + public boolean right_pressed; - public static boolean leftJoyRight = false; - public static boolean leftJoyLeft = false; - public static boolean leftJoyDown = false; - public static boolean leftJoyUp = false; + public boolean leftJoyRight; + public boolean leftJoyLeft; + public boolean leftJoyDown; + public boolean leftJoyUp; - public static boolean rightJoyLeft = false; - public static boolean rightJoyRight = false; - public static boolean rightJoyDown = false; - public static boolean rightJoyUp = false; - - public static boolean LT_pressed = false; - public static boolean RT_pressed = false; + public boolean rightJoyLeft; + public boolean rightJoyRight; + public boolean rightJoyDown ; + public boolean rightJoyUp; + public boolean LT_pressed ; + public boolean RT_pressed; + public GamepadInput (boolean buttonA_pressed,boolean buttonB_pressed,boolean buttonY_pressed, boolean buttonX_pressed, boolean LB_pressed, + boolean RB_pressed, boolean select_pressed, boolean start_pressed,boolean R_JoyClick_pressed, boolean L_JoyClick_pressed , boolean up_pressed, + boolean down_pressed,boolean left_pressed,boolean right_pressed,boolean leftJoyRight,boolean leftJoyLeft,boolean leftJoyDown, boolean leftJoyUp, + boolean rightJoyLeft, boolean rightJoyRight, boolean rightJoyDown,boolean rightJoyUp,boolean LT_pressed, boolean RT_pressed){ + + this.buttonA_pressed = buttonA_pressed; + this.buttonB_pressed = buttonB_pressed; + this.buttonY_pressed = buttonY_pressed; + this.buttonX_pressed =buttonX_pressed; + this.LB_pressed =LB_pressed; + this.RB_pressed =RB_pressed; + this.select_pressed =select_pressed; + this.start_pressed =start_pressed; + this.R_JoyClick_pressed =R_JoyClick_pressed; + this.L_JoyClick_pressed =L_JoyClick_pressed; + this.up_pressed =up_pressed; + this.down_pressed =down_pressed; + this.left_pressed =left_pressed; + this.right_pressed =right_pressed; + this.leftJoyRight =leftJoyRight; + this.leftJoyLeft =leftJoyLeft; + this.leftJoyDown =leftJoyDown; + this.leftJoyUp =leftJoyUp; + this.rightJoyLeft =rightJoyLeft; + this.rightJoyRight =rightJoyRight; + this.rightJoyDown =rightJoyDown; + this.rightJoyUp =rightJoyUp; + this.LT_pressed =LT_pressed; + this.RT_pressed =RT_pressed; + } - public static void inputRefresh(int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , + public void inputRefresh(int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , int select , int start , int L_JoyClick , int R_JoyClick , int up , int right , int down , int left, int leftJoyX_Axe, int leftJoyY_Axe, int rightJoyX_Axe, int rightJoyY_Axe, int LT, int RT) { //to update for more controlBinding ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); From 094fedc3a22cb9fdc49bae1e086925ec3b39d795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o?= Date: Tue, 1 Jun 2021 19:47:47 +0200 Subject: [PATCH 18/32] inputVariables --- src/engine/Engine.java | 8 +---- src/engine/input/GamepadInput.java | 54 ++++++++++++++-------------- src/engine/input/inputVariables.java | 7 ++++ 3 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 src/engine/input/inputVariables.java diff --git a/src/engine/Engine.java b/src/engine/Engine.java index cd3d754..4f6d8f3 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -25,10 +25,6 @@ public class Engine { private final List objectsGl; - private final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, - L_JoystickClick = 8, R_JoystickClick =9, Up = 10, right = 11, down = 12, left = 13, - leftJoyX_Axe = 0, leftJoyY_Axe = 1, rightJoyX_Axe = 2, rightJoyY_Axe = 3, LT = 4, RT = 5; - private boolean running; private final int width; @@ -221,9 +217,7 @@ public class Engine { if (present) { //sprite //bindings GamepadInput gamepad1 = new GamepadInput(false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); - gamepad1.inputRefresh(buttonA, buttonB, buttonX, buttonY, LB, RB , select , start , - L_JoystickClick , R_JoystickClick , Up , right , down , left, - leftJoyX_Axe, leftJoyY_Axe, rightJoyX_Axe, rightJoyY_Axe, LT, RT); + gamepad1.inputRefresh(); System.out.println( " \n left :" + gamepad1.leftJoyLeft + " \n right :" + gamepad1.leftJoyRight + diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index d3ee603..2e9d055 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -3,6 +3,8 @@ package engine.input; import java.nio.ByteBuffer; import java.nio.FloatBuffer; +import engine.Engine; + import static org.lwjgl.glfw.GLFW.*; /* Buttons 0 : Croix / A @@ -95,9 +97,7 @@ public class GamepadInput { this.RT_pressed =RT_pressed; } - public void inputRefresh(int ButtonA, int ButtonB, int ButtonX, int ButtonY, int LB, int RB , - int select , int start , int L_JoyClick , int R_JoyClick , int up , int right , int down , int left, - int leftJoyX_Axe, int leftJoyY_Axe, int rightJoyX_Axe, int rightJoyY_Axe, int LT, int RT) { //to update for more controlBinding + public void inputRefresh() { ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); @@ -106,50 +106,50 @@ public class GamepadInput { // A B X Y - buttonA_pressed = gamepadButton.get(ButtonA) == 1; - buttonB_pressed = gamepadButton.get(ButtonB) == 1; - buttonY_pressed = gamepadButton.get(ButtonY) == 1; - buttonX_pressed = gamepadButton.get(ButtonX) == 1; + buttonA_pressed = gamepadButton.get(inputVariables.buttonA) == 1; + buttonB_pressed = gamepadButton.get(inputVariables.buttonB) == 1; + buttonY_pressed = gamepadButton.get(inputVariables.buttonY) == 1; + buttonX_pressed = gamepadButton.get(inputVariables.buttonX) == 1; // LB RB - LB_pressed = gamepadButton.get(LB) == 1; - RB_pressed = gamepadButton.get(RB) == 1; + LB_pressed = gamepadButton.get(inputVariables.LB) == 1; + RB_pressed = gamepadButton.get(inputVariables.RB) == 1; //start select - start_pressed = gamepadButton.get(start) == 1; - select_pressed = gamepadButton.get(select) == 1; + start_pressed = gamepadButton.get(inputVariables.start) == 1; + select_pressed = gamepadButton.get(inputVariables.select) == 1; //R & L JoystickClick - R_JoyClick_pressed = gamepadButton.get(R_JoyClick) == 1; - L_JoyClick_pressed = gamepadButton.get(L_JoyClick) == 1; + R_JoyClick_pressed = gamepadButton.get(inputVariables.R_JoystickClick) == 1; + L_JoyClick_pressed = gamepadButton.get(inputVariables.L_JoystickClick) == 1; //up, down, left, right - up_pressed = gamepadButton.get(up) == 1; - down_pressed = gamepadButton.get(down) == 1; - left_pressed = gamepadButton.get(left) == 1; - right_pressed = gamepadButton.get(right) == 1; + up_pressed = gamepadButton.get(inputVariables.up) == 1; + down_pressed = gamepadButton.get(inputVariables.down) == 1; + left_pressed = gamepadButton.get(inputVariables.left) == 1; + right_pressed = gamepadButton.get(inputVariables.right) == 1; //Left Joystick - leftJoyRight = gamepadAxes.get(leftJoyX_Axe) > 0.1; - leftJoyLeft = gamepadAxes.get(leftJoyX_Axe) < -0.1; - leftJoyDown = gamepadAxes.get(leftJoyY_Axe) > 0.1; - leftJoyUp = gamepadAxes.get(leftJoyY_Axe) < -0.1; + leftJoyRight = gamepadAxes.get(inputVariables.leftJoyX_Axe) > 0.1; + leftJoyLeft = gamepadAxes.get(inputVariables.leftJoyX_Axe) < -0.1; + leftJoyDown = gamepadAxes.get(inputVariables.leftJoyY_Axe) > 0.1; + leftJoyUp = gamepadAxes.get(inputVariables.leftJoyY_Axe) < -0.1; //Right Joystick - rightJoyRight = gamepadAxes.get(rightJoyX_Axe) > 0.1; - rightJoyLeft = gamepadAxes.get(rightJoyX_Axe) < -0.1; - rightJoyDown = gamepadAxes.get(rightJoyY_Axe) > 0.1; - rightJoyUp = gamepadAxes.get(rightJoyY_Axe) < -0.1; + rightJoyRight = gamepadAxes.get(inputVariables.rightJoyX_Axe) > 0.1; + rightJoyLeft = gamepadAxes.get(inputVariables.rightJoyX_Axe) < -0.1; + rightJoyDown = gamepadAxes.get(inputVariables.rightJoyY_Axe) > 0.1; + rightJoyUp = gamepadAxes.get(inputVariables.rightJoyY_Axe) < -0.1; //LT RT - LT_pressed = gamepadButton.get(LT) == 1; - RT_pressed = gamepadButton.get(RT) == 1; + LT_pressed = gamepadButton.get(inputVariables.LT) == 1; + RT_pressed = gamepadButton.get(inputVariables.RT) == 1; } public boolean checkPressed(int keyCode){ diff --git a/src/engine/input/inputVariables.java b/src/engine/input/inputVariables.java new file mode 100644 index 0000000..d8af4f4 --- /dev/null +++ b/src/engine/input/inputVariables.java @@ -0,0 +1,7 @@ +package engine.input; + +public class inputVariables { + public final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, + L_JoystickClick = 8, R_JoystickClick =9, up = 10, right = 11, down = 12, left = 13, + leftJoyX_Axe = 0, leftJoyY_Axe = 1, rightJoyX_Axe = 2, rightJoyY_Axe = 3, LT = 4, RT = 5; +} From 51733a2e6a41d56a66feda4baef67a0eaf916ab6 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 19:51:01 +0200 Subject: [PATCH 19/32] Wildcard import --- src/engine/input/GamepadInput.java | 49 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 2e9d055..33302da 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -5,6 +5,7 @@ import java.nio.FloatBuffer; import engine.Engine; +import static engine.input.inputVariables.*; import static org.lwjgl.glfw.GLFW.*; /* Buttons 0 : Croix / A @@ -106,50 +107,50 @@ public class GamepadInput { // A B X Y - buttonA_pressed = gamepadButton.get(inputVariables.buttonA) == 1; - buttonB_pressed = gamepadButton.get(inputVariables.buttonB) == 1; - buttonY_pressed = gamepadButton.get(inputVariables.buttonY) == 1; - buttonX_pressed = gamepadButton.get(inputVariables.buttonX) == 1; + buttonA_pressed = gamepadButton.get(buttonA) == 1; + buttonB_pressed = gamepadButton.get(buttonB) == 1; + buttonY_pressed = gamepadButton.get(buttonY) == 1; + buttonX_pressed = gamepadButton.get(buttonX) == 1; // LB RB - LB_pressed = gamepadButton.get(inputVariables.LB) == 1; - RB_pressed = gamepadButton.get(inputVariables.RB) == 1; + LB_pressed = gamepadButton.get(LB) == 1; + RB_pressed = gamepadButton.get(RB) == 1; //start select - start_pressed = gamepadButton.get(inputVariables.start) == 1; - select_pressed = gamepadButton.get(inputVariables.select) == 1; + start_pressed = gamepadButton.get(start) == 1; + select_pressed = gamepadButton.get(select) == 1; //R & L JoystickClick - R_JoyClick_pressed = gamepadButton.get(inputVariables.R_JoystickClick) == 1; - L_JoyClick_pressed = gamepadButton.get(inputVariables.L_JoystickClick) == 1; + R_JoyClick_pressed = gamepadButton.get(R_JoystickClick) == 1; + L_JoyClick_pressed = gamepadButton.get(L_JoystickClick) == 1; //up, down, left, right - up_pressed = gamepadButton.get(inputVariables.up) == 1; - down_pressed = gamepadButton.get(inputVariables.down) == 1; - left_pressed = gamepadButton.get(inputVariables.left) == 1; - right_pressed = gamepadButton.get(inputVariables.right) == 1; + up_pressed = gamepadButton.get(up) == 1; + down_pressed = gamepadButton.get(down) == 1; + left_pressed = gamepadButton.get(left) == 1; + right_pressed = gamepadButton.get(right) == 1; //Left Joystick - leftJoyRight = gamepadAxes.get(inputVariables.leftJoyX_Axe) > 0.1; - leftJoyLeft = gamepadAxes.get(inputVariables.leftJoyX_Axe) < -0.1; - leftJoyDown = gamepadAxes.get(inputVariables.leftJoyY_Axe) > 0.1; - leftJoyUp = gamepadAxes.get(inputVariables.leftJoyY_Axe) < -0.1; + leftJoyRight = gamepadAxes.get(leftJoyX_Axe) > 0.1; + leftJoyLeft = gamepadAxes.get(leftJoyX_Axe) < -0.1; + leftJoyDown = gamepadAxes.get(leftJoyY_Axe) > 0.1; + leftJoyUp = gamepadAxes.get(leftJoyY_Axe) < -0.1; //Right Joystick - rightJoyRight = gamepadAxes.get(inputVariables.rightJoyX_Axe) > 0.1; - rightJoyLeft = gamepadAxes.get(inputVariables.rightJoyX_Axe) < -0.1; - rightJoyDown = gamepadAxes.get(inputVariables.rightJoyY_Axe) > 0.1; - rightJoyUp = gamepadAxes.get(inputVariables.rightJoyY_Axe) < -0.1; + rightJoyRight = gamepadAxes.get(rightJoyX_Axe) > 0.1; + rightJoyLeft = gamepadAxes.get(rightJoyX_Axe) < -0.1; + rightJoyDown = gamepadAxes.get(rightJoyY_Axe) > 0.1; + rightJoyUp = gamepadAxes.get(rightJoyY_Axe) < -0.1; //LT RT - LT_pressed = gamepadButton.get(inputVariables.LT) == 1; - RT_pressed = gamepadButton.get(inputVariables.RT) == 1; + LT_pressed = gamepadButton.get(LT) == 1; + RT_pressed = gamepadButton.get(RT) == 1; } public boolean checkPressed(int keyCode){ From f4b7d5752ded8e2f481a66cdb876f4038f3eb3f6 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 19:54:05 +0200 Subject: [PATCH 20/32] =?UTF-8?q?GLFW=5FJOYSTICK=5FN=20envoy=C3=A9=20depui?= =?UTF-8?q?s=20le=20constructeur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/Engine.java | 2 +- src/engine/input/GamepadInput.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 4f6d8f3..7792cde 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -216,7 +216,7 @@ public class Engine { // Game logic should fit here if (present) { //sprite //bindings - GamepadInput gamepad1 = new GamepadInput(false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); + GamepadInput gamepad1 = new GamepadInput(GLFW_JOYSTICK_1, false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); gamepad1.inputRefresh(); System.out.println( " \n left :" + gamepad1.leftJoyLeft + diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 33302da..8d807a2 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -3,8 +3,6 @@ package engine.input; import java.nio.ByteBuffer; import java.nio.FloatBuffer; -import engine.Engine; - import static engine.input.inputVariables.*; import static org.lwjgl.glfw.GLFW.*; /* Buttons @@ -34,6 +32,8 @@ import static org.lwjgl.glfw.GLFW.*; */ public class GamepadInput { + + private final int gamepadNum; public boolean buttonA_pressed ; public boolean buttonB_pressed ; @@ -67,11 +67,11 @@ public class GamepadInput { public boolean LT_pressed ; public boolean RT_pressed; - public GamepadInput (boolean buttonA_pressed,boolean buttonB_pressed,boolean buttonY_pressed, boolean buttonX_pressed, boolean LB_pressed, + public GamepadInput (int gamepadNum, boolean buttonA_pressed,boolean buttonB_pressed,boolean buttonY_pressed, boolean buttonX_pressed, boolean LB_pressed, boolean RB_pressed, boolean select_pressed, boolean start_pressed,boolean R_JoyClick_pressed, boolean L_JoyClick_pressed , boolean up_pressed, boolean down_pressed,boolean left_pressed,boolean right_pressed,boolean leftJoyRight,boolean leftJoyLeft,boolean leftJoyDown, boolean leftJoyUp, boolean rightJoyLeft, boolean rightJoyRight, boolean rightJoyDown,boolean rightJoyUp,boolean LT_pressed, boolean RT_pressed){ - + this.gamepadNum = gamepadNum; this.buttonA_pressed = buttonA_pressed; this.buttonB_pressed = buttonB_pressed; this.buttonY_pressed = buttonY_pressed; @@ -99,8 +99,8 @@ public class GamepadInput { } public void inputRefresh() { - ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); - FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); + ByteBuffer gamepadButton = glfwGetJoystickButtons(this.gamepadNum); + FloatBuffer gamepadAxes = glfwGetJoystickAxes(this.gamepadNum); assert gamepadAxes != null; assert gamepadButton != null; From 62b888da92f6b2289b2d74de7f0d97b00a61063b Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 22:22:10 +0200 Subject: [PATCH 21/32] getAxisDiscreet && getAxisContinuous added --- src/engine/Engine.java | 14 ++-- src/engine/input/GamepadInput.java | 111 +++++++++++++++++++-------- src/engine/input/inputConst.java | 17 ++++ src/engine/input/inputVariables.java | 7 -- src/engine/math/Vector3f.java | 5 ++ 5 files changed, 110 insertions(+), 44 deletions(-) create mode 100644 src/engine/input/inputConst.java delete mode 100644 src/engine/input/inputVariables.java diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 7792cde..dcebdcb 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -215,14 +215,16 @@ public class Engine { lastFrame = System.currentTimeMillis(); // Game logic should fit here - if (present) { //sprite //bindings - GamepadInput gamepad1 = new GamepadInput(GLFW_JOYSTICK_1, false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); + if (present) { + GamepadInput gamepad1 = new GamepadInput(GLFW_JOYSTICK_1); gamepad1.inputRefresh(); - System.out.println( " \n left :" + gamepad1.leftJoyLeft + - " \n right :" + gamepad1.leftJoyRight + - " \n down :" + gamepad1.leftJoyDown + - " \n up :" + gamepad1.leftJoyUp); +// System.out.println( " \n left :" + gamepad1.leftJoyLeft + +// " \n right :" + gamepad1.leftJoyRight + +// " \n down :" + gamepad1.leftJoyDown + +// " \n up :" + gamepad1.leftJoyUp); + + System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); } // Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 8d807a2..319bc31 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -1,9 +1,11 @@ package engine.input; +import engine.math.Vector3f; + import java.nio.ByteBuffer; import java.nio.FloatBuffer; -import static engine.input.inputVariables.*; +import static engine.input.inputConst.*; import static org.lwjgl.glfw.GLFW.*; /* Buttons 0 : Croix / A @@ -67,35 +69,32 @@ public class GamepadInput { public boolean LT_pressed ; public boolean RT_pressed; - public GamepadInput (int gamepadNum, boolean buttonA_pressed,boolean buttonB_pressed,boolean buttonY_pressed, boolean buttonX_pressed, boolean LB_pressed, - boolean RB_pressed, boolean select_pressed, boolean start_pressed,boolean R_JoyClick_pressed, boolean L_JoyClick_pressed , boolean up_pressed, - boolean down_pressed,boolean left_pressed,boolean right_pressed,boolean leftJoyRight,boolean leftJoyLeft,boolean leftJoyDown, boolean leftJoyUp, - boolean rightJoyLeft, boolean rightJoyRight, boolean rightJoyDown,boolean rightJoyUp,boolean LT_pressed, boolean RT_pressed){ + public GamepadInput (int gamepadNum){ this.gamepadNum = gamepadNum; - this.buttonA_pressed = buttonA_pressed; - this.buttonB_pressed = buttonB_pressed; - this.buttonY_pressed = buttonY_pressed; - this.buttonX_pressed =buttonX_pressed; - this.LB_pressed =LB_pressed; - this.RB_pressed =RB_pressed; - this.select_pressed =select_pressed; - this.start_pressed =start_pressed; - this.R_JoyClick_pressed =R_JoyClick_pressed; - this.L_JoyClick_pressed =L_JoyClick_pressed; - this.up_pressed =up_pressed; - this.down_pressed =down_pressed; - this.left_pressed =left_pressed; - this.right_pressed =right_pressed; - this.leftJoyRight =leftJoyRight; - this.leftJoyLeft =leftJoyLeft; - this.leftJoyDown =leftJoyDown; - this.leftJoyUp =leftJoyUp; - this.rightJoyLeft =rightJoyLeft; - this.rightJoyRight =rightJoyRight; - this.rightJoyDown =rightJoyDown; - this.rightJoyUp =rightJoyUp; - this.LT_pressed =LT_pressed; - this.RT_pressed =RT_pressed; + this.buttonA_pressed = false; + this.buttonB_pressed = false; + this.buttonY_pressed = false; + this.buttonX_pressed = false; + this.LB_pressed = false; + this.RB_pressed = false; + this.select_pressed = false; + this.start_pressed = false; + this.R_JoyClick_pressed = false; + this.L_JoyClick_pressed = false; + this.up_pressed = false; + this.down_pressed = false; + this.left_pressed = false; + this.right_pressed = false; + this.leftJoyRight = false; + this.leftJoyLeft = false; + this.leftJoyDown = false; + this.leftJoyUp = false; + this.rightJoyLeft = false; + this.rightJoyRight = false; + this.rightJoyDown = false; + this.rightJoyUp = false; + this.LT_pressed = false; + this.RT_pressed = false; } public void inputRefresh() { @@ -155,12 +154,62 @@ public class GamepadInput { public boolean checkPressed(int keyCode){ ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); - FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); - assert gamepadAxes != null; assert gamepadButton != null; return gamepadButton.get(keyCode) == 1; } + + /** + * + * @param axisId + * @return + */ + public int getAxisDiscreet(int axisId){ + + FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); + + assert gamepadAxes != null; + + float x = gamepadAxes.get(axisId); + float y = gamepadAxes.get(axisId + 1); + + float magnitude = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + float angle = (float) Math.toDegrees(2 * Math.atan(y /(x + magnitude))); + + if (magnitude < 0.1) return CENTER; + if (angle < 22.5 && angle > -22.5) return RIGHT; + else if (angle > -67.5 && angle < -22.5) return UPPER_RIGHT; + else if (angle > -112.5 && angle < -67.5) return UP; + else if (angle > -157.5 && angle < -112.5) return UPPER_LEFT; + else if (angle < -157.5 || angle > 157.5) return LEFT; + else if (angle < 157.5 && angle > 112.5) return LOWER_LEFT; + else if (angle < 112.5 && angle > 67.5) return DOWN; + else if (angle < 67.5 && angle > 22.5) return LOWER_RIGHT; + + return -1; // TEST + } + + /** + * + * @param axisId l'identifiant du joystick (AXE X) + * @return un Vecteur représentant la position actuel du joystick + */ + public Vector3f getAxisContinuous(int axisId){ + + FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); + + assert gamepadAxes != null; + + float x = gamepadAxes.get(axisId); + float y = gamepadAxes.get(axisId + 1); + + if (x < 0.1 && x > -0.1) x = 0; + if (y < 0.1 && y > -0.1) y = 0; + + System.out.println("x: " + x + " y: " + y); + + return new Vector3f(x,y); + } } diff --git a/src/engine/input/inputConst.java b/src/engine/input/inputConst.java new file mode 100644 index 0000000..4fb4fc1 --- /dev/null +++ b/src/engine/input/inputConst.java @@ -0,0 +1,17 @@ +package engine.input; + +public class inputConst { + /* + Button ID + */ + public final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, + L_JoystickClick = 8, R_JoystickClick =9, up = 10, right = 11, down = 12, left = 13; + + /* + Axis ID + */ + public final static int leftJoyX_Axe = 0, leftJoyY_Axe = 1, rightJoyX_Axe = 2, rightJoyY_Axe = 3, LT = 4, RT = 5; + + public final static int RIGHT = 0, UPPER_RIGHT = 1, UP = 2, UPPER_LEFT = 3, LEFT = 4, LOWER_LEFT = 5, + DOWN = 6, LOWER_RIGHT = 7, CENTER = 8; +} diff --git a/src/engine/input/inputVariables.java b/src/engine/input/inputVariables.java deleted file mode 100644 index d8af4f4..0000000 --- a/src/engine/input/inputVariables.java +++ /dev/null @@ -1,7 +0,0 @@ -package engine.input; - -public class inputVariables { - public final static int buttonA=0, buttonB=1, buttonX=2, buttonY=3, LB = 4, RB = 5, select = 6, start = 7, - L_JoystickClick = 8, R_JoystickClick =9, up = 10, right = 11, down = 12, left = 13, - leftJoyX_Axe = 0, leftJoyY_Axe = 1, rightJoyX_Axe = 2, rightJoyY_Axe = 3, LT = 4, RT = 5; -} diff --git a/src/engine/math/Vector3f.java b/src/engine/math/Vector3f.java index 4f7c98b..4f81fee 100644 --- a/src/engine/math/Vector3f.java +++ b/src/engine/math/Vector3f.java @@ -10,6 +10,11 @@ public class Vector3f { z = 0.0f; } + public Vector3f(float x, float y){ + this.x = x; + this.y = y; + } + public Vector3f(float x, float y, float z){ this.x = x; this.y = y; From cf7a1ed85b77b17b280dc74d811fcf378e36fd53 Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Jun 2021 22:33:11 +0200 Subject: [PATCH 22/32] Oune poquito de docito + Rename de certaine classe pour qu'elles respectent les conventions --- src/engine/Engine.java | 5 ++-- src/engine/input/GamepadInput.java | 29 ++++++++----------- .../{inputConst.java => InputConst.java} | 2 +- .../input/{Input.java => KeyboardInput.java} | 10 +++---- 4 files changed, 20 insertions(+), 26 deletions(-) rename src/engine/input/{inputConst.java => InputConst.java} (95%) rename src/engine/input/{Input.java => KeyboardInput.java} (92%) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index dcebdcb..ade39db 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -1,7 +1,6 @@ package engine; -import engine.input.Input; -//import engine.input.gamepadInput; +import engine.input.KeyboardInput; import engine.input.GamepadInput; import engine.math.*; import engine.object.*; @@ -73,7 +72,7 @@ public class Engine { // 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()); + glfwSetKeyCallback(getWindow(), new KeyboardInput()); glfwSetInputMode(getWindow(), GLFW_STICKY_KEYS, GLFW_TRUE); // Contexte = zone cible des rendus diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 319bc31..9b68c50 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -5,7 +5,7 @@ import engine.math.Vector3f; import java.nio.ByteBuffer; import java.nio.FloatBuffer; -import static engine.input.inputConst.*; +import static engine.input.InputConst.*; import static org.lwjgl.glfw.GLFW.*; /* Buttons 0 : Croix / A @@ -36,6 +36,8 @@ import static org.lwjgl.glfw.GLFW.*; public class GamepadInput { private final int gamepadNum; + private ByteBuffer gamepadButton; + private FloatBuffer gamepadAxes; public boolean buttonA_pressed ; public boolean buttonB_pressed ; @@ -97,9 +99,10 @@ public class GamepadInput { this.RT_pressed = false; } - public void inputRefresh() { - ByteBuffer gamepadButton = glfwGetJoystickButtons(this.gamepadNum); - FloatBuffer gamepadAxes = glfwGetJoystickAxes(this.gamepadNum); + public void inputRefresh() { + + this.gamepadButton = glfwGetJoystickButtons(this.gamepadNum); + this.gamepadAxes = glfwGetJoystickAxes(this.gamepadNum); assert gamepadAxes != null; assert gamepadButton != null; @@ -153,7 +156,7 @@ public class GamepadInput { } public boolean checkPressed(int keyCode){ - ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); + this.gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1); assert gamepadButton != null; @@ -161,16 +164,12 @@ public class GamepadInput { } /** - * - * @param axisId - * @return + * Envoie la position du stick pointé par axisId sous forme de direction général (9 directions) + * @param axisId l'identifiant du joystick (AXE X) + * @return la direction du stick valeur possible : RIGHT, UPPER_RIGHT, UP, UPPER_LEFT, LEFT, LOWER_LEFT, DOWN, LOWER_RIGHT, CENTER; */ public int getAxisDiscreet(int axisId){ - FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); - - assert gamepadAxes != null; - float x = gamepadAxes.get(axisId); float y = gamepadAxes.get(axisId + 1); @@ -191,16 +190,12 @@ public class GamepadInput { } /** - * + * Envoie la position du stick pointé par axisID (AXE X) sous forme de Vecteur * @param axisId l'identifiant du joystick (AXE X) * @return un Vecteur représentant la position actuel du joystick */ public Vector3f getAxisContinuous(int axisId){ - FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); - - assert gamepadAxes != null; - float x = gamepadAxes.get(axisId); float y = gamepadAxes.get(axisId + 1); diff --git a/src/engine/input/inputConst.java b/src/engine/input/InputConst.java similarity index 95% rename from src/engine/input/inputConst.java rename to src/engine/input/InputConst.java index 4fb4fc1..e45db72 100644 --- a/src/engine/input/inputConst.java +++ b/src/engine/input/InputConst.java @@ -1,6 +1,6 @@ package engine.input; -public class inputConst { +public class InputConst { /* Button ID */ diff --git a/src/engine/input/Input.java b/src/engine/input/KeyboardInput.java similarity index 92% rename from src/engine/input/Input.java rename to src/engine/input/KeyboardInput.java index e734f2d..25fe04c 100644 --- a/src/engine/input/Input.java +++ b/src/engine/input/KeyboardInput.java @@ -12,7 +12,7 @@ import java.nio.FloatBuffer; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; -public class Input extends GLFWKeyCallback { +public class KeyboardInput extends GLFWKeyCallback { public static boolean[] keys = new boolean[65536]; @@ -89,18 +89,18 @@ public class Input extends GLFWKeyCallback { public static void keyboardInput(ObjectGl token, int speed) { boolean keyPressed = false; - if (Input.isKeyDown(GLFW.GLFW_KEY_S)) { + if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_S)) { token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM); keyPressed = true; - } else if (Input.isKeyDown(GLFW.GLFW_KEY_W)) { + } else if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_W)) { keyPressed = true; } - if (Input.isKeyDown(GLFW.GLFW_KEY_A)) { + if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_A)) { token.translate(new Vector3f (speed * -5.0f, 0.0f, 0.0f)); token.setTextureWrap(121,0,57,82, ObjectGl.STICK_TOP); keyPressed = true; } - else if (Input.isKeyDown(GLFW.GLFW_KEY_D)) { + else if (KeyboardInput.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); keyPressed = true; From c22f4266d185f1b80f00e3bd357097b60936c036 Mon Sep 17 00:00:00 2001 From: Boyeau Indy Date: Wed, 2 Jun 2021 08:42:46 +0000 Subject: [PATCH 23/32] Update config.json --- src/configuration/config.json | 55 ++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/configuration/config.json b/src/configuration/config.json index 4c4b7fd..fbd5c52 100644 --- a/src/configuration/config.json +++ b/src/configuration/config.json @@ -1,40 +1,55 @@ { - "test": "test valide", "arena": [ + "random", "arena1.png", - "arena2.png", - "random" + "arena2.png" ], "nb_players": [ "1", "2" ], "character1": [ + "random", "character1.png", - "character2.png", - "random" + "character2.png" ], "character2": [ + "random", "character1.png", "character1_swapcolor.png", "character2.png", - "character2_swapcolor.png", - "random" + "character2_swapcolor.png" ], "resolution": [ - "1280 x 1024", - "1680 x 1050", - "1920 x 1080", - "800 x 600" - ], + { + "width": "800", + "height": "600" + }, + { + "width": "1280", + "height": "1024" + }, + { + "width": "1680", + "height": "1050" + }, + { + "width": "1920", + "height": "1080" + }, + { + "persoWidth": "800", + "persoHeight": "600" + } + ], "button": [ - "up", - "down", - "rigth", - "left", - "a", - "b", - "c", - "d" + "UP", + "DOWN", + "RIGTH", + "LEFT", + "A", + "B", + "X", + "Y" ] } From bce22204532d8e7ca4ce67be9d9707de762c9f31 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 15:23:44 +0200 Subject: [PATCH 24/32] Exemple utilisation Input --- src/engine/Engine.java | 41 +++++++++++++++++++++--------- src/engine/input/GamepadInput.java | 2 ++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index ade39db..0ce61be 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -1,7 +1,6 @@ package engine; -import engine.input.KeyboardInput; -import engine.input.GamepadInput; +import engine.input.*; import engine.math.*; import engine.object.*; import engine.sound.*; @@ -206,24 +205,42 @@ public class Engine { long lastFrame; int frame = 0; boolean nextFrame = false; - boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); - - + boolean Joystick1Present = glfwJoystickPresent(GLFW_JOYSTICK_1); + + /* + * Création des manettes / action + */ + + GamepadInput gamepad1 = null; + Button jump = null; + + if (Joystick1Present){ + gamepad1 = new GamepadInput(GLFW_JOYSTICK_1); + gamepad1.inputRefresh(); + List listJump = new ArrayList<>(); + listJump.add(InputConst.buttonA); + jump = new Button("jump", listJump, gamepad1); + + + + } + + while (engine.isRunning()) { lastFrame = System.currentTimeMillis(); // Game logic should fit here - if (present) { - GamepadInput gamepad1 = new GamepadInput(GLFW_JOYSTICK_1); + if (Joystick1Present) { gamepad1.inputRefresh(); - -// System.out.println( " \n left :" + gamepad1.leftJoyLeft + -// " \n right :" + gamepad1.leftJoyRight + -// " \n down :" + gamepad1.leftJoyDown + -// " \n up :" + gamepad1.leftJoyUp); System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); + + // Check si le personnage a sauté + if (jump.isButtonPressed()){ + // Le personnage saute + System.out.println(" JE SAUTE "); + } } // Input.keyboardInput(zangief, speed); diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 9b68c50..78bce7e 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -73,6 +73,8 @@ public class GamepadInput { public GamepadInput (int gamepadNum){ this.gamepadNum = gamepadNum; + this.gamepadAxes = null; + this.gamepadButton = null; this.buttonA_pressed = false; this.buttonB_pressed = false; this.buttonY_pressed = false; From fbf65f3a6f220efee41648e3f2978f23e4c44110 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 15:37:41 +0200 Subject: [PATCH 25/32] =?UTF-8?q?Impl=C3=A9mentation=20minimal=20match.jav?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/input/GamepadInput.java | 2 +- src/gameplay/match/match.java | 76 +++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/engine/input/GamepadInput.java b/src/engine/input/GamepadInput.java index 78bce7e..1cfd164 100644 --- a/src/engine/input/GamepadInput.java +++ b/src/engine/input/GamepadInput.java @@ -178,7 +178,7 @@ public class GamepadInput { float magnitude = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); float angle = (float) Math.toDegrees(2 * Math.atan(y /(x + magnitude))); - if (magnitude < 0.1) return CENTER; + if (magnitude < 0.3) return CENTER; if (angle < 22.5 && angle > -22.5) return RIGHT; else if (angle > -67.5 && angle < -22.5) return UPPER_RIGHT; else if (angle > -112.5 && angle < -67.5) return UP; diff --git a/src/gameplay/match/match.java b/src/gameplay/match/match.java index 6f54f84..f5c069a 100644 --- a/src/gameplay/match/match.java +++ b/src/gameplay/match/match.java @@ -1,9 +1,19 @@ package gameplay.match; +import engine.Engine; +import engine.input.Button; +import engine.input.GamepadInput; +import engine.input.InputConst; +import engine.object.ObjectGl; import gameplay.input.InputBuffer; import gameplay.entities.*; import gameplay.entities.Character; +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.glfw.GLFW.*; + /** * Main class that describes the base structure of the match, with characters, timer and such * @author Victor Azra @@ -37,6 +47,68 @@ public class match { this.roundsWonP1 = 0; this.roundsWonP2 = 0; } - - + + public static void main(String[] args) throws Exception { + + Engine engine = new Engine(800, 600, 3.0f / 4.0f); + engine.init(); + + String path = "textures/zangief_sprite.png"; + + ObjectGl zangief = new ObjectGl(0f, 60f, 80f, 10f, path, null); + zangief.setTextureWrap(58, 0, 62, 84, ObjectGl.STICK_TOP); + engine.add_objectGl(zangief); + + long timer = System.currentTimeMillis(); + long lastFrame; + int frame = 0; + boolean nextFrame = false; + boolean Joystick1Present = glfwJoystickPresent(GLFW_JOYSTICK_1); + + GamepadInput gamepad1 = null; + Button jump = null; + + if (Joystick1Present) { + gamepad1 = new GamepadInput(GLFW_JOYSTICK_1); + gamepad1.inputRefresh(); + List listJump = new ArrayList<>(); + listJump.add(InputConst.buttonA); + jump = new Button("jump", listJump, gamepad1); + } + + while (engine.isRunning()) { + lastFrame = System.currentTimeMillis(); + // Game logic should fit here + + if (Joystick1Present) { + gamepad1.inputRefresh(); + + System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); + + // Check si le personnage a sauté + if (jump.isButtonPressed()) { + // Le personnage saute + System.out.println(" JE SAUTE "); + } + } + + 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); + } + } } From 80ab5fb99b8692cab7999d222a73ca9bc7aaaf13 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 16:46:29 +0200 Subject: [PATCH 26/32] =?UTF-8?q?Impl=C3=A9mentation=20de=20la=20conservat?= =?UTF-8?q?ion=20de=20l'aspect=20ratio=20quand=20on=20modifie=20la=20taill?= =?UTF-8?q?e=20de=20la=20fen=C3=AAtre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/Engine.java | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 0ce61be..865c3fa 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -27,6 +27,7 @@ public class Engine { private final int width; private final int height; + private float aspectRatio; /** * Create the engine and initial attributes use .init() to start the engine @@ -36,6 +37,7 @@ public class Engine { this.objectsGl = new ArrayList<>(); this.width = width; this.height = height; + this.aspectRatio = aspectRatio; ObjectGl.projection = Matrix4f.orthographic(-1000, 1000, -1000 * aspectRatio, 1000 * aspectRatio, 0.1f, 100.0f); ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f, 0.0f, 1.0f)); } @@ -83,6 +85,7 @@ public class Engine { 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 + glScissor(0,0,this.width,this.height); // La zone de dessin du background glEnable(GL_BLEND); // Transparence glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -102,6 +105,7 @@ public class Engine { */ 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); @@ -155,7 +159,20 @@ public class Engine { private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback() { @Override public void invoke(long window, int width, int height) { - glViewport(0, 0, width, height); + int heightViewport, widthViewport, x, y; + if (width >= height){ + 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); } }; @@ -180,7 +197,7 @@ public class Engine { /* Engine Init */ - Engine engine = new Engine(1280, 720, 9.0f / 16.0f); + Engine engine = new Engine(800, 600, 3.0f / 4.0f); int speed = 10; //vitesse déplacement Object engine.init(); From b5319de9406cbf33a722adb4cf41b29a24b74a92 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 17:30:43 +0200 Subject: [PATCH 27/32] Petite correction invoke in GLFWFramebufferSizeCallback --- src/engine/Engine.java | 20 ++++++++++---------- src/engine/math/Vector3f.java | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 865c3fa..9f78bb7 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -5,7 +5,6 @@ import engine.math.*; import engine.object.*; import engine.sound.*; - import org.lwjgl.glfw.GLFWFramebufferSizeCallback; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; @@ -64,7 +63,7 @@ public class Engine { assert getWindow() != NULL; boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1); - System.out.println("Manette détectée : " + present); + System.out.println("Manette détectée : " + present); // On récupère les informations du moniteur principal GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); @@ -153,14 +152,14 @@ public class Engine { } /** - * Est appelé àa chaque modification de la taille de la fenêtre, et modifie la taille de la zone de rendu + * 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) { int heightViewport, widthViewport, x, y; - if (width >= height){ + if (width >= height * 4.0f/3.0f){ heightViewport = height; widthViewport = (int) (height * 4.0f/3.0f); y = 0; @@ -173,6 +172,7 @@ public class Engine { } glScissor(x, y, widthViewport, heightViewport); glViewport(x, y, widthViewport, heightViewport); + } }; @@ -198,7 +198,7 @@ public class Engine { Engine Init */ Engine engine = new Engine(800, 600, 3.0f / 4.0f); - int speed = 10; //vitesse déplacement Object + int speed = 10; //vitesse d�placement Object engine.init(); // Add objects to render @@ -225,7 +225,7 @@ public class Engine { boolean Joystick1Present = glfwJoystickPresent(GLFW_JOYSTICK_1); /* - * Création des manettes / action + * Cr�ation des manettes / action */ GamepadInput gamepad1 = null; @@ -251,17 +251,17 @@ public class Engine { if (Joystick1Present) { gamepad1.inputRefresh(); - System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); +// System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); - // Check si le personnage a sauté + // Check si le personnage a sauté if (jump.isButtonPressed()){ // Le personnage saute System.out.println(" JE SAUTE "); } } -// Input.keyboardInput(zangief, speed); -// input(smiley2, speed); + KeyboardInput.keyboardInput(zangief, speed); +// input(smiley2, speed); //Code pas à jour /* ******************** diff --git a/src/engine/math/Vector3f.java b/src/engine/math/Vector3f.java index 4f81fee..37cf4de 100644 --- a/src/engine/math/Vector3f.java +++ b/src/engine/math/Vector3f.java @@ -13,6 +13,7 @@ public class Vector3f { public Vector3f(float x, float y){ this.x = x; this.y = y; + this.z = 0.0f; } public Vector3f(float x, float y, float z){ From 7b349c573b40d1de360378884bfdecab29352db5 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 20:07:34 +0200 Subject: [PATCH 28/32] Added coordinate tracking in ObjectGl --- src/engine/Engine.java | 2 +- src/engine/object/ObjectGl.java | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 9f78bb7..05fc9c8 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -197,7 +197,7 @@ public class Engine { /* Engine Init */ - Engine engine = new Engine(800, 600, 3.0f / 4.0f); + Engine engine = new Engine(1280, 720, 3.0f / 4.0f); int speed = 10; //vitesse d�placement Object engine.init(); diff --git a/src/engine/object/ObjectGl.java b/src/engine/object/ObjectGl.java index 723cc2d..5c36237 100644 --- a/src/engine/object/ObjectGl.java +++ b/src/engine/object/ObjectGl.java @@ -27,6 +27,12 @@ public class ObjectGl { public static Matrix4f projection; public static Matrix4f view; + + /* + * xPos and yPos will stop to be relevant if you use rotate function + */ + private float xPos; + private float yPos; private float zPos; private float width; // To be used in setTextureWrap private float height; @@ -61,6 +67,8 @@ public class ObjectGl { this.texture = new Texture(tex, 0); } + this.xPos = 0.0f; + this.yPos = 0.0f; this.zPos = z; this.height = h; this.width = w; @@ -92,6 +100,9 @@ public class ObjectGl { public void resetTransform(){ this.transform = Matrix4f.identity(); this.scalingFactor = 1; + this.xPos = 0.0f; + this.yPos = 0.0f; + this.zPos = 0.0f; } /** @@ -101,6 +112,8 @@ public class ObjectGl { public void translate(Vector3f vec){ vec.divXY(this.scalingFactor); this.transform = this.transform.multiply(Matrix4f.translate(vec)); + this.xPos += vec.x; + this.yPos += vec.y; this.zPos += vec.z; } @@ -210,6 +223,14 @@ public class ObjectGl { this.vertexArray.swapTextureBufferObject(texture); } + public float getXPos(){ + return xPos; + } + + public float getYPos(){ + return yPos; + } + public float getZPos(){ return zPos; } From 48c0a66f110e7292c32b4290c721f8ffde74e856 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 20:12:13 +0200 Subject: [PATCH 29/32] Added correctViewport --- src/engine/Engine.java | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 05fc9c8..44d8483 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -80,11 +80,12 @@ public class Engine { 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 - glScissor(0,0,this.width,this.height); // La zone de dessin du background glEnable(GL_BLEND); // Transparence glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -131,6 +132,23 @@ public class Engine { objectsGl.remove(obj); } + 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 isRunning() { return running; } @@ -158,21 +176,7 @@ public class Engine { private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback() { @Override public void invoke(long window, 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); - + correctViewport(width, height); } }; From 9a93fafd0d70b867ddb3c72bb1cad9283d01341f Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 22:12:57 +0200 Subject: [PATCH 30/32] =?UTF-8?q?Premi=C3=A8re=20impl=C3=A9mentation=20du?= =?UTF-8?q?=20tracking=20d'un=20personnage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/Engine.java | 44 ++++++++++++++++------------- src/engine/input/KeyboardInput.java | 5 ++-- src/engine/object/ObjectGl.java | 11 +++++--- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index 44d8483..f8c3c3c 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -26,7 +26,8 @@ public class Engine { private final int width; private final int height; - private float aspectRatio; + + private float viewXPos; /** * Create the engine and initial attributes use .init() to start the engine @@ -36,9 +37,9 @@ public class Engine { this.objectsGl = new ArrayList<>(); this.width = width; this.height = height; - this.aspectRatio = aspectRatio; ObjectGl.projection = Matrix4f.orthographic(-1000, 1000, -1000 * aspectRatio, 1000 * aspectRatio, 0.1f, 100.0f); ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f, 0.0f, 1.0f)); + this.viewXPos = 0.0f; } /** @@ -121,7 +122,6 @@ public class Engine { /** * Add obj to the render queue - * * @param obj ObjectGl to render */ public void add_objectGl(ObjectGl obj) { @@ -132,6 +132,11 @@ public class Engine { objectsGl.remove(obj); } + public void translateView(Vector3f vec){ + ObjectGl.view = ObjectGl.view.multiply(Matrix4f.translate(vec)); + viewXPos += vec.x; + } + public static void correctViewport(int width, int height){ int heightViewport, widthViewport, x, y; if (width >= height * 4.0f/3.0f){ @@ -207,20 +212,23 @@ public class Engine { // Add objects to render String path = "textures/zangief_sprite.png"; - String path2 = "textures/awesomeface.png"; + String pathToBG = "textures/background_beach.png"; - ObjectGl zangief = new ObjectGl(0f, 60f, 80f, 10f, path, null); - zangief.setTextureWrap(58, 0, 62, 84, ObjectGl.STICK_TOP); + ObjectGl zangief = new ObjectGl(10.0f, 1f, 1f, 10f, path, null); + zangief.setTextureWrap(58, 0, 62, 84, ObjectGl.DEFAULT); engine.add_objectGl(zangief); - zangief.translate(new Vector3f(-5000.0f, 500.0f, 10.0f)); - zangief.setColor(new Vector3f(1.0f, 1.0f, 1.0f)); - zangief.useTime = true; - zangief.setShader("shaders/StylishShaders/BasicVert.glsl", "shaders/StylishShaders/FlashFrag.glsl"); + zangief.translate(new Vector3f(-1000.0f, 200.0f, 0.0f)); 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)); + smiley2.translate(new Vector3f(0.0f, 0.0f, 15.0f)); + + //Create background + ObjectGl background = new ObjectGl(0f,1f,1f,10f, pathToBG, null); + background.setTextureWrap(0,0,621, 224, ObjectGl.DEFAULT); + background.translate(new Vector3f(-3011.0f, 1400.0f, 1.0f)); + engine.add_objectGl(background); long timer = System.currentTimeMillis(); long lastFrame; @@ -241,9 +249,6 @@ public class Engine { List listJump = new ArrayList<>(); listJump.add(InputConst.buttonA); jump = new Button("jump", listJump, gamepad1); - - - } @@ -254,9 +259,6 @@ public class Engine { if (Joystick1Present) { gamepad1.inputRefresh(); - -// System.out.println(gamepad1.getAxisDiscreet(GLFW_GAMEPAD_AXIS_LEFT_X)); - // Check si le personnage a sauté if (jump.isButtonPressed()){ // Le personnage saute @@ -264,8 +266,12 @@ public class Engine { } } - KeyboardInput.keyboardInput(zangief, speed); -// input(smiley2, speed); //Code pas à jour + KeyboardInput.keyboardInput(zangief, speed); + + Vector3f vecTransView = new Vector3f((-zangief.getXPos() - engine.viewXPos) - 250.0f,0.0f,0.0f); + engine.translateView(vecTransView); + System.out.println(zangief.getXPos()); + System.out.println(engine.viewXPos); /* ******************** diff --git a/src/engine/input/KeyboardInput.java b/src/engine/input/KeyboardInput.java index 25fe04c..995b650 100644 --- a/src/engine/input/KeyboardInput.java +++ b/src/engine/input/KeyboardInput.java @@ -94,14 +94,15 @@ public class KeyboardInput extends GLFWKeyCallback { keyPressed = true; } else if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_W)) { keyPressed = true; + token.scale(new Vector3f(1.001f,1.001f,1.0f)); } if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_A)) { - token.translate(new Vector3f (speed * -5.0f, 0.0f, 0.0f)); + token.translate(new Vector3f (speed * -1.0f, 0.0f, 0.0f)); token.setTextureWrap(121,0,57,82, ObjectGl.STICK_TOP); keyPressed = true; } else if (KeyboardInput.isKeyDown(GLFW.GLFW_KEY_D)) { - token.translate(new Vector3f (speed * 5.0f, 0.0f, 0.0f)); + token.translate(new Vector3f (speed * 1.0f, 0.0f, 0.0f)); token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP); keyPressed = true; } diff --git a/src/engine/object/ObjectGl.java b/src/engine/object/ObjectGl.java index 5c36237..4144a58 100644 --- a/src/engine/object/ObjectGl.java +++ b/src/engine/object/ObjectGl.java @@ -34,6 +34,9 @@ public class ObjectGl { private float xPos; private float yPos; private float zPos; + private float xAngle; + private float yAngle; + private float zAngle; private float width; // To be used in setTextureWrap private float height; private float scalingFactor; @@ -75,9 +78,9 @@ public class ObjectGl { this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap); - this.scalingFactor = size; + this.scalingFactor = 1; this.transform = Matrix4f.identity(); - this.scale(new Vector3f(size, size,1f)); + this.scale(new Vector3f(size, size,1.0f)); this.stick_state = DEFAULT; this.useTime = false; @@ -110,11 +113,11 @@ public class ObjectGl { * @param vec Vector3f */ public void translate(Vector3f vec){ - vec.divXY(this.scalingFactor); - this.transform = this.transform.multiply(Matrix4f.translate(vec)); this.xPos += vec.x; this.yPos += vec.y; this.zPos += vec.z; + vec.divXY(this.scalingFactor); + this.transform = this.transform.multiply(Matrix4f.translate(vec)); } /** From ba7e093a0045cc15acf7b3f9d7404a09fe7ff004 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 2 Jun 2021 22:16:18 +0200 Subject: [PATCH 31/32] Background --- textures/background_beach.png | Bin 0 -> 67491 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 textures/background_beach.png diff --git a/textures/background_beach.png b/textures/background_beach.png new file mode 100644 index 0000000000000000000000000000000000000000..92598e8dfcdaf92ac16cb4a6062222e3c2fb70ab GIT binary patch literal 67491 zcmV(?K-a%VNk%w1VQm870Qdg@WAG;5Q84-W>Z#eem$~V1aGBGWS^4SNk+HFHx%lbHnZ<-n$jHfbGZRCp`M9{) zU~q6y5CZSRdH(gr^VOR9*~w~&W|=?$P^tOYxs6aTAo=OZ`T5!1ret6c07 z#)bL$`A{$r`TOzu?ZNfiqsf_IP*5RbN2KiD1desky0OC7${1Z~)rb!0^nBrKD=v z$(h;d>G|om*vYxc$%)#bUVAti>8WsVa8rj-F;P)JlvOTKKq0BAiTUQm!P%igFcRy& zbouk^iJ4&e_VVf3nb_H?*~zKZoL$$bapb*;x!LJqGZ?90aDzS{rn%zm)w^3L74p%N z;HY8giBS3O;OXef`1Ry&EE#ucLy3uSouFp<=FM#^4f5l|v9W#l>d;_tQ2+hU;iC<4K*4f_jz;pQW-`uc$mrX7~ARx-Aj&Ls!$)jWZ@xpptH_eVyw0%;8ODyfr zuY|bm$DMQf-@x+Z%+HEVULFqW@9gfmYf(fk&&Ir=dQ9lIZNGR#k4+@~0I2}Usi~RinVI=uiEyd8i2$jInVE3;*||Uf z$(fm20D$S4aBxvGP+(x0$@%&4&0n$kxR`K2AP_(>Ao%F0h)_W2*oZJNAeeAa`1tr> zKp-HP`2YX^A^8LW00930EC2ui0Br)`000R80R0IZNU)&6g9sBUT*$DY!-o(fN}Ncs zqD6%Eau~>wC5r)%8*}8achR3cU%qnq%92v0FMB6no)oE)rpPSD^5y&Jv7-S4#&YV+ z7t|)lkRef?T$)g$uaZ!sN}Wozs=qD#vI^NMB#hSq1GZodBUUWfFj>ih1&fv6Sh8fX zZVhvG%Zp4mYHYAbl7UC2Sqm9JuZ;cs_|xLw zH$XSN|MVQQTW__!@Ir55(Po=)FN9?rd=N$`;e;kRcbRjfC8pR%)@9_FNZL_mj7m9K z*3(BhjYm`#o_(}YQZJ>n-a#}`Xyc6$$rn~V0tkTLkNkuIV14~{b<93U3W#8VFNpP( zg2&+2pjS9nY2}sDS=f_vhiMpEde?o3-gYDU0+dcCYBrQk(4EI+j55N6P>opDd1G5y zndKFa{q%|CpZf&)Cq4V@MixGZ*0Y;fOe#s&3qjsypn+=HY3Zey&h*okl67fOOkaiu z*<+LagwjnLnMqVWY38%pW;wP0=@E#c#)%k>reUfpatUe`mTh4OkyekB_K9eaefG)d z7Q`7?&yr*%>*N4^M%wHE0+40TFu&}2Be&jSIo(l5wR9^*Cn1%dV%ZIr5>6^@v{Oz# zrPu?kJAFB8n={FjkeTg;EAU=;Di|DBL3$NNF+J8(&!k&T+N5p|_jBNUTafiap8{r# zPqktZ*H4eyf;(`8CZBAhrboG0)43C+i)yXbMdl((IHmN_PG@>#uZo?1_M&I%$vG!W zDkmKkYifCw7Fr3f#bb|D3m`ZMg=u!U@y0 zR>);VDZ~p7*AuK*_!PR8gIkookARv_+8?uh+LJZ5!%UvsFtytbA>D=9y`Dxf*VO4@ zeS=zeWu2Z0Vo--8jwVWbuZvw%PU&tvLU_^z^#ERF9Q9e6+jd)&ds5n47+`l@Tj^xe zWwEnc&_gXfJ=!Kf?$-kb4DR{6M>l4vLJaUC;vtQ&hz=SQ$Gx=#hd2Uo*ys8*I`ok(H)KIlliU|N*@a~QrE{45 zh{3_X?2m^%M2@EazQdwalC|BSf?e&hk|+SFOpD`3T$rX?3a@K`xPFq)lyr z1;W~}WrSym(lNroBOZ-yj(-|mZ4gvPW$j4-vP)Lj@<@-3*`^=eLM2szvA<+0^Di)Y zQQZc!5yXU%A(D*OVZ1m*?_5T34D2Mn)?^vWghVhdv5rEj_snpyrYy5Dqgq~>uvrpE zQ4YJM>IP8%27Ks}EEtPRvoeM)0SMD!0`Q}>j**XcMnxFFh{G@%>d>kLW(CPGm;57-m&unLo$*RDxD1KD5YFe7Hf2 zENPj~jUnn!_5sj8yA}p~M9E=aNftuK7A3G*j9Cj2hE{cQkFKKNt62$aR=RqRd}#F- zXmutxy8VD0sn`9V|ak0F15*1Fbto0cb&+)}aU%1!%o! zXG<##ex$g+Bu0UcfiWri7-U*-aa?wsK-huI%|&hwuG?Pm-F+R%Llv!N}F=R$WF(SklSqZ6%V zNkh8Od~UR&GfnA7d%4q=&M>G0T^9K$Y;*(aUiYLM9PZ`Qx@OC+eg1?fMD<2dyHONb z>VcPO)pBfoGEhItVAb`aKp0=$D}URH;(SP0Cng?kfA`ASy6$(iqm3~NoZaj-={Uz- zh4wE2s70_ALgn9y`I_9(f9SIz|jkl7b04+7C!4(OyW-Q-QT zu+mu$b)jQ;>P4@5(y`8Ts|SJWT9-NjsP1yHlRfGxAA8ozp7yhQ{poC1y4t&*@`CZQ zHBJH!bk$-{_z8i9-QCB3lGs7G$Xw(DMhrDDkvwx2#`%wu$Q+06drFC;$S z&9k=0;pQyBv5jqJ3f$iFg>PA(Twu@UH^K%|}ZV1hf?-5|a^>NU@KXYc#4qAxe; zS8MuhSDVKA{jcsPes0ZwxZQaT@MniF@sIzv#Ty4JXhXi{k#7soW-@^P+^Nomre7H5 z2u#09X>N1yaKu&Rk2Z0mlfOVG@cW?*d!xhoRD0&wxd>00w^DzC9Ea)?9h4(SRR)W!@ zB#ehGibqfzQ!J8aG5Amh!Nx2X6>;X4Rt8pJ`ZZd_&{m=6dc>Dloh4epfPKJ_gc${2 z`OtbuSbgTkZFEIic;#T>_G8EAZ^)-^_rOe~<%0+ogrqfuo@Im@SA|8Wgs#_wr$>BT zIAIj_NqC4>%l1`gg;&D|aexR~q-A}xr-%N<5BGpOL)3i%6bzvMg&t`qbXpe^pusmf zV^W*aewA@^R0Jzu@-8Lf5s)DhU=nl)D0D|BiBG4BktlR!Cy7+YigMR-VF!y@CySD( zbgw9Mu_%eHsEbi&i>i2vt{9BGc#FO`i!FCyZLxv2@iD=o8>r(wX4D(EkukRP0{b8Y zsuM>@QfratEF@zWWW#vJ025h57km_Kk=G~0hEQ1(ad1d(tECe}Mq(-Eh)LLaZYYP& z#!SQ)g~>LB7d3oTc#s7q45zhY1gDVO)?WvSZTV1o7pGSMIb(cF6Eq2M z3MY~yc1Zg(aSAt^%$Z{T<#|8GVvunnYZgF6s51~Zj3hvb??OE2Bs1vI5gSz*E0QAS z6faXmFINe4VhIx(8gxNG0vhmj<>Ct@;Fl(+0UxT0L13bIIih8mq9>Y*Dr%r4>Y{8( zqcYl}F$$wEDv2zrmNu%RD>|bZKmuO}q$SskhIyC@Qx~?8F=^D8%+e$cV^rH{nc)bJ z233P*!E1?^G3+Ql_0SLb^gdHl4><^ITR@LKS%z@aaVIv07ztWW2#8ELhXF}%-RYef zIeW<_Wk0rTL5XY*Ig!PAZ2RMptVLRS^@bt;$(+~*gw!c<`Z!VY2&bVXr#%^3-)VeL zc&E!bn|tmBUX_36%6^PM1K;?Mzq!wD!79n#Cyox9S2df&V2_~+H=Ko$thJPD%8{EIo}z_pWH@|nMR4Hu zr({TOBW7c(ms+kWW!om6Q%0#HsiyMqf zS|YoirI&hzwQc`6vP3(o&}N^dWs=kRgs_UMxXMiW*;%M5TEoC&Y~@u#Ic^}=5=HbK z!MbF?03x2HojnORGm#zXr*l`y6MSPpC8ivTZ5Qjk&I!IlJHA9~z9)vhdAh!&x3YwVhzUoX7^$-* zhE_f)w8N0UCV65^C|YCawH=&domYgoT5Z5dkSPYh~Zpd1mbGqEq2(Kka(6q>ZG zDd8QzsvV?AJk?~nA6i_f+qyqWx;bjkFN)7{r_UwF&+|;9^$ffBEYSHZ&_o)$06nCd ztHoJiPdLODWFcO_vPvSvuwYTflVZo$D~@X{F=bk?2RkW``967c8;XYpKkx(4O9ekr zUOxa1Xz)G}N2pBy_-{$Oc@VWf`^#2E7|Q|2kr<_`iTsmLHVnE4w8`9qj9jtFrjSle z3_=ODOfAY&2$49+VujUXP1s}1d8oo*ti@WfrDxLzoYO`fpFKTpYVFL43Q?mq)O6)+ zM$KPJ&B)s6u^DWVKA6;Q2&%;V*E^YyU!74MT*+H4l&vK^N!+ctbF0Ci5k;tz+uXra zHX82&&OQ9AZ&tVu3Q9h4i6WuS_5haAbQtgat|K=R>58uHN}}Z2+GY9Ltj*f64X^2H z+w7`z1+#$-Jxe4sOU!bZ&{b**Gan@ly-fm{4f8PYC_5hQ#vbi3&|6f)fZymS!dtw}%QEZx% z2G*(Lw%*BBgbG<&C3boFIgu6_WBI#33b|mQ7Ys5+%B}~YNudE%tvlLk@M53B<%UK|$J zE#1Wb0ljF0HOE_2A1yJ?ve9`on#VAuiJnJNpxxlG>1fd1<4pzNKn3OX3rk(JIxNgY zR$4^3$e@MH-uc&x3WOkxo^ea+OkK&qDY8;VVo#WzAW32WePcx#V_iLkx9V1%JZ=ka zU!-1;rasw$7~iX2wCg>$s9v4Bnq;$XZnbWPsv5U!Rm@uZgl;{u09l_B$1PtC?%Z;o z3TIy!g|@EB)g@Ly8!_afqLadq&0oze+~SBzZc=1cWl#PQqv#Yfhc9oIPJvsMKw&CR zR2`<+qb9mUD$&nE*SHFe@g=A6mpjh{;PLyM@sYdnATRP9AMz#t@f5%EBj39H{POkx zEc5qF^B+pP&L~TH(mlbQ2D2n7ci~R}bw*z?9HDd3yw)QO)9B1iH5;AB8!g?{ok9|G z-4`tdST6-M@B`Z2>7d@}RD*^~w#}ZGr+=NO^eCxnpKaXUgXc-ZX%%tzRmgzMWTc$4 zziD5@saNpMEn=m^Qr6>g?QHq@%<)~wDLeM?y|KJ}_LAzcDht$V?e72H_Hn=BKWN`M zyt1}V3~o)F`TO}=t8k?SwxmyndcUd!31uBO-<4eNI&&0n#@IXgwh*-5xPPAOJ&Hxt zF~{3YxcuwWm70UHLA*hyl+MvgoQGFVEMEPtK+ zHIt@IV!wig)LAnm&z|{ero4AgSg?HecHRRiEGbfhrJYbx3S8` zP48OO2~3#BkCi+6RQoGx$Fjrn9i4jbt36*iR2#^WqjhUv_D~WVmO97(yU&f5}$S1vezAU~{OK)v2hc5%h3_$;$rFd}yB+{?f zFr2u(_3G7YpsykR{rdLhuh zEshCe!vO}^B8&@MYYdn+h18EaS2_t9DBB9u$}Y1}vm#`I(@r{9y@ydu8zU4c-KOGdDioX>@3mc% z^Mx1^P9i|HVN4sQB;INRF17Qtb1gjOmNU=UvszZ?>GiS4MFTs#SBLz@!%~|G;xa- zFXT|hW9kvWo`GphsJI;q@>pYpJeD#@k1Lk4$dD0w;TS29Y&oJKMnGZaCkL>&o})y) zv$xBR;t8*gdM@j-s3053saHp}tf-{Lyc1G3xl+j}VLDs?O0AreD%!Gp3K+b{^~OpXuzGte&@y3~4U$s=6qzpDuc5$lyL(=h1?xTc@6ncFH56 zjI!+Rwn^hk&Ycq1bLX#w$}?BzT;rCz;d}`uSQ5Z}R5#jQ($2Z!Vsnq&HgJbb z8x0XZl9Ur(hEE=;S{HMuII5M+FE@-@;W`)+$9?1;!TZj5jIq1epoSRfA%+HyQ;nPq zg9JMn26TY)$JsF_In`m#>{v4#+hHeK%Tdi6m*XAPXs27}@lJ8fwV!mUD?R5@kn@`N zAOsxrF}wXDb?-Wp69N%s8ufv>txM zgO71a<=Ck;PPG#SZ7Lj>s$@7tamgx?SriJmmzB5u>4T72Owx47!yf8s7~X8B5XD&( za;^oU=Umzl*Vz=V=y0HR+LHy_6w%R)Mul7)p;Ic#D3K=gahH1xR0_9J!<}%A-uYGz zreh4%s4GF>ss;gmv7X@&V|H;gq-(OENZvW?kT#tTc7g*soA%(5+6j+%P~*ox`e!`f zDV``x*`Ti`&y%J!-YV%uAWnkyUTK|PeAo)0dBorZCoqB$P7#Fsd`K&IxC1Xew1tGo zvJCVfEIq=YOI_9@L%qZYK0*Yr3kl)>MIS;)FZ+Q^Sz;ENo8>Gtr6~mzK!gTBux3WG z*^ea7vxek+90b!sMUgD7YFy(|pB%Rm#Vrk@S!~l$M#2;=CNY7U!)>Y>Lqpy0X(Ze` zmTuQ{G|LnVf)(5*FjQL-=n}1j9bMwlatK@$+LoW>Y|P$(TVAI5mTSSS;>`L)T)cS^ zg|!vF*r&v4{p9HLU|sfujfaF%*h zE@j6xjJy_huKLIdlP8XsB!CK3Ks@x2xIpE5(f|baqQD|(h*D!_22s(36DqHTAUUy!MI`c#yy4`U3fF7h+nSfU)GdlzKJ`U= za=iTUrH@w|V?|G+N z-s`!vnsDV_Uv#jE^&<@c3xmd-99R@J%&}8;tdlde zGGQtdU10y)tzi z3Qm|0qf;r;e#W3@cvusrtNJ9zdN22cQLLiBxiNU5&EoR>^P0bfQz%S}&UqfE_5yw9 zY3?DaiGJxmMaIwX?b_M-yiXO1RG&uCCj^3&h}=wgIZWI?pM`jo2ZM?~D_=5tlBLDmYKT?Y(Z-&wJnjzxV84 zZ|-`_KKA^!z3y}WPfFO=TLT71cr6>w*N6XAMHlJ^hCZ~SV+_R0>HFRmz9;3zIv;(& zgx?m5GcbuS-FTmua}^WnmY;=azE>eKbUx+uUHeNxxdTEKh^rc zr0G9&y0jCtu9>+T1;RkKo37YOsVw3YXnOPdS>j*x{hx70iaN`0#n1h2WJ|L@*gLxQ=84-$u zK9$KVjw_KQV~ERgGW3Zuh8h%-~a zj9@b==o3I=ijruX!r+@Ufs~Pml{f3H^5Pm-`>3^Z3R&D6^r9N``h~a)x)B7ziGm<_MrLFR0c@4Rn45Bx zwUFYwi3+Y-`!7EmMkGq9j_4C`fsWxwj@K|SQ|S#7U_uf|fMf`_gj^PTAU8;&s$LtH zfD9M^&&#lhlq9K&B-=o}Hc}UIaSzmEJ%>C=luSvLTuGK}Ntb*{m{iGmn1BhWt45dr zL8PUI;~s`t#1{b(Mf}MXF$g4UtO1}0DuYDFN*`nj5rlxO7a2LJ)EF8e8LGU>tE?Z5 zvC69~vov7EmUFK)LxY&3p+f7%GP)B^gGV8flXwgodE~UU*qa=ZEl(px9&)d$alZp} zOXRu|91OL4;D;&Vp|CTRV;Kh9l9NQc63a--(nuP%L@r2K3%KkVDnbkPGE0Qw%nwX8 zGcilQgcPI`iqb@jpfSw^qMAf2L4+znAmpNX;;Mkew$?bpkMJg9U_t_5$V-Ys;2018 z6?m2o@Ez8Wj;XQ-3p+v@G6rXPqmBeNY9UF>TOIG%syJf3fjbx9BR1~jy?FahfeX*u z+s^VN&+fdW^jwc1-~tFRg;baTL#QPkn}9*&hvU zOi^$$OQ=vB8HG`&qarmaipBhjpi7$@_g8uZ+4{1Jtk);eN$^u2o z@A)2skjmyOk%2)757{#G`PGrxPz$A>E=veuJqU#$)>Q;i5w(a{j5(gGqPJ-^ebUFK zgV6*^j32GcuQ0kL61pXdQT{75GKDRtQ^svor(;<=t(X~pxH{CNr^cK{+JMucGaI7m z8e1zb^Fj-3Wg2bmMbzA)Z|%}IbxqSK*K18!(^N+IGt+t6%WRdPDkWI|&Wu++X;+T` zQlk@w)=8J-_%?gUlDk;Qh9tHolr{tC0OC*q@bDFzs*b73spq5)oT8*>n-17W7vJHk z?=Y~{u+&TCRH7|fqisnI&;ofFRZ_*zSGt2!C9>z^PlJ)T4w<;c%0vR4RVqueTOEjm zh^2$c)f$-*Av1{R6OtaeRkpoQutip6RS35AmqI7!}ut{Zhk?$0G&T#@W`MNet6;uXue^a+J%H@TVK<*xnchei%A_(hcl#i8u{h z-56X&Dco=+6o~!CXywI%eO>MWT|*&F%1w+IRZYG;&5)WWr~9t|rdiXuL>hnc3MTzr zY(=`u_*iklHq;wgmT<_EJz1(c4wj9`o+U!=Se6{f2W-hH-uWZk@fJLlu=fDAG$esR zJzDl{-=oEY320iKJk<(;+5zAP4(SjV$&mgek%ht9A<4ukLrPterLRSqmAR~e$yIw0 zvXNs5424?`ecQE_+qN|bV$D#z&09Bkxv~6#viya1H9GloHOKimrf5yo>{k8L*1Rjg zXcdYPE6H^!Pa8791jtujosxpSwdA9Kt$*rPUk+e<{sDMGWhk2NXaI<4#qhu0@ z=Hy16WKcF`ORj)msYLVTiqqg2usiy`ebSIV_?g$)+WJZW=RfoE?VP zS1Ij(TB6+WjCNJV*?kPr$f5~MOxISF+m2}eAI$7D1>??c?S}3-(HG#k-ZeC!`U1LRd=eaejxf*^HFY5n7DZw*4+ zl@noj?jLPeM+0w}7T(E*ZW{7(C&%6YBNky62Jg<**RQcT&z&bHXA~%hiovst-L3L1 zzjA+OT?pdxH#2kn3v)4VG>BbM-%WIf)jQs;VMj;09S(DMg>>zHbTrl#g4`7{JfmPp zfHbUt>@B_67|w2cHZEx-LSB|Z_B^SIo$Elhs3sSp>hDt?)C7<41D|kQXXOCj^+wk9 z1#fU)=XFUQb_0*(C3u4+Km-Sv03WLZrged?_HeSk1N=3Z0k9DNOoP9IrT;XaG>9@- z?GOWoV34WMzGli~-ozSt=CJ*kkg>|a9_%3JN_zhod=HrbdKqdua>jn_0muk6wWt0Q zjcY}(H5MZG5K2ti$`?d1#Lc|VVVwE zK@vli5R+=CfNJ>I)+mNbf~4jpjzm7H9!P-u77t%&PDgU2rGm&miX;E707q5kcd%353!5{p#KLsOjfv;Wy2XKHT&;|MB z2N;-uTX2D$)OGuCUIPNwz@ z$oC0<>fA z?)^LXVp7JBA422&`843bp?UUf!~itw!42a$kfOj~!-TdJCTwCp{{7?qLK@dAmTy@Ubw)I zE=z2-nP;JWMjAi(l(8$XckGG}Yh~hRN$KWPh8os608$Q)qdo8xv zR(lM!*#dyix8RB^?zaG#doH>F^s_Fz?YjFeyyT5XgL&xD;NE-j&4&Vg2Qlg3FeNGo zpo1bxbWlY1U4&neOHK&kluY87VTJ`o#38~CFPx812kAE>mKQ(dpMD&}7~n56{=%Za z3`p_N3?Q=QiTkONyKE;KB?7F~m%dE4s&6Y+# z$R>LXysf*=db;NRVQxRP*IqjSf4I)B>b?8^JMgN@E5&(33~>DMQ2Zd@zWlbhbcHLo z#E*kM7DO{j9&t!0p*v&b<--v&e38W~UFdMm*`wH`iAY|rpN2F7vwlVm1~q>{Fp4<; z%!y!?MnW|!2JaxqvwWMV$xDA0OX6uyw?=NALhSwa5eq680p>6waxxR~N0bvI3pA_kJMEBu&A3+EOUM&WQ#PGQuWVE7b# zUJWNB*##ZLG-#I4PCZF8u^|^D7d81;?f{0`R0{`*4q0l$)5K}p)bJ3r#t~FO+5L@ zOdtS5HW4&WSm{Alwsy6%C8HW>gNj%X#gmzI%_wNtul%TlXZj4ioJ;u4&|taOgkn zL_x_=K#cP>=sz40hKPcqOkm`LMZg4xj(P0k{RH`X0n+T04}#<;%Qdb|{@Iou6x+{o zsY5V1t)ETXpwDb@BDk!jNHk>V5{g6^KH&$M(?r9Y@Tn;IIEzg(eZ)}>w=2bkiVwGD zmYy`%7|CGh*^FVRq%h?sKiO`0mnbS&v)8|-*s2(cjwv%v2`aD*S+of}+|k|drGha(M^8tIwE zQtMU_b_kxV)JSNIoG{W_cIMsOhys_!&51AtL@De_S)5{w9%Mn%0YxGNglm(eOt*!( zHE1#lwe=zzfT1|4Mi#X46*RGWDqOpD);py{y=5Kl*o}MEXPtMsi?{ArzdPXV&iA|% zp70wuJO(gO3HOST*q|ZJ9cZ%~KKhq+3to9m~JkijP=z%HQT=WD0p+y2Kr~K4Zq1t*%E?SzawA{Gmps{B7g_O zBm|$n$v8G3vt}R44_f70c^}lA9{~PYN*JJ(Xx91coMnZ~m23%VIpAfH#9k@P)G(br zxCjbe&DT{L)m=>obU<@e0|{0GL!DYRV9h{b8l~k!*j0t5fdxa^!>MJ#sU?6hNCn;e z7FyID-|0;P>3-6;UV1}I?@<{cCso)vBY29UucM1m%4 zhOD5JMt(7uyj3;`cG7(5i zM1=Q<-^Ey*&TUi9Ar1Hh8lQ0qNl4i#A_OvxnPKf;!hji?i5xH1pM!KFnUNVNs+=gc znL!}nXR#B}9LzG>(w`yCD~8bdU<4~wqsTZQHD1s&o)-BvU@PJb3iw3!6xUMR#8)gu z2PD7;@a1p@r4P7Suy( zOq;bK%kd;f9`+%&rQu4>28B_Qak$q~obMMM1UWJDT9BC4&kOR15Y1auv!< zfCX11gFUEC4!maCHASFQR}VJi+!Z7s*d1{iB;XMqazX$_VgM{$c&+Ss57rd7HUC8D!x_!b0Lzf)zUF zL{?;Ul7SJN0C#%l2}DBUfrd-LRIzYg=Ojyjg$^FEOHd)pa$r~*KwE&qr0NLLsGe%? z+-En4KpKdE2(%ll>ZGg|M|qG3zrENHRH7TySb`p?@)5*PMAP%F1f&63{$M3V3|#&= zCN##xSBgoqifEN^NJb>1pJB;;NUO6_<1X?Tgdo-~9*LOjQilX9jZ#Qp9xDYZE5|S^ zH*TwjYOA*XT(z?Q;*|B=lO}03F4|?5U%g(YwQ8sZaub!ZgvzDGPUMi+Erkh6mvn`L zZrX!8+QU(pra{qWSp3OXwCQf*L^6n=0R&+Ou$r3;XW`)~pQfzJ=G{apB%fAcC741a z)ECW8fFWqcu-VET@X;I^2k77tf(;l<%G-mP-T*Y%tRly!CN0wv2dp9z7Ki{AV1Xn^ z0v2$92o$B(&IG(w6?qInBpzRj9cY070X5`mC59Y}SO|qc5QWBwLjF0auHRZvVMz%*m2O)q8vQ(=V^-_KQ6|!HQ;&FAR}=_;Y~a@vMGgW~Z=zrc zf@zqx=4)1L2Z9B1fd$)e1;=W|sfl0?s6Yb1MLE97o$5`VuB`Q5@1B-QAj~X%&B{tS zfF{%|ecb^+m`14ftc7W+w6q4YoE~-*ZP8-b(fVw-iCgdeo{HtK{(6T}MeWs!Ky-)z z)|!}e?C<_sl8Yf<@-gMEPQ+7IA~m4d+IA4b#E6q543M>}Fvd)Ua3*4Yk2az%2y>>C zWMc+xuF@F92;VKUmI!{>DE)LJX^DsgL#{w%FuE=im$j<~BgB7nu$9Csvrc0OvvBAR zF1d#P)6XHP>5?$UVCMRa>)vW(k80?VbOo32$CchhKB%TIsK5>KZtupURM=2cxR65S z(DAZq^4cJ5CPUeUpb7*^8T*1k${P0Ou^wk#B?Q7pK8~%_K^a9VKP(#?34p1FPP_O{ zchtsqd|MqJ3#q;UcDUgq)0^+zp&P!NCcob6g`0MKvhN{_x=;req(Rh9N4Ydds}gWC zP?&baGAz%sEX%S0Kw^2AhXO-z1NSQOtywh1fd+R-U_#pDhE_44oYnrFY@L<0{FrXof;VT=501~-Q<>YI_DBaAt1E$2Bh>$$8<}(G)%+vOhaK! z%k)ggG)y0!7o5P&f@FNf3i&Quv5W>HzhoYop1k#rxlytJ#D*Kzq3@WUv1pj-ZE|;9 zo9dMthJAG&hMR1t%ZN=a)^-Dk{YH7p9tT9NA-0>bc!%fJ+fMEzygfc5OW3z;X#1<2GFldBR3A2{=*vIz36NPLx33WEH z?i`l*oa=tB_T;NPqX;(JRx~RLRb-7rJMU{&_ZZvb+n`BPFv_6($=kfm)qHdgnA!=F z^rQjQoftq$%Nk45G*9cad*}2`zqd{Aw4okeA2-4rXa*Pt@=EbTYQ&_4u|~Ib9#bEO zhRJn3#Ks;X?L%~qRZH?x({)^L*oM*My!D~Ht+gXb0xGX6beKT7=pHHq@Q1M*9X0J- z)2h70*oz&gQ#xhyO~l!zK{x9dS)B|D*l0^ML_$EQzaZRR865e!rQQ<%^ki4#DizrP zML@d0l1ys^F?UA%uqn0eWrp^d{V+k4h-AN3j@)=-={S#<#Df62#<`Q5ahcBH^DU`4 z1U>oCIoSw5IRHgDMojr|i_DQgW(4Z%Vs|6OW#eUD3_?GUi7-WOsoGW4gdC?$@M1Uj zu(6?+Y!G>O4&mn3senzGS~ZOHQPjjfwGciTKup8MeY^DG-FK;1VN9R86`K00v-IJ) zdUayJElj{i)`6|KfcI(!`O-#!=TuL1+i>ut9xgRaW>|yOZ#{fQg@^LD?V-G3GKI&r zwA(c%_u*R0p4GOsFNi>hKhlS#0oIy0imSLJ4Nvj47z8sguhO^_P(w)s|HBKf2+P=q zG>sy{MbNN*tNK`A2NTf0JBe+FE=f4^S8ipGq=X6Y6~e`-SD~w;y4I^Y z*T=fow>m^Bsu3*e36Q}p;4H3(2F`BAV?>^>*M@rrSR^m)9^SozLv@Am15G}78C<)$ zfi>^}J|8B>{Z_lN++jU%ct3dfDX*$8sGCzY(uWUlxtlw3jE8#^|KDCOWxE#$*sdR9 zY5CgXnba({ix@1?$hISOa@*1XGOnQFi2O2~UK5L%a; z2#AP2FbPEIx6J7qTsuh_>zm^1cNtp#HtjF5?T1rE)Ky)0P-+QVqT-Ug8!I;aqN5@kx2D_N$*fT2<#BSun9IB~)V8C8fJEUCi} zXwaTLbpgF|?AU;Q175tSH=v#Xr1hvCqZ(DfRjg@>Wpye5|14F0ceFZvk@f0Vul1TX z%^H>}T(D@d&P6MrsaCsa_u=c;PtraSSVVLyY@(S*d(BLk5Wzu&iEiB(H*TyIGiI}C zF-!3*<=L||X=n^FJ%n0nH*SESaE$^SI26Bv<+FWz*u8wgh5@sU;vPR>uJipe?)u&@ z6#R<+%9lK!uwOxi<>RMYSap8OgY(mlB05m;-@%K&M_hb9VAQ=|2P(`v_j~tv53@ha zb+Dl7fdw0`ytsU3tL--1a@(!9-+~(sJmZuDPC4d`d(JuOsIv~c@7(jwy7AH@&${i- zD{njX*n_V-_=Mr^z4_p4Z@CA-i*C8?WVG$P6@x+U|Gew&5ypTVyaUnzU+lR@BV&9C zGK+ldF#seZRWM*9D2r6go`#^z;-er3%EBOo5L(C~UzRi`fn-WDKn09)$dV(EpbY7x zl1yp|&pbt{1Ot&?`co#FCKz-ko#yDN4i|y~$^oK`8UU#Qm;#HR0r&xHs<^;PJ+@PY&G|GfDE9&X4N6{hY-AL+aAo?-N34jAA3 z<0stR$`x0-a)&v$H~-dc*EN2eQ%<*)XA?I$f`Rf4xa-yn*k6E|v)46(mor$zgu7F3 zx$GSF*Sm;YR61$bepwL(qklfm>6!t|!hjLy`z1(zpfu9AAoDSkqa3mrD9S9i+=xrX zzBCByC%ruLpdQ9l$f1YwNwWj2+sw$9wl|`)P8IId6Y&jT;`7fx$#@(VnQEG#kwVFU z#Slan;$J(Nw(IgdMQA>d`9Vl9t;)m8_(r`T&T3vlrFIQcCAyr&Eec>3j1c((W z-kahFDSn=%^_r}P^+=M!di4mhZm`5?|1c5kiGKR*wcmbv&#tARv>`$p0(@$^W$m@s zDl~3uVeT77fMx{9xZU-VyRJdo$X!`C_2A_g1vk@;c%ZhZsL@O~?Ay+IUbC+n4J>La zA{UK{7M^m^r#`i*4KU`j8x#a1T*AQM`p6Zt_r-618SBk;rgNSE6$d&K^k0N_B)||w zEoDJDpnwuct_5xfIry7d&muS*?4+zZFN#|G-UBrUL5N(-X%2Cm<3c4FplV1u+m#*! zj2z_SY-S5mk#gWAdpM_zPHP7+l&@ zpEh78KUHFoCn2Qb5V-+9DN=Ec|7;uv9#_dqnt~>Vs9a7ScLh^S08xr!)DnWSg=1_X z4aTd~7D^Ws)CDCCuRI3vis!n~#4akZ(u*!Tg_eHcjxCxB3s8{KJK^zemb?qfEQwi6 zXEp^NegTa0j@6hnL~k^kyF&TP~p9VyyoX85^|(ZsV*V(>6r1sf4D0yrOk&1X2- zahgVflQH=0hBm?gp=~x8z>I!)@^4-RjnHip${mJo z$Dt5Cj)+`CQ4T)LM;Ub@|3}#cj2HdFHy~wU6zL~IV%#fXw25MNqN5~XEXe>5(uhD@ zbFX}SacpwL+LFxHk)xg!Bv>k=8w1%Tfy}W7#;9YNmZT7ltkq3MvWGD|;>boS&Q6Q0 z#9{;Jm;)#`M?8L*vXrcBWu;0xnnf|w zbj3W~D`~~LG~_^bv-?XhDaDU|Ec3OpCFX0JxlCv7V;_GJfiFZLiOCcT3s~S)WU6OP z%2>t(rP8i;Jp;ba&|q8O9ZhOpL(lXX2Pn>gkN_;kLGut}YY^I({&2Lv;uy4HGwV@w z-1oEF1fxgyDwu#W|HiHk2F0Thlpy;$>eQ%(3xw6#=X#@kz_@BYh(U~S zIW1fmeU31^iUK^&sUa%xMF4|=RxY8<7)AQ4TaW6IHF_B$Sq7tB2VxN0AjCFyyyF)G zDMlk|*<5$Ue=P&XMfXo$hTx1Lu4}mBmg6`Yoz%YM!t5_F^j@bW%!CV z$*4UHYYzk4!qN7QxV^I5e3Yj?8h4Lg4B)a(2sr9y_s!zL0&Q6+@nZQGme@3sDdm=nQm>vGLzbBBzqw#BNzd5L3{zmCp*N<2}v_w+04f) zLrF;|tOW3_zI%ZSh)dxQ>Ay9rYMnl<-&AftW!)C+YScYUsY+`%^;Xa5qN^aj&s)H~j zs>}0ricdAPf?H| zfWzSQO@w~r0DlCk5b(ob4r{W5kL=-qJT4P+piL;S0^O#J<|-aJ&;tVp1Qi1!&SsC? zq#?{KOwtUD?x@TZf=O)SY&=4+=45eR!s@VYAz{J?Bk~3#@=rDZ6NIqsiqHjI;0TR? z?U>N*bYbo`#|4TIBweivBaOIXEh=!QSxQY+zOe1Y(Cx@@na&XM*6=WDjq+-(83v=9 z(%`x*0}q4kGxRW9NJE`QVDwB+o{p_XqRrk~#y-%4$cpUR1gv64<`s?TIW&=FG=`*j zBRHZ1z>1GRxWmG_(HrmML3Sj@egXXY=@ffo-N0`cgh76;N&qbGH#Dd=|3*Z;SSVmv zW-5!LD$C<4@$#zJ$3Bz;KPE^S!!rB&EjM=NEY~e9uVXDON*M5xD?cb@?qx2GgT3q$ zEAw(b^3r|wXXRo>-|})8wB$LID0ExsnT*yzua9GCns4C#Oj#tEtvFU^GNPAAXVpn#Tm%urhM3 z^EN{>t^%D#AoRv-DZNDyUqeD}u^DCq6_LXei;OY#Z8}CqWeiR?{}N_5;LD^4q&{+l zH>!ik7*H9*<*gXg_)uV7EU`3$p&2Yjrcx6u_HusCqrmnliX=q*%2K^v3Pg_#Lezsq zugygH0Y%T{IlfXiWC}_9gQRxx!Sd3_Y*Z6*w1aeX#d;Kjel$oys7m37T>PVcjt~5V z&wXT*=FX@%JfdXg=YW#&gM2{+fZ=cc1~}bB1BY`u?ZGyH0U_B2OMJ8FvP`WOBIydE z%{n5?Hp1vILa-VlJGT?-9CDHZfzVvw4ak5z6~zS%0Ry}s5F+RpN}?1hF@2#-vCfI0@h*%wqOwuVHK7{i2;QwhBpYrVs??}+%I;N-;0;oNRbjyk2(3{fp%KtCSNqm)|NnM#ezhM+?FFLgm-urG{WjO2 zwRxha8Pb4zmP-=sq1IrKdpu$Tisy1Mz1wCG=Helsj_iOWh!Cirz?Y2 z-)!o`u7eo#fp&$#4)CD~q9Hq?K_8+a8tlLhc-N_fAsU(>cYzleeAjq)w|H~6ce6tu z=*M_zw+VoOc8gbeeV2Ci0fjsagS4$0UI%0R-w%2xX zS9giGcYil{qjz_W7k`ttd6}1gpH~>7H)Ez(AFB6ya~FGgH$es9GvTMjz)t|=k~KkS z7yAhS5kwU~jKRE!P=7%MoI?eKp$W1?QOhQ4|2^WNoCH)sl^`Z?BmAgJ%w{2)1kDEG zAnIzcpe`UeFjN!L9>$YZ4TlVPq9>LBiAS=sDCZ^u;R;Z7bMm$kXccg)xUz0R(R2Z{ z;LZUw;SDChJ>PR5-r*e#pa%9~25P_n0$_|)?LA!}5cU9!H>Yz>pb-)!D9Rw3Oh6K* z>sUl!o8WL-CBYXcWAm~Vk)Nfzh5$6YRa?CE*qV*m$_s`vhBoNOg`5N74wk*HiZ@#K zUyLYV1YmoC!462cetFk-fmfBY!+3Moc73;a^#OpLmzD>Zeh!#=t+#oVw|8l`VdH0Y z`?BAHLVQ=QFq`U<3oL&&8D~4WKiu^d|3le_n1hsQ*OXCtckh>#pBETjS$Biimus1K zn*e%qxe0c;clmdg85k@c*n!VQf+^UkECx5*Wn@N5q_A>zu_I&5Bmo3K1psV>OW1_j zDg%Yi-aHUguXAe+a*Vb%uRQgJvqY~7f^8r|I(^v7fcR`Nz)p&|Q936I>8>bTAOxV8 z2pdI{oS;#{*oxm6i%Y8xItLLNArczpZ^t+QYG4KeUt|YVq}+Lh)e*YDVkildVwLD|71CMaaXSeSb>{hAF=}WNcyLkm$ zc?(+@4x4{**R>Cuv32{geK)cvn|p&4{F=dDTCW*o3gJF;f>jaxXag{dEMaleUXIot z0y>26p`c?Bp_k+~4-g^!$cN3OjLvLKPH>{3(@4rYuSig@%4WPf+RN-g(M*9mhk~Sk z!tGww5Xz3FDW?%8Aamx9!1>|qiclm^QmIL@rj=MImVnU;tqyK=QMgzW2IT|>1&Iy3 z4(b2~>Y%_KytKwx6lP!s|K1^}Yk;WV;kTZ!!W*0B00yLor&kzm!SXhEZ zTdwKWnrHJ&z|;^~kdHi_mXe+L&_c&+*`ShKudz2&h-G3^b%!BH&*OWA0|nsgs+hyA z^#LE~L4fafdsjJltM`??Id{|fme<*qGv<0{+svuAoug^EIRImAg>Z4uBbDR{}AHXvvyA#wINgi1{{DSQ~;Dnx}^V;zz0R#2gLytg}_Bp7eHK; z&VBLf4k#8piodmb3E_`vZPD8|^tXQ0Gwz~GB|lp_4yUEI|Y zdMS^&!pE*?3uh` z8yJ|m7c6Y!dj+IkaZ@-3-R7G+=Fg?ASuucazRSBD;dY)FdS23jUX|^fcZ>djOC9Om zTzh-@fUWoG|MxzD?|16KqV*gY)$Pqb99X2}=i0E5-s~A?ryGUf>lbug1#t5h4BFTk z0&Ri>bKQpKIPk9UMvfkW+1pzo5TcL17L24ljjn_Pv!wOch#yMg(MVcz;L`~^#{nQ- z+|8Yo{vF*z+`vVW-$nfFN-M!h(j?~{_cclP6U6}#;lqKSz&kwp`9a`K9HvRh3LbW@($00Ib# zfg|qSBPKw=uVDh3{kjKi*sx&4C^j2*4@E*?C>|2KHw>77eEAYK6QBSy5v%g!%Xl z`*<+n!iEncPOM1mV#bXf4}ug)QfkVTEngn(iPL7#pFDl;+^N*%-JeL8Hcbh&p#WmT znu(Oy7&0-N!5Bi8EG$^Ct%^@J#CUa>ijhq&*|X=%mpuc71dY_u9(V9ffXH_FTr(9#7+ypLC6h~g{ne9FM%|UvPfE%3ls?VGbm&wHZI)0)`J99h z3SNFB(nVehfKiweQB>xckD9qANSL|_=Sgz*L}#Eu0fXmGtmedLpLYV9lc0pfRH$MS z2@p&|yGlgnFuzcQDP+a|A`Gxnc_!?mqAAo9b-}ro!)etnhnj8E{$>ns-QE^l|8&0* zXIwt9NjqE*2K?5WbjwwTTXyoEH-UZOeaMdsw=|Msi2=GWhkEkWN1p@oEs@@Wh!p%E zzWBPJ-~{&$s2(B^KS*DMC>r9xJ{Q_x0frme(163`ov7X%{+j3Bh%3@_qa;{#G-D z6-p{06%A9h^3|$7ufmGcP=Or<_pNXv7F9xuM&+1dWcI2U3K4nKkeXywT@giCpSiV~ zT}KACVq(+Pl-V<(4fonC0fp4tbHlnhu8EzrD^W^M1j^hR8AvKc_qx~_F=i~-Y8XYKRyYFDoVh`?ZS_5iOp zAI3|-5b=T|8k}+V<_~yc9WEH`J<2Gm=dpz$hx~EL=bP`IAprDaLNoqL(u^E+qZvBG zf&n@3BN6z>9?g)A1M6Y82nwJc6s({HDHy>cJ)>wtND>V`h@~o}foWJ0$UuJKnO}tF z7hzhAW*B8AE@5gR3sGHK@D_(t{p3%D`O8sw*ttPEs4YDNyn7MQ)p z*y%v^_H#dzDQF4balm_0R0n>cXki2kr7PR>9!-!hVH4oT`%=`gk6B=sBeUNt9R{#6 zz|2OHpxKK!&=CLmZ$=38p9!7`&1b$~n$)bOHLqFCp)KhdA9NCwro^toRx0Hyxlptp z`?x6Q;`Y(hsx~I{Frpp9hPRmT3L%C9TScTYHP>y%p`IlMXh$_t&j6{ka_T2)JJ(T< z>O&mNWv*&lTU$&;1#fSZXPHEbSuM(Cjbb?ow)jX$|K+Uab~v5gPP3rMYPlvgtTAdL z7YUu!5J#uRXmEnC~O|@APB=8*05gb0nM2y z6R?tySu>k)*u(bY1vi>zkcd3wplL8kMeF9#h9E*JVM$9Gu^S2(a}{-J#&Nt_7DZPl z1=13CY{unhbDO)`)k4>9h(gJ0lV}mLEXJS;fmD_q%H?u)Mzmqx$Cy`A<}{=6%xC`S znmf~G&u&q5`d}lR9i2pYCL}kr(N=53yDr)F|8Y0cAxUe7=eyk`Qjz9DZ%>_f8UxI? zzRjy$7P1hW+U%FV{gtW;04!i#tn5P(u5tI&M;=|A06vX?>-{b~o?gdz3Ba~+R+H`G zmVp&t`zY~=Es$ait=QQFR(5$PylZ6VYp*tf5s;OMZo}Hh1UG_a(B2&+Bq@oT-Sj4w zo)k_uU}*%M$#O+Nry0-A^H8#lZ8GEFXFr=(CgK=0b1wn$OE}k`gl;%Lp?k!DPM38{ zM2ML<({DHe{G^?^VZmK`@Pz;QC>9rV=bHPDgui3rEH5-`T`OB=VOF{#73s!JcQ-dP z1WuH`>1$eZu1xdsHoS43s9{a5pemA)|2=>@Zo)NRd$bxgtdWi{IN5=)hrJk@Ec@6; zY%;U9#{n}YPgk4$O8=Ng?IvP7fksUCe5v&oyB<)rFErN>WSe9xwlLm(y}q^^zCGmb z2anwSOuj}Q-joMgW2JDkCqfZSAd^Iw?&PWlK^<@C)+z4J@kdO*Lvl#U>gQM+FCSs!J5KwS4~1|W7SkN^v~|A1mQc289d;lVxxLrUUfZ09opiicMl_#y6bfz;Lj zHgF->Hh9~{f#}nCBH#<`R(UPhf=ea^9Hb;uqIusmWdjj(7lBz{6DLRXbDiO5Vy1A> zXMJe&4iL9}mvDq;riAq1XAnnyor7_&)kV`)TZytdY=m-H$VQ?g7d{AjR1t(K$9k^! zdes+uN2r7p0&z3PaN_U|FEeuuw<2#=TU}UuC+B8+ct;zDXqe&|_MjZOgI>OKNnTff zUKd_C)kpo8JmB(b+k#$MM-urUJJ_LsQRQFNPz?)sYhZV4EHekHbW0Nu2`7Mx@Nt5x zm>_R(0$r6deWz7_H-gwk|34;(Kat>ys`OwUB1|m;03rYYEZ8D0XpBW7Z%c9{ko6>3 zG6Ya!B|xBWQW9Li6=^aNe!k~s&6j#YSXxbBhC>vG@1PGcw-26>aF}WHNt#p)-Z3BUaZ9dcNUl2{Ev!9>pe$zeJ03H3K1V zi-nhqOWBJ8f)D$X|8A$zK}oQ06>@k5EFn|1D#_J0ALR_;Ftl>35dyi{orQ$&<}-j6!mZv z{a}~;gqO7UGM1^CpUId30GX3n0|8(U1qT3~0Gl-co1MT~`*4{Ffe$ZWn*2l^tRaYn zWF0yMb>?LoD%m_8kN~Cz9Jy0F&e3YaLlVf*J6RwvVV8+KsenC6Ri9W@;$bi-qKiuj zADVzY-d1wXr7KCnA5B&f^J!&ICdU{7e zuh{6UM-i>0m6xL_07li4DV3yk5KuJnKsLa3wf3ap&@t~%PK z9ZEqOs-@P7D}xK7)C#ZxD;q}vrUhu2tNEg<>4cp50tuHGT3WhZ`V_5c54pLAeoL_# ztCTokhBvBAG#`0{hDz96b5TQ%2DZH6} zo3Sn2mq+Y`{2Id{N}4}vnk`b8;aZl!%dHoC8ZDxtHDC_`up*o(X7um^6hx#H^a27v zS`|B{z`BR{;Jb5Q0{TV)U~QZ$Qge@CK($%K4IkySzU6k-=-*!M1A6wF<(N zmy90NP0m;}(710-x4&a#YQ^AsM|TU`)erbkhG^+3hlh|m!0qwpG}9~{Dm@^8SX)J`TWzl|?5XB&7t;x=^mCk!SK~JHZ6kD;?u~XgRbm%q6`}b<% zrAYY2vId~Y$>|H*E0fYmovC4+3n*3FIjEfYvp+jk>8rBERu3 z@Ezf?Vc$X4@AH+C7i7@X3@>n&W8MsKY-E{PWYxr$cH@?qcO*^rSR6!I`)j~eZ_qUP&3iPJlh_i7ynU<=wHqNgE$f+X$(U3au^$b1DATrrDnV8c9uf=541t{#st;~($h0>h}RjI?as zRSP5Kv)Z;TKlAXGpaAg)06u~R4IV^T|4_<8hR+-hNt0&CkP#Ijy1__|TE!9g_Vuf$ z@5MfnB}wAzSCSsdl_XQr8@X?#N16Qul)l7eBCje8S2B^{0DNlMWTh?T$vYyG0AqBkf2vQ{3k|{N(cxR^7+ z1wZcG>ny3Wy?b{D7Pht#MBj2MpB)iZwd3zJE0N# z?9-$?C5(9QiW44ua6UsEP{Ke6+0*YmQz8NIK>8xdkHIV0dxO3N9nho!8*EU~f)GNm zV1^kQ*rz-n-e@pB2s+VAv#*RYj1tJGQjB7dJFAsT3S#-fRa*oY&IFaiPyd?X9$GlDexh_bgdduc8>Yq}{Xy_RBZDWn2xj8A)( z0#qNWUg?A?#;Cdm0I2Zl3a+?h@@g!$>N#sowcPA1&adQj3#PDWl1zZR_C!^ur~+`b zrvN-@YEV9_N_3~jhN8+b|9T)ZX|hPcQYkZ&B>POWH$4){0Aq5zY!e!C5~;dIlDT;NoI7B$$0GNLtSUHGn!@wjtf30>~hWeEWV zJP$t%MI3S9|8`98KmrkFxWM}Ub>PD{45Tk#iyc5jK#U`KV_*#jHlksQ>uVT76xSaSn|p;Irpgtt&gmB z6Hcw!^7RF;=>gkR|2@Yh8vsPNvURAv{;JhaMUm3!vAc<-w60;dPRTQ4{kEstEb?hq z*=S+&W!h@59Sz%R%f)Rs<&>*NIO1dn7k1d&746-|u9!gHZ4LO&fqVJMH$3bnC~t`m zjcA19^rmMxm4hFQcxHenFa(i>O9nqe?whB%yz(@mujlYPhVTs^3^@^F10!zuWEoY4 zaRwImQIF!9%U=Q_?i0QX_3RB!Fp`sywm=3pupeAn$d?>4f{0ASOd3gpMmVCWeQ<_O z1%cAtdc~4@46bluLtNtyr8u_ji772~+*1m}D#}$(Zj>Qa-8M%;4tlUkSQ24Ld{sh9 z74B3iA}LCpls6Bp)OQwM5s0(Lf7Z)S{NN z)QGy+?jJVI%X9CDjwkNPuzzm7G9=7&$=jsYrh*n?e3q)BuEq z(nAUJ&?W8TF#04=Air#q1BKZ@2s-2$5pfy?E69-%qzMRa00OXRLXZ$v+QVHQGGZQa%QHOV;W=gF2DItsxz{KuZD~!5NE$c-5sj3oBGIfTmY}5AYlbSD00rn-UeJ%p^0k3N z@kC}b%TOr-r6@&v!3#1IDY|%VqrS>q7wx9lEQOGtbfOdyFB(~w>=gi+MS~jDkOd1& z|K$}m*lZ0F)ucoTrGcTjUyM#RsS~5KNaG8dHYYeLnCW-H z`<&;z6sLORqaLM$6rQdwHGb^QfkL;fNa*4ONIf3;z=L0YxZq*}^s4kAhi|8Ys3Ct{&ORbNypIy8qJjnzm=)<{9 z(2R9AgWYj(cf8}hZgs0WwD+#)K)K|lrqN)qQR9d+5&M#p5Dg`fF>-AC(Gtjr7R(QC z3&h`4EUbY!Av^ra#C14j5fZB;?zk-E~Su1(Z&s%m+uH+8GaR%}pL z^!2{i)mztAsSO|ovX|ZLXXiuO)xP$$dqWJ~aQoTKzJe8$J?`;~NPm z-r>G?zn{Hm${>5)%AybwxYtb%YpA)g0*=t1A52r})M zP@_nXF#_bn0;}g!I=DtxVwqiiGbLl8EXq^9dznAnb2R^bJlpc-oTqu`tJM-UO>0`( zgY))#(>?FEme5Lnv9?;WzVCyt#ftyRoK3IVW z^aeg~24_%)4O9jRjE8vGKxd%45zITdTLEPl!4+@@vhxPS>pQ_CJQh?uF%ZEKM8Os4 zJ29xc8I+O+Xn-i`z`nBv0%W|Dk);)B00vCJ1#G}&c)$ppzzS>tb!z|({M9h#BjVnHmgA<+uBP#ibIHa*}^20my!#xB$!YpB5;bgxQ#5o@r9Wl%vYyul50JeAQx4phMq%s^|TI}YSVXw*V)ggb8Bz`^Ul zXRO9;L_rBmLAq^xBv4N`=bN<$rcXqIAd#g4ZZptIl1yPWQBn?W_{-%$qO#AWF=FC?HP(fD$x#kr%OoJ@ZcXq>{xNi#Lf+VYxZ_ zyh`Y-3FurCSDUV{tiNj^%bAj+b$Pn9T+3P<4fe`9o*Ess%mVj{76bIf5p5Pd3P!!W zLBZ@m%{;+w+`w3BOc?RTYD3KzY0TLa&2zLtY{X2%)n=~!hX0P zCXJCF49pZn!Phj>$5WBb^;QD^8=~k{e3{8c01I zE3D-lI8f;fx9CZPLo@$`66}l;?Zk(X{~$RmsVtKFqBpr3k0{XeJkJ7+u{GP3OvSy` z%D&U;&@?+TtxVL(@JL3TvU>PWDUno4m9$Is41AzOg;IkrlGT22N;SwWK6}dZq%2Xj zl+Gwsit`*zN!3VMRYctfv6RIa#V&g&h7%Ppc7YaIoVr_!j$1iJtgEikxl!3LjciH3 zG8!INBf7kNQa6oPWq8n7QU)1e(iK>d`(YXVv4Jh6(kSJ|YsAJX^~P^B*ed1HgOyT+ zY(XDvfDmAjYHI)sVAu^rQzn(od2Q1yJ+~t@(m933fVBhR?7ZPD8a{=+g9y1F3cY=k z$TFM=sZpkgFszJx&Ww|ZiF;Mk|LV_QHP$TAn@PPBW9i7w!6&XMiB3h&C;{4(Sh6+g zny?@u)XF}qQZjHrROf_&dfK}@$O3Ou(s*U$@jXr9%y2O^! zI2|hOM$HvX7l|duguH6w*9R5Te)ZQa-Q2)T$S!r$%KXj4blr;;%pv7K6^U3Mytb49 z*lf($werCy^~{D<1`}Yb+x0<_jol4&iS=aO(E6rEeBRLNPUy`yeUpM`_$%amhA|n` z5y*%&%-NXh+U4s{M-AFX|23AFh`6kbIU&k8>3viwxm2kA8Yt`8oHbQ9YYUi2)yvu1 zi5p+p8yxeU-(w{R_03cv(^cx*v-h2>EO?PVi%{K)k`Aihi@Gw8%wJ61D73h;`TNkn z&4SRmR#D74p&(1}I?)wHT+?vT#f4E@+pf^4Q8g-8wG61aF*w6w&%WF0phiQYlD&8 zHGzSKyL!gcFl=K6f?4F8*&eeIC0XL43YfgRWs z1nhbqY|OR>+dbYHDZzfGM^}2s#%3$aUTlUw2X9~*(T(Vfp6n6SJkMjT3QfK&;q8rn zAnYx@FOg%4tO(|$28f`wS>#7<6*GG>*yfYV7zPW z`bTE0t`ukS7H9Emi;)(;pT=%XmAPgY$MGCzao7gzYHsJyRtFvTM;Mn8718n6WRWK2 z1R;0v;&mk(xN#R}$YI*kFtl=oU44 zf%Tt@7EIgW)Uj3$N3Rd}YqTEbZC-}z0svz`oWJ&AC-w%kf&3YEF@{)tg^^-+_Gfo? z(3W;+FLsDcV#l+AZAQ~$*T*EJc3^LjCWZElMp@wItBwW}kiJNpZO#w9n;cqHE*fe- zmft;A^nG~q_N~g62syDuWIGRPj_dS@c7CE;s<%g|AJZ3$d^V8Cx?Kw;dQZg?$-Q-k5zj2{N?_d0G}q3*Z7Us0&KvD z`@Zjl0{LUWhWd_l)#votYJE2}mXA7ouum2fxZ1@mt zZnU^LrX@-iD`?O}(K6i4ap{};9_9<$F!!h2_ZcvDI&|i`aDC;-VQ;;!_6BlfG4|eo zFMGv`l3tK=P%MFUu74UtBhW>G^8 zb#9EXnq9N?#oBdrK?Yb>FYHssTZ%148ftniR-RpcS!Eby-tnpEUjKMvHYih4O|?%w zG`K# z2Nbs3ZH5}AC!#MPLYbq9C>`04iz{+-%)ThCI3tZGHJPu%3+u>IO+^xU;!H3xV`M=l z&U9o@J36dol~OL*q!(1GSL?1?j9N535@vyqga!K7o~C%&ov5@K zs>kko^6h89dc~BRxxB^9i{XIcW>H^yS>%(feCSr_Z3nNv`>s8x`xl;t-lCVoG{{V| z`@OvH&ih5Z17AGx!iQ`DLH%&kyz?-ogbIrWH{X!*GYr2w@!JPKP4>oX-~IR8gFpT> zNI2+s`nL9#!C11T+(k_F^AfE*36f%lk!6hdJoD^;1wXqe`} z2WrJDQb-e;$O5zxxG4>BT8mo-^EJb0xewxR2aX4no>eP=YoWq1s^xbfbe%xVSZ;4WTX{r3=^OI-mj- zz|J18vxk22p&w((YjnD!pZC($z1{_ne)T&ZB&R_T_Sv8xL>Ry^oF}j*6^we^xR{Z; z$H?yi?|70dASEHmNJyg6m9L~9!W!@}h&9Q7R$9pW;AfL7HK3BO>>d8D+VyG4*1jn`7oq@hBYAo<-mTyOBe4}2|T4rl95iG#!#@-k7F3Xc`q{23|hnufoPQ= zM+(7HRVh`e_7191jb!+k!GX8FHI-=f9`R0sC4`*_ul~bWN-k-E2J{0ZHo0B{<_cB3 zUTI(!SSC3dJ2G-CqLjQ7f)E%}rprPAuteHM8HK$*FukWVv&78jppDXn}*Q@8;l5KT)e)QXd#d|~Zv0Q0ohG7vMo znQdYmS{*D#hgZ8wPON+dEvNZbhYBnW88d@GLaoOb8}bk3P|7Yh=I%lO8e~lAWgr2; zhp6c)U3#ST$Nvt}r$MD%4w7|W0NKN-zIea`qUzuWLzsR-X}|ys(8=dfxh@aG4KD4TI6rktp9u4kNbGRg3z zZfKrOX>1Em=;CRG*a5G3^4U?Q2zQ-SG42q-_GKeZ=54iku9>5oX1RTB9}ZPc2zKSG zEDkO?c$<}LI#Y)5+Icj1?xCKQg5c7%$3Ti~mod_#QE4DHvD_tj5- z=j%rS7b5|>zE2@btu1bOORDX0uqqkcUd22l?NXEKk+PZadD|MwF5Z7~;9u?sF zr@H>*?1oBGYoRN_^h;L`j!oiW{+)iD^d$TiGCk*k)!O`uu!sXM*Qio}0&t!DTPfgo zNiw)58Vd?nSAr#>w77p0E4;*LLT?>oGJYyq1UW_q!rkIy;=2j#veAF;oz30y_S?c4%LXp z93CG-rIvIV4n62$^Sxgs-o+gzMj%2F&~+DeOq4-D)GA|8w+&xb{o4*Fd-BEu42l1c#9vq?#6;#g*uX6Y5=L5_?UBxJfJAwjss0qsKxB!%vsAwCEJ?-A!x;0#zi zga1dC1<+`aSx^B`-btje1{c8vN-ke*ln_60Vn38YpvYEi9Y$!pP$3phY|)uk3Sj)* z1ry0)B$D5=)Zx+4MHy7*`l+O!sAOzxXLmB?Zcqx|2*+?lTG4SAHbj9HGzS_4$9Wpf zB0>sjK#H@F<%YP20v;gcn3_rXBDieMUfzxhxFxGi2z(S+fwi5590-4?hg#-kPuT;2 zji4b_BdD#1791ve9Gecp!C`WvH#VLyNs?lUqv1{4COts^un%EA036t8H+GvA0HlY( z=0Z?FI&>yuGL2_KLuTUG1Kd?;-rMq|n^m!Y~oCLkog;iml9!2fPm z)(eyXJyaHB)Pn%-nOB<44>9UURtn@e4Wt_7eP(ArQ0l4b#ijB_^vOjO zK_%b($`BlA6!Zfcgg_Kv!=;6)UW_Wqu_r!!%YEe(edv_c^_R9t;Jk3?i$Y`TfT%EL zh=F)(+d<&%%uW`tXdoe2Akhwf{fB_;UEl3s4|XGu`sl7CW>(O|3{sDUHQ2f-DTL|Z zxy8t3t{V_`CQ3XIG!X2y5d?#wDN#h}^7KPcK!p_YPZfeGlCA`sw%*7jr2hjfQ^jHl zogzk_>P4RlKr!%XRM5kns$t7Ug*BncGxUsF{J;-v&<`vsCJvEMW+i=EjSIo5%E)Rv zd8(~8Wu~&wc>a(KsZ-Ns<=UhF~DWxD4?|3k+;f}+aZ`Q1fvSnj(Yr& zFb?Clt`r1@-M0uB>?A`qxaFtGhq~TTxa{Dug+n;VD`oN^ggwwWQV%D2o(ch62!UTL1)mDSCfq4L2*6h0X#=@z8ctA}j0GH~!4HhU4^TnQmS3Y1 z5uKGm*pgq+g00mgVxWY|CrVtUQAYJeji+{8Q8wt&78>?J&27~K-TY+n!7tdzFa5fc z{r*MR_Qlh5CsB6de+Fn4T~QVd2R5)R8o2G>5HS8a=yo8mVkq#sWF5Sy$AL*Jedq_@ zO^dn=F5xDFF!q;#fM|$LAi8v5+&N?1-3J8%NPPSUysRsPbYtgsZV`$YWk%KDXhAg1 zfb1f zFHm%&76hq@@KuwX9x_<*=872eI)tODTw?QhvmVqN@i)O^QvRE^r)iIl<6$SKDA zPG2x%B17R81gA2nELYIBa{dBT2A8BPyN3PA%KkmttPH_#s6jteks9bSsCZxXrB*!s zvI}46Egr}cyB)WvSA(>gFZNgArrL{w=!+VFxysjl>@YOyS_l&Hi*oDiTrN^6Ach#> z13+;&uply20qQ8yiOZ9siUn&tK6`9Rpz-({2+sVLx=H z4G`=d%g+O337Do^PMx*ZX8ss7eP-FRYV+GI_s;(B`sr8m&_D+TX zlz?sZgP-DA2@I#8@}3ls#T%YQ4)jb_mvV0SnR#gnd?qteF7wmwMHfNNH_e3)B}VxH zFn55ISEKMqO4-K2)BgfhEo8m z8mPf>VF$7h4%@>H zCj&J8krB&tG+yorK8S$4ZZ#xBI3xoZ!>$!easRzeEK9Ht?RM3S&|p6lGVIzkbW8W= z{!$tXpE#*w)H`22^KcfD8BwjK$0%>VdO~M@qp~TOwgU^VJSYSYv0(P^z&ehM;s2 zY@~HvAJ+nh$y?)L0o%m_ksJ`&HNl}OgCClMvj&8NhJ@p1e#>oKVE85H#ci>0s5}LL zs-oWfMm7MsWnAK%of$9NGG+^iAJt`D;xL79i-NevPU#x9>YD6m%YpEe9GM!H|FGD# zwm+{&HOyUJ24gY^m^_bbSY99wYk_Ph!~d?pE)+{Qbl3OmMg_*akC8z1a#I@-R5W`R zvK6Z%oWm{^HbCSRti1ILYtGnS$)g=>L3wi?cAq9-4SJndL3+neYeL0M>tKDu!5zTE zRg!wCm%0^ahGSG#iFMwG*Y%d+CQs8?P{R)lzz?8-t`ESjy9o`vI578x`bGFR zg)NRBrAoRoo)}Hagc(x+%AK$^o|#zxUvS9Q+W7Y!_!^}dxPVUaUJ_&B)h3B zJ3u{#v&Tg(U$$Ii!#BwLyvuvM)4Ms;`wK*Y`MpMyZ5(dNDn4LHUM2t`39;F!bE(M- z25Kx=&z1KjBv z$vee90|5|J0UVG#$=`t&435l0cg)B9W~yeENUQ<~y+l`AKk)p~BfZYUt`QQtk*EYG zbY|qK-a>r$cTXw%0HKx2F*FPgP-ufT#E4Kl#nI3FuJEIcrCU^(z}hQ)6&yXA%6DTe zf0UG208Vmpx3<0o5oYyQ$ zvBw24FYsKPyNm-AZ``;K{rzQ!yQb(~%7_qJw~%FNd-YMcQn0mUlLzYC+_-xX=9@dL zW~X0E%I81(-vhI~n?vy9`~No#zq||oH)Mmp&wi))JD#;ZtaU&RJbdGtjw1DkFBCjJ zzxK#WgD@t;yNHXL@2$D0xiGdU2zGpJ?=Z>BwhFL6s~z!rw8H>w$jav$$+tYiCxcDb zJU~dR0t84EgH^O7^m50`!h|*~K(t_CMhFWH8YockO#wF|9zXUYIPzdggb5#{G^r)T zjET^oQII)<<_rqyWXi;elLE9EHgfjt2@_huDmH9HP`Zt2Q>EIV8cdiF2qzmZCtAGP zub;~hElq?am=F$}l-RH>QcI34IkjosE;3q$9=;MnO3>Tq$Im{$0tCF+r}qV5eEqT| z?nmz~SI3VbN0vOf-~SLARE7-5A)&|+G(&z2p+bd5zrpqVrpD(NA3eRM_o0r>y58#8 zFZ#W}ojZ3u*LnxH)(gCzV8Zo~Be!i^Hon8ob*D}(c<}JSeywwLj_<{G=k*NZlfCaS z`PHlGjc3i;^*-3Lo7eVRJoj$gFMPKT-k!MeefX1;Z=YLW?%x1Oh3EBAQcyLh$V9Bar&hqO7u}YSW+{2qmu59>9RU5+k6Amp50s<|#+KLOV zMX-4_A$qziA+LR&@uM6+vMEM@ev<3Q*lfxf)-HO4*iE~~p1aUH?=H;tuxTBm;WAMM z7-ELd$Q8{p8cws#ukQZ4t{(yR5r8}S@PT(V`gG&!zWk(n!L{Xzn=ZiGu5Io)@y4@F zF!ZidS2b(JgN{4Eis=qD)5>#>ymb3r&A)f!o%cL@Z>vw=-t=4dU)reqZ{Y0+Y;Zva z3q0_^2md2vSTBcJv)0NN#1x=I6@knm3ldF4@k11WPM=aL0;V?DCIW2`6@3R$ zU8=|>8!*BMqT0pULG+T)TC3K#7I6!klAxuognsxE){kf4b?mQZn|)@me7B`cyKAk7 z>@v*49nD@3}S)L1qE|5d4MBx^2p9DvL_=so#~*W z4bv@Ub%=t)Kww9amQX}ggR2u#ED*;+$*On0vsLhL702QghdaR<7O@22E5__48~*|r zRyLmDu?$^{n8h@vF)x#bAuN-b&0HpF?zJ3xlwq3I5x@npiA@dysDpm_2X)|+9Qeg+ zfdRT^`jBHD6N-mq3IkwjU^77XT&OniLJnXq2$%&z=RfC(CVQw!&Fh>qo7voE17Bb? zg$5u1;cQ^Q05h<2qR?g!qFI9qq=jQdL7skzr`qWGG!@h%0XG7YJ){((FZrT}Csi7V ztR|)#sj&lCR8j)EU`7xnLqu6Ck`%KLBon<&YFEr6-NFdQl9H&VXk=oTXrxf1F?6Xk zO29zASQa%&$xVJLOHHyu5mXw^26*~LAMsQOKI$$`Y9b_}Dz~{x-GnI6VE(h_D{dct&D~ zrM%?fk}ug%!876@t?aGVdNh!NWzGd#8Vo@S-kR+Y=2KAJUX!=_=q>u-2fyOrhcz7x zPzUj&Tiue!V&8$6U^29@=Xex?g5ipCvq@0&9ZNd(z%Dj>8{YHb4M8UPrIUI46D zoWlLCJ_uwp2Q4T;H`9U}j*$)LT!^|G6AYF*fXy(G2&KvJg%gKH;1rz*MIeId)o?U7 zCPAr)TSB9lz!apQ8YxCh6l2-4=%g@`jg4koV;U=L#Pg;%0P6)n-T$n*g9IcaZ-vTR zo9d{liI5VN17K_+IM7Fp069+zaGmbnn&d=%jwl9c|h7HLkhKRw6|nSTi3c)3aHWUck!8N-}1IFx+!OJpo38ICg;5u%pZW* z30~`R2R68IPrh&Gt*Aw5W?wgC0~<4J zH34D$0xYG^M`>&thLOh7Af_k_A9}Dox}XASsGtj5Leh-b$p6GNqPs>pFvbpjR7EC{ z_{2|}8#>03Z*+(hN>zH2hkXs~76X8(C7yAbL|09CKT?`FqmLD4(a0Q`ErYEPfBQy{aEipUzYS?;0~cX0b#l!OV#L$r~d`9+aIDaxX%=Bt8J;?L>1GM zkYoS?6SxDuVAAciRN)lkJKwz@2RgVU?s2o8OM(CO;0NBMnm#QVDj?L;0tbYfm+C7! z#>!8yGLacDp%5Iolf}EQ033{;{N=~N4$gmmBulO(H%EW@`Fbgx%pWH{K{=r?0)#u1 zMU&e|otFF0|CmB4jtu|8>~Ly_b{y->Y=BVAZ~Q0=8326`qjV}QFfbaky2jQzh68~@U66721>loIcAJ(AM^eIa;&qSA zilGUgaNuB!#MJ1Mp2l^^@8-Os`b=rZtZ#PI>iaHE0qDW}L(En@jjxW93@f~ZBq7Wo81R&Y&3mcB%@vtGA zm@%K~K}u@xM~-A}x(JLg3?qx-z(}k~vZMpTElMbi-{P>QFjA!6u;20!+=ht8qz2#6 z0Ug?5CTmhA1rhe{#t{Ee@Y0Kj7}5Ej#uImd;T%i*vd3)Q(G2OGPYwMk88Me zV>8POKt9c!^bs@n@iXZ$GzSt0MgMIxRg*JGNHh^GxK^_>?`dFqlJJ}mSzI$f5bq$f zp&l;kzJ>tuh5#FeKpmN}oO~fmJjCGChzvC{^ww}_l4M4h3MAQRZuqT;{>|L5$VRTH z3t*BXA&hN&q4#XE9ng~|X;KXhaVO`dHi69#`a#^3ghp_H!pKjg#_}kCLdU|2;UeOb zn1Bg>U|b}C2^fMQ1_E##P%3c%49st_8sGsjA}hC2D`!U(tDtr?G*wK6;jY5r#EL?% zq5-In5{*(4v!WQ;stPDeEZK6-uz^7}kY_%tFb&h`_=0(8DKd{~zpe*c9OFliX-G9B zHCJ;pd1Ep-sJ&EkV4hSq%l}JChYLxQ6iSV&99NS!O7Jo6<9)K!N|SU+C8J4^)DH&F z9R_aT9*UdVw7q<@X66e*ULYGB z&_<-51Zs+?4AsbNmLyBwCK_Lr6tUZeXO|w8v*Gm!W zb8M1i{KRDZ#?nNUvH>XZaKuV>Y(P$EVsLE0LCFspK`~Y!u`00w<%$&uGRe%65-Az0 zA0k3@tm0H26bIZADPhMye_}x$Fq9mQCc+i_9Ijl075#=WEqTla{F3}?R5kEnFmV(F zp=WtWkVq*rG9iOViT^2Ig_J9Xi%ciOn6kw&loT?y)Jvo7WbET)6gDyvR$r1-HJ6kz zf3#p3Hn;@VGK&dg-zPHCG`%bV4@mZ48@6G2V`fyAD`w`t)Zk@_6B{NrU;1(#U786R9q&Br9yj3Y9qt%u+2(8t$+;F%l*_!1q4&z(jQ%grpq|u02tz zA40apMwVm^5ham?D^$QB?5IMiPy2AyB1lE7Li8tgz;H%1{m^fY4B}6Wm2ZrqEKKDh zQciR-sUL)K7;6VABBCF5fD;HO5>b@oh!I5_uthhNc0}}7SM+g}QdPS3aog|u#C2MA zrwZPcHSpm^umABd?Ug=))JORhd$`47TlX?|qcMpogkZ>@_6s*UHb}iAL-chqVV8FQ zwO`Vn2=XBl$STIyY*Xef;CR?Ha4XogM(I5*r$~n6C zd+!UshI2RvmPGmiQ@;pRUoTO;$Wg@zO7L(@q{LKp7HZUnYH;M>O7(3r@@nu9Bbmrk z(KCS!U?#0Lfe#fstAu(3z}9^7Y`S9Y(OLkB3lQ?cGePZ0|z6dbuH;cgv-?}TVhTuqWVBI zM5`}_rT>w1OZOR?B}a$lm+tjnvj;MP)ElV{!7uyb{J{BjYKWccNjA|h}&hZ*-nan3`PSt=W#a7aZGnYbp*HFf}0 zl)j>lka*0-k316XMhz1iOY2?6Sh)7loaYgpy-Nz&xt-C@ecmBAn!yL%xt{A857_v6 zQUCdruc05}`32_rz2?{o&>#w;AbsxGd);6S(l=(aX-cF)AF$16Q%IsX9l&{i}gA(?76S~S|4!Z9RlDT z-k~u5`mozspH2CC*UO&=yRhjQq0!(g(4e5z0HMoQ3(;aYA5XW|hDMUpXlW`%r2j@z zr9@E0_S`bk5YDrSpwL&~pF=K=fd>1F%G~+nBKd zAcMiM`ILmliXmN-lC8OwE5IyvP7zpBu|R7V%BT6K(a zP6SE%vYFw0m2Ji9Zw`g2aX^S?SrW5PsCQNSPO$;dB2`XQ$Ha0V;JTQYZnQ?rv$k=2 zwdKJbb4Vfl!Kr1!BYavAJHrjnv1?$kEl7qQ49g_MnEO;Qa^7evwN314V4E51X2FEyORUO^3jftf>}_e) zCoDY{<-ZhFU4>hy&QX%~8p1hf$THa#$U3 z&gon${5Am1JFtSeDT;a+x#Cx|87XL0zJEe0U+0;-;&8Cfb1e~)zLx`Q&dh3bmeWA*iQS1ZI-9lJQ(!&Q9MH5|+t3JUQc08sqHzpKSV zAbbxRp|haHUsgD09Gh_Vvu}vFDYEv~jXIwbjmRbs*HDn-mr#wIM3!+KTKYsb%=Y;0 zw67BncVwn~YRSFiOX|0x^DO~n9r@M^56TFM#*joffQB1Oo7ua~IsX6}@SOv|YRm|I zm%%%%1wO1hw*gECbvmW0x2($wr*N_wTPN|*3q6+yzNzusaMC(m+j7U!Omxs9gwuR* zH61Uy_(GoHw3aS0Ivq;t!AN7bNLlygiwV|g{(@RP#cMw2^`TW4DgfNr)?K~SyqBQG z_p(>~*LVG8IXh1a3d63XjIbm{Cbdj%>QQqR_tp?fmajg~O{Dyk5SfUi} zNtVh(398!E&uoCAV2Z%n|1`3EyXg; zp%re^@8jjxzsWKhNghZK;Lcr^EO@Q~=)h4$ zf@BGbaqPeW8Z-_lQrTurXr?jvYXNRH+ga$d02(jTS9R zGz8BX4I)I?Mq$IYZBnIb!@;#H4sF_`_8Z&Jh7GbfZvTc@yR)cToHl?i723e;ShE)L z;@r#krdhApu+{Cmvw>l=K!gY>fsbrIe9u%we)cSzpKO#Vt0*R*p5xD;KjRxsx^&~y zp;M1FEkHoC)~{W|o-Mm}?Ax?)+s@5TNA5+)&^YL{ zBVR-lS!A6?8;vAQ0swY^V@fTt^wN(nnFLcx{r|X>4hJ|qWr0~dO@V`xP(CSTlwSFS z)DAlF6xCGQY+zLcU}+N+P+dU@Rs>|7g_c@6?IdMiHgsj>QFYnSKtB!m#pIrR?&%c{ zfz{ckopnB`7-Nn>CRt{dVV0R>t%+vZq?A@_>7|p3py{TZcIxS;poS{ysHARsOsS}* zs_LqvPL#zV8C??q0GghfDtX^!5yhtDd6$J6fvxdrgYsqZk$cie7~g>n+UH@19`Z+` zJ<__T;Di4~cp!xtR;ZzV9EKZiG9BV5lDHm8lMF~5J~Yll`aSeY0I$Y6D~>h}h_6aA z^=M>}LylDvO&nCQ1Cu-Pjrvk(F} zp@0F3JD`W7J8OV3c4T;we!grDq3H>7-rr`_BFNynT}UG$LcX-)5Jcnb-S^*s``%$c z9U>$!zbXj{Fj)iFw1dGs=@sXd-2Znk_L7C+Ak|e@X_fNBUqz5-VRttCWM++Gevc0bzzm$r4n=$0hQCNgEN9635h+FvB#!VM#g} zli;AF!f4@^x17_7uQc_;>!WD-F1|;i9rZU&@k-%UB4sBx~KK4P)$t)@x z*^ppnGSe9gu4Yn_0w-B8Rhn>?25gX67z!Z)hPp8#Zj9JiJJT5yw&6?*Mu7wl+F7@L zb_ERSaOLi>rhCPty5Ohm&IH+lz4s_`NRvZAu~ zb34y@(T;b#B8S8nt^*~cME0m+2ke2N9K>!Q`f($)pe09;0Emox#A6k*|DUYFIosW~YSh zq#yfa=uvu^r3T=0WQBplEjQ_f!vK@6zkFGpast0UVFMn?Sf*kV;7q}JL7Jp_AfvL0 z%|}J1o8?SYImP)HOqugE4TLLK-f6hf`g3md6iQd|xdVOv>78Hz!wUD=Py#N6C_=$4 zZkHm~*n*)7lbA#dEU8Ic&Sfa|Os);0E8(X-^@87+nj~uk<3_>uRX2y?#RTnEyaU;W0XLgsZN z7IR180RLHQS^`p#8N+3w4n&$>lP;w1eiz^hALc11(@6tXGCe$1j{~^W!W}}alYX@J zD6TziK}lxr9hB0PH9HD!uLOyeg*Z+qc9@S@yzf+kp~z*)cESi{7EUaA22}|6le>?wH8iNq zRjzWB-|(R5JfX_n0Lw%Jy0%vex6s4gwr5|YIupUeEumTIN)vZ3*;Qh?qYkltNU?II zHqlGtgP~QM6hhKkkP6fVl4e26BLjACfpD#BHsUlsY9y)GRY1A|+0jIIA6%o>co^f8DOI?K~*kNzjn@hq1=2bvCR)mZkM3;wz3yyhTWuF373PKI83 z_G6J@OCZ(%U2X&kFX;(591yMOwbR!C4B3XoLIgmwi7a?FL zb_L=)WOPNdrXU~DRO*5tPX#-$Ga7dMeJ zbKzqRFjs`d2{lA|yfjG!=Sl_#KRv;61%wUrGZ=Y+3eFT1tr0bGC;*%>7B3J7bl4e3 zGl!hf8e8*+fEb8bQ(A;rh=zEGi0C!@1W)!yP+ZYYmv?Cr$7qjuJ~S8rS8yFAc0Ne- zY5unZQFlvYp$2Mj5%N)L5~eN*(0~O2fxV`6D@cK3M|QD>A0u%r^pT3XLoOf~MkDAt zHkAXqqdP4%EiU+iGT3*Qn28#(f*fLDgK>C0h!WjaJ&~kiB6dEE00~trT60h549 z;fM>G1P8Qt7IQHJPZ%dL7BN%hO0d*W2G=IHq=hd>6p#>1gi;p!W_zx5aO`+pfpGE*0Q_@hQ&0k%Py(Ofe8`6nQB!6wpoh-qW~5G?6LokvgS(0q< zjwqRuoM0GgAPQJek}w&QGAWan@Ci0~lQ@}^H|YqMFq1y{lO~yxLP>@!>5@Qslq8u8 zmoO3gXD?mHmK}NcjqF&<1^w0X;bcqOg)fDU^Jv267pgHEESMa06j!lmAR<9Zo5hc}bFm zhiyk@7$rdglt}?&0S%Q&0niYZJYbfruy0XGm7MvOj_?k0d5&>el5CPN9l#11Kno~o zc!Kqge7R$TbrV`ClZ6K|Y{)+E2#_4X3OtYjzLyun7Z`NqhJi7XCD5Fr@HfvH0MBUv zo=^k(ARO;d1D>!C$1xnz835F@570TD-&vl~d7k8np5~dJ?D?InkeWll20CDsI%$;| zzyd6g0mI1xfGG+rIRv>d1cHE;Hy{X?5TF1+mT1|T!ubgdYL-2D1AQ_PhL)QT~_KBYvkO*T5pClTV zj*yjwd6QgOlCSUrH=v{pik4xymTIY{ZEBM*TB3$opEubC{qUx4d6tgQ2X)y7_SutI zK%@PMqdKYsgi5Ct8l+f|3$JjdYU!B^dZrn$q&oVZB?$m7dZqa(rBn)C649ev`j|V& zgWHx4nR%I+2@N)xru)VTAd02K$qD&6oFvMkbXpi^5vF;njuS(lmv9Xy$q9Nndp7U~ zbcz>kawjL#0FYXhg&7*XNht3)NjvcgiSP-AikyDY0RMuaC(aa>%~=BD`JB(God$57 z@9+-P$(_PMuIniZ`{1tf`kmw|p7VOI;7PCgIoItrvh z+NDtmmiD=!j#`$^dX`FBn6Ch=AgTlTd7*!xqZgW?ABwF3Fa-UOscGtL?~sQM|h2WzZY`Ujkl2xn=Q4tuf;%9e%cuxt93q4^0^8Y{9g5fwVK zIhvM7>ZUhPOAU~dpy`={&;};(m2G;MIq3*cTa}#|w4Rx%_1O0sEE#7pk`i%L6=Hw^Qq|Ir$lVfRi`CtA1gZcsY`Lc?LWH zKucn%w)+WxKyLe^Z4L0dlX|kL(VJ8Sjd`LySn3FgfSgZ}WZP;MS;`6}fCnWouhL1K z)`^|k$*%8!p4j`H;c2hrsjuU!p8Oh~=own!vcE*f1sj1)Hjcdt$DkjEWo=T8kO%W zxM*piPr*MSKzsAqyZvYw8DN%#E5Qh?1CkrI9$L3>`k*Y#0y$fid3v^b%D8+g1$P>j zU#SBKZ~+Ry0u8{IQaqd_9I_{TlQT=hg$cGN%K~{@m3S<YfUv{%78>`a1^%vHz= zpRf?0&HE~yDw&}H`v>)Vzh}UwcNxc4sk>aPp*`HA zaH^p4`;G*w#bxg$p+`flulRMh6ax2ak00j*&sR6sdhQXILyTvO?mFbM3JW$6g z%f&nkuq*tQP7K8f?4eVIqlL`HsXMbg(GMZe4;Dbu{QwpG2q$GJnpU~D1{<;x9mPJZ z!bb|gcjyZO{oF;ILrH0tn#2NzBn9OojvvzfpU#VkxVSny5JqmKrO% z4dAn9%g{Lcp)xDaI^5J|smR%8oRF+NtWe2;6_!Sl)-AHY$HXz?;pu>k5rbjEbNbO2eJi34j z;A%-0gaH?J!h<_e%focU4-Tzf?c6@R#(miUlz9%BshN7M8t||Zl*tlNFnytc0QuX; zhKCbTH5S5b0%MJvT)nMB`R2kbo}S>uqO9G~EDH5a%?FLur`(_wUX||qp**mo;N02^ zuH3ebl1Y5foS*=CPyh%p&@$V>E54FG9o^uJw@WSEI@`nQJh{x=+eZ)u9z5e4-2k(2 z0S&+e7r+Lgd6+^Dvc^ga;jO|~PTp|a2Bjdvs@@C7ZL9!23#_ij={*WE9>RAk#i8uq zP^|+OAOXj%>i-BJ#rbW!Z)v)>9nU%b(g}^B!a3P_tD*4w3A9k{7jOg`q}2w^qdO|X z3arq%eYSK><53IOoPYqMu-=?-10r$aYdq=2ecV0%$``=ieCgsa{=wHhpEvLaP$1B< z>Ik$@0L0z^y{!P+j==f3((_KUU477`o3RHw-0q%1#O&l&h;6tD8vZ&90xj$Feb9#S z-j`1EeoWV9{uyCzs$C8Zvw)%4YUVhtmej6}YZRS{Khysoz&|_9jLpn_&0NDUX9#U` z%^9MQG)JOTx>eFP!yK_(A=R9@lB-fl+uWjDm82R;x{>-y%FpjVc)uU7$NT+wzhB4m zIlPVdbw1v4(#PzlefS5*cNWZ>uWi1y-g=0(@`b=Lz>Xh3XKk&VV&B9W6s~xEHyfIg zx&Of)S-?~Iz9RK@`B204kyo7#$UbRN#n)S3Z~olSdex_=_U3_9*Q)fDzmCXl7?{PO z2EP$0VEcE!mu0B+Ut)(hjtzHD*T0=Rd>@|(^(7-a_W(m0pDXtQih};`ZhIWV$17hw>1d_ z9;A`gCq{o(f0Sz_g&~(%~Gu5cf)^s-G?`uL?_EVAin<+}}fGHO3&A*`)iDfRvV=35^x<$X_CR}*^{A+yzm%M$bSCh z>WNfqoKL#Ua{uCbzjEd_qp^rl-q-6WyR+9nj#meKhpP@}8}Gh*kmbjZ0kmQHSeTTY z9seW3B1-u^7pGcm9jX`|hnTqJNhG(4hFre1mLd8ZQ~k zu4|Nnu1F$5huEJ4T4%p#-)sXv7HG{zPm>5^b7N&zl`D^PD)YG63(hH! z3C*iFR*3O5^QtGrF=z@lesj4#b_*sMgbX4e@+*n~Sfc!~?FP_jz)99ElyFGvzx*%X z5JaCScG>BW4rfdqpV zdUdFE_}3uOyk%fOt7&1$1)sMOL6^Y1RWmr&7gf;)Vl`C(9R|@X0=6E+gb67-f?s@+hP|A*h+i5qt9a7osp_H zvB`Q@dP`EYi(@+(^QyJpMWic}{klR6^0L))uIXyoLWNN$BQw&&FVm*WYqvLncd?Tx zI-P2hnyobzKj73FQ}GKiWa#z#lm8QkyVu(`dq*uNCJu6~B~AD}huFyHN3`@l{*4Vq zT_Acsx`C|VATI3(&^GJlKc;^^1B`@2O3YzA4oNL zvqW;dcSCOh?Yuoepl8*#QLTN^`f$5Y{5SO{oz?bC1I)a0ZdsZzIRI8aiu!E-L*j#M zBX|6bjc_3?m?>@O?QGz>y%YH-wnD#}(|K&yis?0FZKR8Gx!g{`gz_=yvA;O}&r;ek z9Qi9y+49cWiBFbl4odN< zuwi$pxvGY=>+Hc?3Cy2gDfpNFlxt0Qmbi~2TnRmL{)cL&d@G@M=qOv-soj}SUS+>s zMK;&c&aa2xlwy!yZuMMNr>MHWp!lzcL36wMt5a#plG&g2Koyhk3THcSYmG%bH|L%b zjCZt}ab&OAXuDX0f)Y~8BTQy%I- zxF*>#Z@oC9zYTq+e1Ac2m=|cF-L=%k;j~vovgn3FA7qFq zcu-g&^9QFeE0sttKlumeXBuI(b_r&S9{d_?QSQ=W>>}NHa@ZF1Nyl9GqP5g+&5Z+E z2zkV4yYh}2%}cF3n<`zCra5Xl+xmR2JYPVB z(NL~+tc_X7_%^qScS+TOfDgIxfcrt+jKvjxaOtyQ>>5eS_Ctxd`jl&PWYzK<_mc4h z``!hmL*3n0ji;|&9LZ|@cGAx}#zWJr-NIRia0Ekn3pDAaI^EoEB2eGyjI*!5mK%*C zTp@$$+TmCOUs*e;)zJNZv$2R~m(vBo3)V00-IPVXUS+7Xd3YwN-9fAJ?d_Xc)?S~x z462@a{-fum?4lKkCdtffLSbU-y&`;tyEZ7@Ew4mo>^=Ad2Zj4t!=L_?^B-H5=sWt@ zEkEe?Kd~-xOl3H>MM(5L_vpTPRiHs~Sn!EOTYCde$8)X z96Mn@I`IK!aw*m{HLE!zerI5C@#%Jv=u)TpmrX;&`^THW_2=-xeEONQ#f{wE_Qfoa z1{ngzkvFA^_$CjS;(>1;(XS3cu+{Vsptz0D(yceeGx8^sn2*HRX=s}Y?? z-j%(1uuaR!a^9(fTZ8^8MkUGxE)aD?vR()N$WUDqY<(w@T+7E%_p&7Pv7UC50`0Z(bfEdKY)z}f+g@O1K zOFGZFy#7mb>4CwfBoXrB2>J|bGwUZC{tB&})j)m4O=D!MMIxW7v|k6bD_XB>iea{r zU8lLpryr*)&MF6-!<5ko>c4r;#9I~&cJV=hWwYc*&$0w52j@X1F@{GVW`PDE!9}^& z7DjqZ2U@(t1#_9f`-GHq0Sm@tEEZ} zmv4@n)NgC6yPv`K!#h_bvz^wh*_2FVR1=sE3brYM{Bb-?0*5Uk4}0iT&}!}>ON;%G z#`%?aRc+k8taG+vTi5&I-A^_ZmRL}!xrc@z&P^T*=T z_mrrAT2?Z0MO5`-#n=yfRu^FEc>6$6~LD`@*6*sik49V6upBEKDbxEKpjP=W>HGq125 zUj6~uG5|Oa)|j7+BLWsY2)fC12Xy0h2p?qfQrnSr?Gi!F(emNcqN{~3AY%)$6{RP! zd2RL8`L?y!C%b*G5X~hmR$JvZu($67@!dS{mNImq6>^PJdAy^!i%Je|2FQGSx4(F;|NrBM(Ov$ajTpMX$;^B}P-z4ImyZYuyq~3Vl42M-h{=yLPmYJiCi=l2FyXa%C8&18(jqXC z4a2BGgJ7EnuT_rz!iagqnb{o0e4fwp-PHT?DJw5=r6`r!4 z3w}=XBCcNC%DQ&u^S$8WE;s`M@YvP~pt7P{857M#0$b9TjOS}m)q@Z0gP5hqA4-W~ zf2PJvq&HHO5IZV%1Il!;h06{}UUO2+__`qX!XLq%!~v(g%Qg!V>O{anx*eo5mKQ8MDA}52WH#LVj**ogRcS0A(&q2>|7(r4SI$!!Hg;sMl;K zUI}!m+gP*@I(lvY?H#dy-7Ul>+Z@c{?|cI#l|rR;pv=uNI7HS+&mNA&DSx-&cqMv4 zz))S8U&5#(l^Moh&d%{vx$Lln0p)mJNyoOj>DoV+02scGTlX?>#kXQ6rO6AFm%qV$ z2Jub&3xcnL6h_q5`@u%jG_*J+a3on@2@0oxb;SO`K}=JnWGZn$K`Ggn0!GKf;5Mnd zYSL7LGGwyG<2QW;c2n>e?S!>tljdfB3ZPLH_&bv1xCyP%X(#X4O-!h9Kweq>oN-yl zYH zTYE#24corv&0*=*DF$8snMsk0EOB+)4=KF3+b*v>^l_E^m)adWeK%fw`H{tDq-d|Q z!kXl$FgLV=Ll_xC>rz_!4S50+1a^=3iA9G=ZmoH{S_=T`RgjOEH7^*;18Ws~msbjOFh-mLi(%;_Qp``nY>U{QH4-}~xqa&91AmeA<=CphY3ulG0(qSL`9Axd zxub(Qt!i+NjCiAT=Rd3a8~1zUK%H$hXafxF#Mx@87}o8d(#gb>Tnqn1hnagfRkim# zY>MOYON%Vx<-U(3@2ng>SLrS7=Ekl+H%;Sjs`LVDTjVO`6pLQ#C%q)xOl)t7(b6vo5WahVoq1n2d=RN8z0uXwZ&z@mD zcKd0G7;LyugI%EzLcE1ia_+j65+(>&|1|~?1odglZ>|8%WqG$VaY`IBfJImhS_NIt zTCTOJxYYc+g?KduP$Fu?KmZ#y8|NA7@&=zb-7*LX-ACr!HvM6w^l?3goYc6ht|QBL zv(o@3W%o$3QM}!--!Ev6z!-D86Q$oX8iucO#?EX&CYzz2&JPI}rMD`&&ak1kum6F( zvaf}4qofkR@KrX17>e#sR{70>0W77}4M0jMB@D4oCmv>jhdpV|U&r%aTvb=s^0Tfn zT$_@~VF$)m?UW=xz|}}AYzAovLF(~N@MalS===G}4?LvhwXnoE^KB7D4MMOB+ynXdL-kIMjaa+G|9ouZ<^jquTP4`M9b{?!puq7H<<#&-gXyj5r*yqnxaedP zcj)@fFx%?5umhyGE-4<{JJJeV!KR)pJ+H`P--7zfzt} z;w_z0X5ZEtL#P7V6tI6$^YJp)w0q_qaLNv^=qL?m|2Ly1im#@4fNc|KbMxw$34U9~ zB5Y9a{nJ~ehZ>`fHyblIjOOfG!(|k~^7`W#%@kR53ii4JE(aw40k*3jdUjPgSmW-m zztLI0J3L_)di_i4FXoz7j$W9y@+s=ox)7!92IwZ+y?tdKQpWpNGOiy5Omo1`B9omN zfdBllui%4Q`VM`)ztQ(7m2J<1K*bDL>0rr`k}ju*t-@uz54=W)dh9A^I7+Vd9<>x z{HhlbDfZGH22YG_r~7QT<5Yir(&WEImdZ}W$GQ8flvtqk7yv{7{_A@A&OMONpNvy~ zloY27)wwlWuSmDjvMX$z-RMt03>jC2s!c=0n*{$|f4jjoVNH|CXd9+d0vL^WueA8f zOmIp^>G|_SHf`I9v%Y&jwBHr1zrDpTKWBeQr*y?LsPs+=jQrL!@XOm~yxTRCWiaBC zb9})+?@18*bhE?y>3j(haBDfy7*>0mJ|7yx}UKK-%! zu=svyX~iuf9789-0@E;txsNiURXs-+j)gjXGZ#JEKA=7m3=0l2t9-ej>w~Bt63-_6xs!I z=$!5L8&8PjuE$+$dxT1pjrnIc7EzjSGo<}l0+)PDsmV*IBU``SP9;8${29y+h9wOh zz--2tW58Fl#V&J|;T4mM@hcy9z}>b4`8_MtEVa&7!S@&c6p{42_*tLi-@B$chZU1KZ07eI;`N#qyDmSfFWfw$TdBLAo~d7U ztt|+Dkfo+vCWBfYq9}NxAF6b8jitE=HBm{HjIoid20!F4>-A;<#8eU`g}GR=kSar@ zzQ>IYvwL2IIbVF@AI4eD;kV3@c#C(;q)J8o!08c7;4Uxyvv3(CtfL7^<5I1wR~+ z^tQYzoD8@?0l7d*SL=8BMJVtZoxBz%!f;*HZO{C(Y(=TfT^=MJrDDCHUl#1$up=(x z?V}BasP`z(I=)u|hy%xA{4%Xv|!}NxoRBB#!+}bqT8#^rDA2*3^-pq zDwWz1bWQ)pH8@}hY?;Kn>DeU}zKk|r6j4$PQ0Bdgrq9)qAvygs85*}I$61ji9wC!P zA7sB^pEbym!#zr;V~dWQUzTuN0=+1^LR#Hj37s@=c)W zPgfrioPr|@Akn^isj00PLSfc!1rI7ND`KP8B1)k54U2eHBsN{j>fR$w@sQ;O@mg1O zAiwVkl`$hyvmLd@V@r}pq1cp|^9x|VgzQ5~zY1m4w2s5@&MnzImS&<*UU5XVF^SSr zfX9>E2RItX1hk#g0@;breOoD7$!2YoXngySVsDc~dCYbY79*0I1Mc|6$jWQ3GGRNL zbF3zk<=2a)sWNiP9z6%c%{kyo1_Gw?ge{@Y==n{FYMZgtNvAA@FaVBOiBi|h&r;N`dk_S>jrPgUINkK z+b`!KeNCkz8iI?Qi!7Z125$hmuVvXi^2^2lLRxtLa7?*a)gG$>7meg+W_u)L#iVGS z{*2`~s(#7|q(FuwzQH5gW%Vj;B=mYDQ|gb6Oz)ERhhFU`WGUO|p@+6$tWOxafST|% zCz!+ST4I#&$E(&S0!f$9ayfNDG|qoSP#PELWqWfXHy(0F3d2@(TMZ)ADQZc_a(uk3 z^m7liUxlG?B@-n*vI`>K?W;Z63HJUMW?hH${M$1rXi1L9t!ReCh>rEM6G@}=7pBS1ufG)GK#f+RypwCFK3r-DW zywnB*k@}gx4-=oyA9(~YFSO`?Avt!|$b4vzrNwK(x2SjfS)(uEoSVz-B6s(psl z+{O%*bhnHRJ8`Q=)N5>@{#&xKS+_n=yh zgoaUOkVrck$eET8`#UUV6!+=p;~QGkZ^~H_$sd2# z@9~-uYW|wqCGUkcmx`zVz$!Y%49-Y+da$?(Scm>&P*6wwCByv**l4Wt?pODGF8Ijt zf5y!rIya1;Qx1Q6`;@~?ash-&@JlwrmYGOWLbYMwYz@&_izXnT1S49V$n^SlH^+dm*{(!4824PKe`-~S{ zBElse!qmbAN}dBS=sDKwqPZ6K;hWd?tXy6;PW6!dfjK;_)0|?}{bBy*>o@h>#|Id%npft#eFk|`#{@bc<%V1@cKDO`udDgRuQ;cxeQUH zmM5>g*sT+DbLryUx@R;lTRP6{V92XAsrndZh4 z>O}(e+UD^>i(iK`cHH{f-&`;xh`@rbQrsS}M6?oq{l&wx6E|LeZyeNL-z=r80Z`6D zS(0?0;tf42JSR6<+VNMK6i%xoR2l<`W8!k<8K%FTZr7m=)BKu%>*_UBBJC3AqTIFT z6)VMz8s&>{_G;Zf`Dj-) z?R*(I{>#)8g?A~ex97d!M9NtN;*W#S0mGJA5JWZa#d@&~0HA-Q%V+?AKvPhO0+6qW zL=+hTJCQuE>!H1{4ySGL*GX-Zm*NyJY+)!x+@SIM)Yr>?4>bdCrNNJswb{AFp>gV z3Zio-Ub9owtGa!ptjwRMAY z-AJ=3i7&@bR&^5vHg}k6_RoU~_o=Q3nN@zQ|DDvAN z0$M9Kh7!U#c$V1qhGs{>R<#N0Q4Rew@Y8ct(j0A@^TkK)SW@~k&%`Vhj!;JjR3AUT z{a964k#p;95U?7ovF>_M=82up-qIoo)2zzRf+w&qVq6VNdx3eVLArIiOMVD!n8kWm zHN4c0Ik%xUj1Cw^&52Y{tQr}RbP<5Gqv4nwi+ekAQUb$>%($$6lS7`5zoZ+r2^<2| zRGT!>)QqdVEVomDYWsLY>a#=lz)x4@b@x$ll@gwm=vS}lUnzPq34p=kC5d)XUB0VB z@#e;~3Y5i4UTn-d)13$Qy9Vkl2*KiGh7EE$+BCojw&aSFl?!(il~=()=PeEpG3?Xj z@DECWHeJm-w~r(!MNNueQPcp!q;`2VL-TMKJ~76*l&y z{=Nn;k~#2N&|Pr}<=I_slpxrYfkCDrLvgVRCk$#9_S`fP3|$f_cTZ%6#nf#;VTBsZ z;{=wXM}$=6)v!U)mqgb7cJLC9T|DUAIO0U~V#Bi7%D%Kcwd!jHQ>?};DW5EZ0oupg z)NK>+q2Y?x@_xq?xJN?KEc{fNAqOM|AUI}qDJWNbp!FnRJSWsM2mzrav8cJoX5lR* z)#h5655g?9=RQiQY-TNU%-~|U$Ar>Qt!1ar?vo!Eg1{Q3-}Dc;>3LCYW_9z@-NX%k zOJ^b=(917}x`T=?>OS-QDstJDPh&sBIO;*e7O2=Sph#gkbtrpZO&mx`AY&-9j`rHK zij^Z$6o|%UTA<-Xli1b$7qWF!1eyw2hP8(qwCxwxPdxe1J$rRS{z>ejsE&8@=2!h4 zB`h#seEjQyS?6AETcku3<-Pp8|EQcNUQc1wi%=ODSvWL*6;y}So_qGr4hB)(OvL3VNWXQ8{U~J(L~X}2^Y?0e7trTdtyuu#g6LmmyXel!*f27 zjxyPlbFMK+fdpjwKtNKeQNy>Kc9ZX^ZlY{aW^}R4MkTr6{bA%**M|$bl#Z%oi(R3!>q zYQ|Uxwcreg+SC!gt_yI)2aNOT$&c!Llda`;>oM8I8JA^NFDo1e(~o^uvIp1q8@xOa z+V6N&c8OMD+p|KZn!efYkC)LnEH9lRA5cBGe+9f^E;7SkekFPm?sa9UF!jGtpNk!I z=2)ndnt*5kme2g8>(wJoc}yHy^v=y-yniu&(}UPVZ2sGubs}}TGbWOV{X)!`4Yi^dw=v^&tW zpLo);6{$Z!#dc#|at@e;f{`@e37w$b2SzpXH{Xxn|1I5C+Mpht%^8|bmZ0qCHQZPy z_854JR9DQ=p~r!!R_jM}l>OVNEFpbsq1j(y|N4Fn3tvkqVslD?H;7Bmjgmccd>iuz z;;pO{1w=klT6!$B|L~h^vLLcq)ul4Lq=1liqQ+H0wl*uPG9;VH8PkiRf~Lt->z1r( zCs`euW|7DtKQOu}18c)PYs#|UP+C^(7GQ}&5V=A{O-^;l>__8XqntK&$*j`J41G0` zmY8LI-9%$W|6loKw-q)?ngtpH>r+^^Ni((3 z+w5M0()n?v8?5f@7u25VGY1vORK_lFuldc+Y1F-2zg+|W^~N_vn-MR4(((^2Bb8xr z@l|{7_@{S)d}m5OYCL}Mmz)-V2rmwH7@+Abip(ZGfW3k*^op#u>>@i!3oFk20J{vU znpQCU@uJ8PMI|jtfyn~7O8+*v#r_VTCFebF2Ls{L^+De!I>)}Ihj33f?)`9xb}s0} z){dVQ&#yGw6jaUkU)*@x{=xdl>=!4O%ukG6Dd2#FeJdZ9eoB}q9f6b>)~+L>~jnx*!-Ka^Mt05P21S2dC{92=FY^?-J|Nx0(N2P3ixURU}#zt;xB$>(PN!S-N-xf(>uOUf_Ifbry^ zCu}WurcQS4iq7%U48_j>{<*_5T~~DS1TklA3U|8dY4kp9u^@Jj>b?X=4mvhd8P{|3T8 zh0OU#M_$Xa()H<3r1{G*8fprUkQ!(i4rN+>zwj$Js%yI^jv(anz4MzVqEFJ>&WQJu zkIWJe3vXnhlty7ps__XMn>|NB&T$%v*ZVu4+ma@d;I3=&)<5PZ+V!n%M$xkKKP-ug;v$SNnRZ|&gedE&VZ)?<EgW?!a%jW2X7+b@46Ckh7Rlf(TdD=<1~=nG5d@V)q8mk|5(qhhCmjZn*lv9Dbj zfoaax{)-t4mJ9wwR5)bE5XflmhaQbD1UZ9MWy1ZDU7>3JaHG8e}3r+5S$#~Ds zREn>H>8$(D8lc>i_p!JFq?8TYq*beB0E1ub(6oHO$R}v5Ek4l9h(btexsF0?b?hg3 zmqN^&xOqhThzRRo*W&jX=Lq>Jl{(SjORP0s(Z^(?1L2MLw5}z8OC{6qp3)p!wepHEIW^0U!9yvxkJE#r5=6-@CaOK#EHb3trz?aGbOR)hQYk4Hq_3E3 zZ|?qusY4IE4ZAgjXu_j;i1$p>sC(&h3WHZ~b~f5i#g!qi<9}s_Wv^<7pre#^QgvwV zY%EOerGBa|BdA;^iRn?W%a%t0$)34J7fDL!y?lqzIBWx9!9x9%rc0EHMqU;7DxH~A zsw_2y!50PZcwTRj03auSkAE2_Po$+Dc<(Ns9{0%HQ1TJo+IA-#Gs2SdQSqgqbvixe zg4W=WkGnPyzh`OrzGv9F*FW0M=b&<{zks1}J2n`&)+X)oSKO4087Vlfbw$!LuBQH8 z5LUY?+0O6JVgv2m8cLu-Z43ClLKd7ee;ghFNc7(Uaq z$PRGDxKxa4jnth?Jbh7z=hdQZ(!|J8P@7t;*qxbmyFyAQp7$aQ*(8R1e7)Zp=SFzP zNe4%VgF&!pkgraM@G_bq2K2LT==5E3lS1;j``*uD*$V*L-YngWB*gsj1)*cKK)Z1m zIF~EzI;DV93Iag?&#IC@kTV;r`_Kq_cK~KFMdwR2ZZkDG7&5N_2vEdzauK8ukH+-R z5YW7wp-hJt59mhgj;LlOj4s1|Z0 z^J%wW9|%EFU~KXPCR1>}BbjPJD;&F)R7bZER8T+XHgz%z_deGPhXmOAWI+k1KdT&9 z<=9O`Z5&I6TxLvf*(7mSgS>pBG{`iKW?qUHDgla+4F`4op5LM$zUMfheak{T0sX)u z@ANmTVFD*B>baeguZPvO{*+lr4Fe>lGU70l4%LG7L+&2na1=kW9B+Kipf&pUgiN}a zG@S)^ts7{j*c{P|ra2?_W9>x=F(n%0WSO-QwJ1Y5kkPV2mdpZcYZc0^KHZlZLN>TE zBu31a4E>kOYyX>-S9;|)RpYd79XdQFsk~qC7q-F%9$7cX z1b5R+P8ck_v7=;aBFgIFS_4Y(rN@_2{0_UvfV6flrESX>uloQ-x0 zIW5@B-bN6PO<`fzbIJQ1b>Z;PXE1X5Fl5!Aa5JHn9-Lr=voy%04tiXx&^5kxHUS(tc)u*zQaZHeCtysZWzMsV zBqQT#AnyX`AGR*6An)=K>9#(%DT{sm{jG==)h@|=;!E1u9&N=SguBSX z+~RgO?aw6&DRoh1P#n9PVN0$}#0N_}GwXEB1`+as8DB9V#kwlB0X-r>{#;~AtgH$o zvKPE@^-A8Wb%lwl9h_vXS!VfJp06necJujXeECN&=Viy*r-0r=R+)A)=Z#Wew(nn>_+9|T1?kT<8 zMmQwYd%wF|yHVxfc?ZJL=Q?r*dzhOO6hn6?5Hneyd!2owU1-OdFj`x`=?^RZ`S0hB zJCi_?l{QZBprbF{NBrcB7nw<6-ba;e%JR&LlBIkPRu?!0oHk1+-a37B<_-WHat+y3 zH)A5=s+9IBZQ*{`@E>-+r*r|!ZGOkYimG#;YM(>AolunuEiZ8HcTVcFJ~<8cUbOzU z_qt7Q{U>@xsyXf)lMRtHL@d~Vha&WTuoTBfydNhs;c8D$y;8^z&GxrCH{ul*_0Mk^ z@lpGY`#8r~H`$&ut$k)u{S;(>s@iGJv7UTBL}6lTclPmDwdv+hs9SITPXByxCjC6f1qJHB z;L#ak*+hzHC1qFB_IDv-i^b23ro&c449$+5SB@wOZEP2`5e=osN^ zC>yU<1v$aLf{p(&Xd?CG2?i{d``6bU;5oGk5hx|#qVaJ-LRnwxiAAF^LgS(M0Wn4h z3+?wJ4K|B>;PwKbEzZP)>WL`BlYra**m?cn7|i}}6Ss7De1u_|+{pZaYi^Rr1xR0{ zd^DembGluKIExXAGiqRQOo1T=O-@02Uz1T0kN3v^;JfNy$v_Hk5bd0`YGo}#7L zn_cuo27qoCg*}#3g78~zcsci)8p^)Op8xx=!X=s}xqy)^#xFtOI( z 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 Date: Wed, 2 Jun 2021 23:20:40 +0200 Subject: [PATCH 32/32] Added flipTextureWrapH --- src/engine/Engine.java | 2 -- src/engine/input/KeyboardInput.java | 2 ++ src/engine/object/ObjectGl.java | 19 +++++++++++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/engine/Engine.java b/src/engine/Engine.java index f8c3c3c..657804e 100644 --- a/src/engine/Engine.java +++ b/src/engine/Engine.java @@ -270,8 +270,6 @@ public class Engine { Vector3f vecTransView = new Vector3f((-zangief.getXPos() - engine.viewXPos) - 250.0f,0.0f,0.0f); engine.translateView(vecTransView); - System.out.println(zangief.getXPos()); - System.out.println(engine.viewXPos); /* ******************** diff --git a/src/engine/input/KeyboardInput.java b/src/engine/input/KeyboardInput.java index 995b650..0bc484c 100644 --- a/src/engine/input/KeyboardInput.java +++ b/src/engine/input/KeyboardInput.java @@ -107,5 +107,7 @@ public class KeyboardInput extends GLFWKeyCallback { keyPressed = true; } if (!keyPressed) token.setTextureWrap(58,0,62,82, ObjectGl.STICK_TOP); + + token.flipTextureWrapH(); } } diff --git a/src/engine/object/ObjectGl.java b/src/engine/object/ObjectGl.java index 4144a58..1abcef6 100644 --- a/src/engine/object/ObjectGl.java +++ b/src/engine/object/ObjectGl.java @@ -27,8 +27,7 @@ public class ObjectGl { public static Matrix4f projection; public static Matrix4f view; - - /* + /** * xPos and yPos will stop to be relevant if you use rotate function */ private float xPos; @@ -44,6 +43,7 @@ public class ObjectGl { public boolean useTime; private Texture texture; + private float[] textureWrap; /** * Create a rectangle shape, use setTextureWrap to correctly align the texture with the model @@ -76,6 +76,7 @@ public class ObjectGl { this.height = h; this.width = w; + this.textureWrap = Primitive.stdTexWrap; this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap); this.scalingFactor = 1; @@ -199,6 +200,19 @@ public class ObjectGl { this.setTextureWrap(result); } + /** + * Reverse the textureWrap left to right + */ + public void flipTextureWrapH(){ + float[] textureWrapTemp = new float[] { + this.textureWrap[2], this.textureWrap[3], + this.textureWrap[0], this.textureWrap[1], + this.textureWrap[6], this.textureWrap[7], + this.textureWrap[4], this.textureWrap[5] + }; + setTextureWrap(textureWrapTemp); + } + /** * Set a new shader to be used by this object * @param vert path to glsl Vertex Shader @@ -223,6 +237,7 @@ public class ObjectGl { } private void setTextureWrap(float[] texture){ + this.textureWrap = texture; this.vertexArray.swapTextureBufferObject(texture); }