Merge branch 'master' into 'Gameplay'

# Conflicts:
#   .gitignore
This commit is contained in:
François Autin 2021-05-27 15:31:16 +00:00
commit ccf004ee0a
40 changed files with 1716 additions and 31 deletions

4
.gitignore vendored
View File

@ -1 +1,5 @@
/.idea/
/.gitignore
/jeu-de-combat.iml
/target/
/bin/

9
.idea/jeu-de-combat.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/jeu-de-combat.iml" filepath="$PROJECT_DIR$/jeu-de-combat.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -2,11 +2,18 @@
Jeu de combat inspiré de Street Fighter III: Third Strike, réalisé dans le cadre du projet de fin d'année de L3 Info de l'ISTIC (2020/2021).
## Technologies employées
* Java
* OpenGL via [lwjgl](https://www.lwjgl.org/)
* OpenAL via [lwjgl](https://www.lwjgl.org/)
* [JavaFX](https://openjfx.io)
## Contributeurs
* François AUTIN
* Victor AZRA
* Indy BOYEAU
* Antoine DUPUIS
* Léo NOLIÈRE
* Rémi RATIVEL
* [François AUTIN](https://gitlab.istic.univ-rennes1.fr/fautin)
* [Victor AZRA](https://gitlab.istic.univ-rennes1.fr/vazra)
* [Indy BOYEAU](https://gitlab.istic.univ-rennes1.fr/iboyeau)
* [Antoine DUPUIS](https://gitlab.istic.univ-rennes1.fr/18002392)
* [Léo NOLIÈRE](https://gitlab.istic.univ-rennes1.fr/lnoliere)
* [Rémi RATIVEL](https://gitlab.istic.univ-rennes1.fr/rrativel)

Binary file not shown.

84
docs/grammaire.txt Normal file
View File

@ -0,0 +1,84 @@
Version modifiable:
Alphabet {ε , arène[1 à n], perso[1 à n], perso[1 à n] (bot), joueur 1, joueur 2, bot,
j1, j2, ordi, a, b, x, y, l1, r1, haut, bas, droite, gauche, egalite, vrai, faux, n, s,
}
JEU -> PARTIE | QUITTER
QUITTER -> ε
PARTIE -> ARENE PERSO JOUEUR, PERSO JOUEUR, ROUND1 | QUITTER
ARENE -> arene1 | arene2 | ... | arene n
PERSO -> perso1 | perso2| ....| perso n | BOT
BOT -> perso1 (bot) | perso2 (bot) | ....| perso n (bot)
ROUND1 -> ROUND, VAINQUEUR ,ROUND2
ROUND2 -> ROUND, VAINQUEUR ,ROUND3 | ROUND, VAINQUEUR, JOUEUR, QUITTER
ROUND3 -> ROUND,VAINQUEUR, JOUEUR, QUITTER
ROUND -> JOUEUR ACTION JOUEUR ACTION
ACTION -> ATTAQUE | DEPLACEMENT | DEFENSE | FIN DE TIMER | GAGNE | (+ cas ou le joueur ne bouge pas)
ATTAQUE -> n,NORMAL | s,SPECIAL
SPECIAL -> a SUCCES ACTION | b SUCCES ACTION | x SUCCES ACTION | y SUCCES ACTION | (+combinaison de touche)SUCCES ACTION
NORAML -> a SUCCES ACTION | b SUCCES ACTION | x SUCCES ACTION | y SUCCES ACTION | (+combinaison de touche)SUCCES ACTION
SUCCES -> vrai | faux
DEPLACEMENT -> haut ACTION | bas ACTION | droite ACTION | gauche ACTION |(+combinaison de touche)ACTION
DEFENSE -> l1 ACTION | r1 ACTION
FIN DE TIMER -> egalite
GAGNE -> vrai | faux
VAINQUEUR -> joueur 1 | joueur 2 | bot | egalite
JOUEUR -> j1 | j2 | ordi
extension a inserer de dans la grammaire
action (+ cas ou le joueur ne bouge pas)
attaque/deplacement (combinaison de touche)ACTION
est ce que toute les commandes ne devriat pas être directement dans action?
ex: arène2 Perso3 j1 Perso1 j2 (liste des actions1) joueur2 (liste des actions2)joueur1 (liste des actions3)joueur1 j1 ε
"lsite des actions" correspond a action durant un ROUND (expliqué plus bas)
signifie que dans la partie, l'arène 2 a été selectionné, le joueur 1 a pris le personnage 3 le joueur 2 le personnage 1,
les joueurs ont effectué une liste d'action qui ont fait que le joueur2 gagne la première manche, les joueurs ont effectué une
liste d'action qui ont fait que le joueur1 la seconde, les joueurs ont effectué une
liste d'action qui ont fait que le joueur 1 la troisième, le joueur 1
gagne donc la partie, la partie prends fin
ex:
liste de actions1: j1 gauche n a vrai s b faux n x vrai s l1 vrai droite....faux faux j2 droite n b vrai n b vrai s a faux ....true true
le joueur 1 a d'abord effectué (dans l'ordre) un deplacement à "gauche", puis une attaque "n" normal correspondant a la touche "a"
qui a aboutit "vrai", puis il a lancé une attaque spécial "s" en appuyant sur "b" mais elle n'a pas aboutit.... il n'a pas
gagné ce round, ("faux" avant le j2), le joueur 2 a appuyé (dans l'ordre) sur les touches "droite", "b", "b", "a".... et a remporté ce round.
ex2: arène1 Perso1 j1 Perso1(bot) ordi (liste des actions1) egalite (liste des actions2) bot (liste des actions3) bot ordi ε
signifie que, l'arène 1 a été selectionné, le joueur1 a pris le perso1 , il a joué contre un ordi qui a pris le joueur1,
le premier round n'a pas donné de vaiqueur (a cause du timer), le bot gagne le second round, le bot gagne le troisième
round, l'ordi gagne donc la partie, la partie prends fin
ex:
liste de actions1: j1 gauche n a faux s b faux n x faux l1 s y vrai.... egalite ordi droite n b vrai n b vrai s a faux.... egalite
signifie que le joueur 1 a appuyé (dans l'ordre) sur les touches "gauche", "a", "b", "x", "l1",... le timer a été
écoulé il y a une égalité, le bot a appuyé (dans l'ordre) sur les touches "droite", "b", "b", "a"....le timer a été
écoulé il y a une égalité

27
docs/syntaxe.txt Normal file
View File

@ -0,0 +1,27 @@
(interface graphique)
Launcher -> fct Start qui permet de lancer le menu afin de configurer la partie, elle ne prends aucun paramêtre
Menu -> fct Selection qui permet de choisir une arene et un joueur
(moteur du jeu)
Engine -> fct game qui lance le moteur du jeu avec les configuration correspondant a "Config" (ex:arène et skin perso)
(gameplay)
->fct _ qui lance la boucle du jeu (cf gameplay_loop2.drawio)
element moteur du jeu (https://docs.google.com/document/d/1eCxAiBJTWdCK0AfzmLIlXzun_GEAG0jeMs8qg8kWJqs/edit)
Config -> toute les config selectionné dans le menu (arene, nb_joueur, perso)
Config est un tableau (d'entier?)

11
pom.xml
View File

@ -21,6 +21,7 @@
<properties>
<lwjgl.version>3.2.3</lwjgl.version>
<lwjgl.natives>natives-windows</lwjgl.natives>
<javafx.version>11</javafx.version>
</properties>
<dependencyManagement>
@ -90,6 +91,16 @@
<artifactId>lwjgl-stb</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
</dependencies>
<url>https://gitlab.istic.univ-rennes1.fr/fautin/jeu-de-combat</url>

View File

@ -0,0 +1,10 @@
#version 330 core
out vec4 FragColor;
uniform float time;
void main()
{
FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}

View File

@ -0,0 +1,12 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
}

View File

@ -0,0 +1,12 @@
#version 330 core
in vec3 color;
out vec4 FragColor;
uniform float time;
void main()
{
FragColor = vec4(color, 1.0f);
}

View File

@ -0,0 +1,16 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = aColor;
}

View File

@ -0,0 +1,13 @@
#version 410 core
out vec4 FragColor;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{
FragColor = texture(texture1, texCoord);
}

View File

@ -0,0 +1,16 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 2) in vec2 aTexCoord;
out vec2 texCoord;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
texCoord = aTexCoord;
}

View File

@ -0,0 +1,19 @@
#version 410 core
out vec4 FragColor;
in vec4 color;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{
vec4 tex = texture(texture1, texCoord);
if (tex.a == 0.0){
FragColor = tex;
} else{
FragColor = mix(tex, color, 0.5);
}
}

View File

@ -0,0 +1,19 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec2 texCoord;
out vec4 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = vec4(aColor, 1.0f);
texCoord = aTexCoord;
}

View File

@ -0,0 +1,21 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec2 fragCoord;
out vec2 texCoord;
out vec4 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = vec4(aColor, 1.0f);
texCoord = aTexCoord;
fragCoord = aPos.xy;
}

View File

@ -0,0 +1,21 @@
#version 410
out vec4 FragColor;
in vec4 color;
in vec2 fragCoord;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{ // Pas fini c'est moche
vec4 colorPoweredUp = abs(vec4(color.xyz * sin(fragCoord.y + time*20), 1.0));
vec4 tex = texture(texture1, texCoord);
if (tex.a == 0.0){
FragColor = tex;
} else{
FragColor = mix(tex, colorPoweredUp, 0.5);
}
}

View File

@ -7,27 +7,17 @@
*
*/
import launcher.Launcher;
import engine.Engine;
import launcher.Launcher;
import javafx.application.Application;
public class Main {
// Interface de configuration et lancement
static Launcher launcher = new Launcher();
// Moteur de jeu
static Engine game = new Engine();
public static void main(String[] args) {
// Lancement de l'interface de configuration du Jeu
try {
launcher.launch();
} catch (Exception e) {
e.printStackTrace();
}
Application.launch(Launcher.class, args);
}
}

View File

@ -0,0 +1,165 @@
package configuration;
import java.util.Random;
public class Config {
// tester a la main (okay normalement mais ajouter des test)
public static void main(String[] args) {
int[] tempfortest = { 0, 2, 1, 1 }; // {arene/nb_joueur/perso1/perso2} 0=alatoire
config(tempfortest);
}
// les variable a configurer
// sel1 pour savoir si on a deja selectionner le joueur 1
public static String arene, perso1, perso2;
public static int nb_joueur;
private static boolean sel1 = false;
/*
* fonction config qui prend en entre un tableau d'entier chaque case
* correspondant a une variable, et ne retourne rien mais modifie la valeur des
* variables par des fonctions annexes
*/
private static void config(int[] tab) {
int i = 0;
while (i < tab.length) {
switch (i) {
case 0:
SelArene(tab[i]);
i++;
break;
case 1:
NbJoueur(tab[i]);
i++;
break;
case 2:
SelPerso(tab[i]);
i++;
break;
case 3:
SelPerso(tab[i]);
i++;
break;
/*
* case 4: ?
*/
default:
System.out.println("ERROR OUT OF BOUNDS CONFIG ARRAY");
i = tab.length;
break;
}
}
System.out.println(arene + " " + nb_joueur + " " + perso1 + " " + perso2 + " " + sel1);
}
/*
* fonction SelArene prend un entier en parametre et permet de choisir l'arene
* du jeu
*/
private static void SelArene(int s) {
switch (s) {
case 0:
SelArene(random(1, 2));
break;
case 1:
arene = "arene1.png";
break;
case 2:
arene = "arene2.png";
break;
default:
System.out.println("ERROR ARENE INEXISTANTE");
}
}
/*
* fonction NbJoueur prend un entier en parametre et permet de determiner si un
* bot sera necessaire
*/
private static void NbJoueur(int s) {
switch (s) {
case 1:
nb_joueur = 1;
break;
case 2:
nb_joueur = 2;
break;
default:
System.out.println("ERROR NUMBER OF PLAYER");
}
}
/*
* fonction SelArene prend un entier en parametre et permet de choisir le
* personnage en fonction du joueur
*/
private static void SelPerso(int s) {
if (sel1 == false) {
switch (s) {
case 0:
SelPerso(random(1, 2));
break;
case 1:
perso1 = "perso1.png";
sel1 = true;
break;
case 2:
perso1 = "perso2.png";
sel1 = true;
break;
default:
System.out.println("ERROR PERSO INEXISTANT");
}
} else if (sel1 == true) {
switch (s) {
case 0:
SelPerso(random(1, 2));
break;
case 1:
perso2 = "perso1.png";
sel1 = false;
if (perso1 == perso2) {
perso2 = "perso1_swapcolor.png";
}
break;
case 2:
perso2 = "perso2.png";
sel1 = false;
if (perso1 == perso2) {
perso2 = "perso2_swapcolor.png";
}
break;
default:
System.out.println("ERROR PERSO INEXISTANT");
}
} else {
System.out.println("ERROR SELECTION PLAYER");
}
}
// fonction nombre aleatoire entre deux borne
private static int random(int min, int max) {
Random random = new Random();
int value = random.nextInt(max - 1 + min) + min;
return value;
}
}

View File

@ -1,14 +1,305 @@
/**
* CLASS ENGINE
*
* Classe principale du moteur de jeu
*
* @author François Autin
*
*/
package engine;
import engine.math.*;
import engine.object.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Engine {
private static long window;
private final List<ObjectGl> objectsGl;
private static boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1);
private boolean running;
/**
* Create the engine and initial attributes use .init() to start the engine
*/
public Engine() {
this.running = false;
this.objectsGl = new ArrayList<>();
float width = 1280.0f;
ObjectGl.projection = Matrix4f.orthographic(-width, width, -width * 9.0f / 16.0f, width * 9.0f / 16.0f, 0.1f, 100.0f);
ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f,0.0f,1.0f));
}
/**
* Start the engine
* Create the window
* Set the color of the background
*/
public void init() {
glfwInit();
this.running = true;
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //On utilise la version 3.3 d'openGL
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Compatible MAC
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Le core profile est l'interface 'avancé' d'openGL
int width = 1280;
int height = 720;
this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL));
assert getWindow() != NULL;
System.out.println(present);
// On ©cupère les informations du moniteur principal
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
assert vidmode != null;
// On met la fenêtre au centre de l'écran principale
glfwSetWindowPos(getWindow(), (vidmode.width() - width)/2, (vidmode.height() - height)/2);
glfwSetKeyCallback(getWindow(), new Input());
glfwSetInputMode(getWindow(), GLFW_STICKY_KEYS, GLFW_TRUE);
// Contexte = zone cible des rendus
glfwMakeContextCurrent(getWindow());
glfwShowWindow(getWindow());
GL.createCapabilities();
glfwSetFramebufferSizeCallback(getWindow(), resizeWindow);
glEnable(GL_DEPTH_TEST); // Z-Buffer plus z est grand plus l'objet est proche de la camera limite à 100.0f au dela l'objet disparait
glEnable(GL_BLEND); // Transparence
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
System.out.println("OpenGL: " + glGetString(GL_VERSION));
}
/**
*
*/
public void update(){
glfwPollEvents();
}
/**
*
*/
public void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
objectsGl.sort(new SortZ());
for (ObjectGl objectGl : objectsGl) {
objectGl.render();
}
int error = glGetError();
if (error != GL_NO_ERROR) System.out.println(error);
glfwSwapBuffers(getWindow()); //Envoie le buffer vers le moniteur
}
/**
* Add obj to the render queue
* @param obj
*/
public void add_objectGl(ObjectGl obj){
objectsGl.add(obj);
}
public void remove_objectGl(ObjectGl obj){
objectsGl.remove(obj);
}
public boolean isRunning(){
return running;
}
public void setRunning(boolean b){
running = b;
}
public boolean shouldClose(){
return glfwWindowShouldClose(getWindow());
}
public static long getWindow() {
return window;
}
public void setWindow(long window) {
Engine.window = window;
}
/**
* Est appelé àa chaque modification de la taille de la fenêtre, et modifie la taille de la zone de rendu
* pour quelle corresponde à la taille de la fenêtre
*/
private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback(){
@Override
public void invoke(long window, int width, int height){
glViewport(0,0,width,height);
}
};
public static void main(String[] args) {
Engine engine = new Engine();
int speed = 10 ; //vitesse déplacement Object
engine.init();
// Add objects to render
String path = "textures/zangief_sprite.png";
String path2 = "textures/awesomeface.png";
ObjectGl zangief = new ObjectGl(0f,60f,80f,10f, path, null);
zangief.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
engine.add_objectGl(zangief);
zangief.translate(new Vector3f(-5000.0f,500.0f,10.0f));
zangief.setColor(new Vector3f(0.0f, 0.0f, 1.0f));
zangief.useTime = true;
zangief.setShader("shaders/StylishShaders/BasicVert.glsl","shaders/StylishShaders/EnergyWave.glsl");
// ObjectGl smiley2 = new ObjectGl(0.0f,500.0f,500.0f, 1f, path2, null);
// engine.add_objectGl(smiley2);
// smiley2.translate(new Vector3f(0.0f,0.0f,5.0f));
long timer = System.currentTimeMillis();
long lastFrame;
int frame = 0;
boolean nextFrame = false;
while(engine.isRunning()){
lastFrame = System.currentTimeMillis();
// Game logic should fit here
if (present) {
gamepadInput(zangief, speed);
}
input(zangief, speed);
// input(smiley2, speed);
/*
********************
* essential part v *
********************
*/
engine.update();
engine.render();
frame++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frame);
frame = 0;
}
while(!nextFrame){
nextFrame = System.currentTimeMillis() - lastFrame >= 16.66f;
}
nextFrame = false;
if(engine.shouldClose()) engine.setRunning(false);
}
}
private static void gamepadInput(ObjectGl token, int speed) {
ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1);
FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1);
assert gamepadAxes != null;
assert gamepadButton != null;
String name = GLFW.glfwGetJoystickName(GLFW_JOYSTICK_1);
System.out.println("GamePad Name :" + name);
// for (int i =0 ; i < gamepadAxes.capacity(); i++) {
// System.out.println(i + " :" + gamepadAxes.get(i));
// }
if (gamepadButton.get(0) ==1 ) { // appuie sur croix(PlayStation) A (Xbox)
token.translate(new Vector3f ( 0.0f, speed * 5.0f, 0.0f));
}
if ( (gamepadAxes.get(2) < -0.1 || gamepadAxes.get(2) > 0.1) ) { // de droite à gauche //joystick gauche
token.translate(new Vector3f (5*speed * gamepadAxes.get(2), 0.0f, 0.0f));
if ( gamepadAxes.get(2) < -0.1 ){
token.setTextureWrap(121,0,57,80, ObjectGl.DEFAULT);
}else if (gamepadAxes.get(2) > 0.1) {
token.setTextureWrap(178,0,62,82, ObjectGl.DEFAULT);
}
}
if ( (gamepadAxes.get(3) < -0.1 || gamepadAxes.get(3) > 0.1) ) { // de haut en bas //joystick gauche
token.translate(new Vector3f (0.0f, -5* speed * gamepadAxes.get(3), 0.0f));
}
/* Buttons
0 : Croix / A
1: rond /B
2: carré / X
3: triangle / Y
4: L1 / LB
5: R1 / RB
6:select
7:start
8:L3
9:R3
10: haut
11: droite
12: bas
13: gauche
*/
/* Axes
0 : left X axe ( right : 1 left -1)
1: left Y axe ( down : 1 , Up -1)
2: right X axe ( right : 1 left -1)
3: right Y axe ( down : 1 , Up -1)
4:L2 / LT : 1 active, -1 unactive
5: R2 /RT : 1 active, -1 unactive
*/
}
public static void input(ObjectGl token, int speed) {
boolean keyPressed = false;
if (Input.isKeyDown(GLFW.GLFW_KEY_S)) {
token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM);
keyPressed = true;
} else if (Input.isKeyDown(GLFW.GLFW_KEY_W)) {
// token.translate(new Vector3f (0.0f, speed * 5.0f, 0.0f));
keyPressed = true;
}
if (Input.isKeyDown(GLFW.GLFW_KEY_A)) {
token.translate(new Vector3f (speed *-5.0f, 0.0f, 0.0f));
// token.setTextureWrap(121,0,57,80, ObjectGl.STICK_TOP);
token.setTextureWrap(121,0,57,82, ObjectGl.STICK_TOP);
keyPressed = true;
}
else if (Input.isKeyDown(GLFW.GLFW_KEY_D)) {
token.translate(new Vector3f (speed * 5.0f, 0.0f, 0.0f));
// token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
keyPressed = true;
}
// if (!keyPressed) token.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
if (!keyPressed) token.setTextureWrap(58,0,62,82, ObjectGl.STICK_TOP);
}
}

26
src/engine/Input.java Normal file
View File

@ -0,0 +1,26 @@
package engine;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWKeyCallback;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
public class Input extends GLFWKeyCallback {
public static boolean[] keys = new boolean[65536];
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
keys[key] = action != GLFW.GLFW_RELEASE;
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
else if(key == GLFW_KEY_SPACE && action == GLFW_PRESS) //Switch to wireframe
if (glGetInteger(GL_POLYGON_MODE) == GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
public static boolean isKeyDown(int keyCode) {
return glfwGetKey(Engine.getWindow(), keyCode) == 1;
}
}

View File

@ -0,0 +1,75 @@
package engine.graphics;
import engine.math.Matrix4f;
import engine.utils.ShaderUtils;
import engine.math.Vector3f;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.opengl.GL20.*;
public class Shader {
private boolean enabled = false;
//Identifiant du programme resultat de la compilation des shaders
private final int ID;
private Map<String, Integer> locationCache = new HashMap<String, Integer>();
/*
Crée le fragment et le vertex shader les lie dans un programme dont il renvoie l'identifiant.
*/
public Shader(String vertex, String fragment) {
ID = ShaderUtils.load(vertex, fragment);
}
public int getUniform(String name){
if (locationCache.containsKey(name)) return locationCache.get(name);
int result = glGetUniformLocation(ID, name);
if (result == -1) System.err.println("Could not find uniform variable " + name);
else locationCache.put(name, result);
return result;
}
public void setUniform1i(String name, int value) {
if (!enabled) enable();
glUniform1i(getUniform(name), value);
}
public void setUniform1f(String name, float value) {
if (!enabled) enable();
glUniform1f(getUniform(name), value);
}
public void setUniform2f(String name, float x, float y) {
if (!enabled) enable();
glUniform2f(getUniform(name), x, y);
}
public void setUniform3f(String name, Vector3f vector) {
if (!enabled) enable();
glUniform3f(getUniform(name), vector.x, vector.y, vector.z);
}
public void setUniform4f(String name, float x, float y, float z, float w) {
if (!enabled) enable();
glUniform4f(getUniform(name), x, y, z, w);
}
public void setUniformMat4f(String name, Matrix4f matrix){
if (!enabled) enable();
glUniformMatrix4fv(getUniform(name), false, matrix.toFloatBuffer());
}
public void enable() {
glUseProgram(ID);
enabled = true;
}
public void disable() {
glUseProgram(0);
enabled = false;
}
}

View File

@ -0,0 +1,75 @@
package engine.graphics;
import engine.utils.BufferUtils;
import org.lwjgl.opengl.GL11;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL30.*;
public class Texture {
private int width, height;
private int texture;
private int index;
public Texture(String path, int index) {
this.index = index;
texture = load(path);
}
private int load(String path) {
int[] pixels = null;
try {
BufferedImage image = ImageIO.read(new FileInputStream(path));
width = image.getWidth();
height = image.getHeight();
pixels = new int[width * height];
image.getRGB(0, 0, width, height, pixels, 0, width);
} catch (IOException e) {
e.printStackTrace();
}
int[] data = new int[width * height];
for (int i = 0; i < width * height; i++) {
int a = (pixels[i] & 0xff000000) >> 24;
int r = (pixels[i] & 0xff0000) >> 16;
int g = (pixels[i] & 0xff00) >> 8;
int b = (pixels[i] & 0xff);
data[i] = a << 24 | b << 16 | g << 8 | r;
}
int result = glGenTextures();
glBindTexture(GL_TEXTURE_2D, result);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, BufferUtils.createIntBuffer(data));
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return result;
}
public void bind() {
glActiveTexture(GL_TEXTURE0 + this.index);
glBindTexture(GL_TEXTURE_2D, texture);
}
public void unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}

View File

@ -0,0 +1,89 @@
package engine.graphics;
import engine.utils.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL30.*;
public class VertexArray {
private int VAO ,VBO, EBO, CBO, TBO;
private int count;
public VertexArray(float[] vertices, byte[] indices, float[] color, float[] texture) {
count = indices.length;
// VERTEX ARRAY OBJECT
VAO = glGenVertexArrays();
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
// VERTEX BUFFER OBJECT
createVertexBufferObject(vertices);
// COLOR BUFFER OBJECT
if (color != null) createColorBufferObject(color);
// TEXTURE BUFFER OBJECT
if (texture != null) createTextureBufferObject(texture);
EBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
private void createVertexBufferObject(float[] vertices){
VBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
private void createColorBufferObject(float[] color){
CBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(color), GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);
}
private void createTextureBufferObject(float[] texture){
TBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(2);
}
public void swapVertexBufferObject(float[] vertices){
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
}
public void swapTextureBufferObject(float [] texture){
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
}
public void bind(){
glBindVertexArray(this.VAO);
}
public void unbind(){
glBindVertexArray(0);
}
public void draw(){
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0);
}
public void render(){
bind();
draw();
unbind();
}
}

View File

@ -0,0 +1,123 @@
package engine.math;
import engine.utils.BufferUtils;
import java.nio.FloatBuffer;
public class Matrix4f {
public static final int SIZE = 4 * 4;
public float[] elements = new float[4 * 4];
public Matrix4f(){
}
public static Matrix4f identity(){
Matrix4f result = new Matrix4f();
for (int i = 0; i < SIZE; i++){
result.elements[i] = 0.0f;
}
result.elements[0 + 0 * 4] = 1.0f;
result.elements[1 + 1 * 4] = 1.0f;
result.elements[2 + 2 * 4] = 1.0f;
result.elements[3 + 3 * 4] = 1.0f;
return result;
}
public static Matrix4f orthographic(float left, float right, float bottom, float top, float near, float far){
Matrix4f result = identity();
result.elements[0 + 0 * 4] = 2.0f / (right - left);
result.elements[1 + 1 * 4] = 2.0f / (top - bottom);
result.elements[2 + 2 * 4] = 2.0f / (near - far);
result.elements[0 + 3 * 4] = (left + right) / (left - right);
result.elements[1 + 3 * 4] = (bottom + top) / (bottom - top);
result.elements[2 + 3 * 4] = (far + near) / (far - near);
return result;
}
public static Matrix4f translate(Vector3f vector){
Matrix4f result= identity();
result.elements[0 + 3*4] = vector.x;
result.elements[1 + 3*4] = vector.y;
result.elements[2 + 3*4] = vector.z;
return result;
}
public static Matrix4f scale(Vector3f vector){
Matrix4f result= identity();
result.elements[0 + 0*4] = vector.x;
result.elements[1 + 1*4] = vector.y;
result.elements[2 + 2*4] = vector.z;
return result;
}
public static Matrix4f rotateX(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[1 + 1 * 4] = cos;
result.elements[2 + 1 * 4] = -sin;
result.elements[1 + 2 * 4] = sin;
result.elements[2 + 2 * 4] = cos;
return result;
}
public static Matrix4f rotateY(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[0 + 0 * 4] = cos;
result.elements[2 + 0 * 4] = sin;
result.elements[0 + 2 * 4] = -sin;
result.elements[2 + 2 * 4] = cos;
return result;
}
public static Matrix4f rotateZ(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[0 + 0 * 4] = cos;
result.elements[1 + 0 * 4] = -sin;
result.elements[0 + 1 * 4] = sin;
result.elements[1 + 1 * 4] = cos;
return result;
}
public Matrix4f multiply(Matrix4f matrix){
Matrix4f result = new Matrix4f();
for (int y = 0; y< 4; y++){
for (int x = 0; x< 4; x++){
float sum = 0.0f;
for (int e = 0; e< 4; e++){
sum += this.elements[x + e * 4] * matrix.elements[e + y * 4];
}
result.elements[x + y * 4] = sum;
}
}
return result;
}
public FloatBuffer toFloatBuffer() {
return BufferUtils.createFloatBuffer(elements);
}
}

View File

@ -0,0 +1,38 @@
package engine.math;
import engine.math.Vector3f;
public class Primitive {
public static float[] createRectangle(float z, float w, float h){
return new float[] {
0 , 0 , z, // Haut gauche
0 + w, 0 , z, // Haut droit
0 + w, 0 - h, z, // Bas droit
0 , 0 - h, z // Bas gauche
};
}
/**
* Chaque point correspond à un vertex de la primite le reste est interpolé
*/
public static float[] stdTexWrap = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
public static float[] upperHalfTexWrap = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.5f,
0.0f, 0.5f
};
public static byte[] rectangle_indices = new byte[] {
0, 1, 3,
1, 2, 3
};
}

View File

@ -0,0 +1,24 @@
package engine.math;
public class Vector3f {
public float x, y, z;
public Vector3f(){
x = 0.0f;
y = 0.0f;
z = 0.0f;
}
public Vector3f(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
public void divXY(float div){
this.x /= div;
this.y /= div;
}
}

View File

@ -0,0 +1,237 @@
package engine.object;
import engine.graphics.*;
import engine.math.*;
import static org.lwjgl.glfw.GLFW.glfwGetTime;
/**
*
*/
public class ObjectGl {
/**
* STATE CONST DECLARATION
*/
public static final int DEFAULT = 0, STICK_BOTTOM = 1, STICK_TOP = 2;
private int stick_state;
protected VertexArray vertexArray;
protected Shader shader;
protected Matrix4f transform;
/**
* Projection and view matrix are set by the engine do not modify
*/
public static Matrix4f projection;
public static Matrix4f view;
private float zPos;
private float width; // To be used in setTextureWrap
private float height;
private float scalingFactor;
public boolean useTime;
private Texture texture;
/**
* Create a rectangle shape, use setTextureWrap to correctly align the texture with the model
* @param z depth of your model the larger it is the more it will be "close" to the camera
* @param w height of the rectangle
* @param h width of the rectangle
* @param size scaling factor of the rectangle, the model could not show up because this value is too small or too large, a good compromise is between 2 and 15
* @param tex set to null if you don't want a tex on your model
* @param color set to null if you don't want a Color on your model
*/
public ObjectGl(float z, float w, float h, float size, String tex, Vector3f color){
float[] colorBuffer = null;
// Check des options
if (color != null){
colorBuffer = new float[] {
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z
};
}
if (tex != null){
this.texture = new Texture(tex, 0);
}
this.zPos = z;
this.height = h;
this.width = w;
this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
this.scalingFactor = size;
this.transform = Matrix4f.identity();
this.scale(new Vector3f(size, size,1f));
this.stick_state = DEFAULT;
this.useTime = false;
// use different shader for each set of option
if (tex == null && color == null){
this.shader = new Shader("shaders/ObjectGl/vert.glsl","shaders/ObjectGl/frag.glsl");
} else if (tex == null){
this.shader = new Shader("shaders/ObjectGlColor/vert.glsl","shaders/ObjectGlColor/frag.glsl");
} else if (color == null){
this.shader = new Shader("shaders/ObjectGlTex/vert.glsl","shaders/ObjectGlTex/frag.glsl");
} else {
this.shader = new Shader("shaders/ObjectGlTexColor/vert.glsl","shaders/ObjectGlTexColor/frag.glsl");
}
}
/**
* Reset the transform matrix, the model will appear at the 0.0.0 coordinate, his scaleFactor will be set to zero
* Because the model is at position 0 on the z axis he will not show up on screen
*/
public void resetTransform(){
this.transform = Matrix4f.identity();
this.scalingFactor = 1;
}
/**
* Move the object according to vec, direction can change if rotation method have been used
* @param vec Vector3f
*/
public void translate(Vector3f vec){
vec.divXY(this.scalingFactor);
this.transform = this.transform.multiply(Matrix4f.translate(vec));
this.zPos += vec.z;
}
/**
* Scale the model with the vec vector, the x component is used to mitigate size modification in the behavior of other transformation method
* @param vec Vector3f
*/
public void scale(Vector3f vec){
this.scalingFactor *= vec.x;
this.transform = this.transform.multiply(Matrix4f.scale(vec));
}
/**
* rotate the model by angle degree on the local x axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateX(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateX(angle));
}
/**
* rotate the model by angle degree on the local y axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateY(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateY(angle));
}
/**
* rotate the model by angle degree on the local z axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateZ(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateZ(angle));
}
/**
* Set a new texture to be used on the model. You may need to use setTextureWrap tp get the correct wrap
* @param texPath path to the new texture
*/
public void setTexture(String texPath){
this.texture = new Texture(texPath, 0);
}
/**
* Change the wrapping coordinate
* @param x starting wrapping on the horizontal axis
* @param y starting wrapping on the vertical axis
* @param w the length of the wrapping on the horizontal axis
* @param h the length of the wrapping on the vertical axis
*/
public void setTextureWrap(float x, float y, float w, float h, int sticky){
// TODO set sticky property + precision issue
if (this.stick_state != sticky){ // Check if we're using a new dimension
if (sticky == STICK_BOTTOM){
this.stick_state = STICK_BOTTOM;
this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
} else if (sticky == STICK_TOP){
this.stick_state = STICK_TOP;
this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
} else {
this.stick_state = DEFAULT;
}
}
this.height = h;
this.width = w;
this.vertexArray.swapVertexBufferObject(Primitive.createRectangle(this.zPos, w, h));
int texWidth = this.texture.getWidth();
int texHeight = this.texture.getHeight();
x /= texWidth;
w /= texWidth;
y /= texHeight;
h /= texHeight;
float[] result = {
x , y ,
x + w , y ,
x + w , y + h ,
x , y + h ,
};
this.setTextureWrap(result);
}
/**
* Set a new shader to be used by this object
* @param vert path to glsl Vertex Shader
* @param frag path to glsl Fragment Shader
*/
public void setShader(String vert, String frag){
this.shader = new Shader(vert, frag);
}
/**
* Set a new Color for the object if the shader do not use the color attrib this will make no change.
* @param color Vector3f r,g,b format
*/
public void setColor(Vector3f color){
float[] colorBuffer = new float[] {
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z
};
this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
}
private void setTextureWrap(float[] texture){
this.vertexArray.swapTextureBufferObject(texture);
}
public float getZPos(){
return zPos;
}
/**
* Do shader binding, texture binding and vertexArray drawing
*/
public void render(){
this.shader.enable();
if (this.texture != null) this.texture.bind();
if (this.useTime) this.shader.setUniform1f("time", (float) glfwGetTime());
this.shader.setUniformMat4f("projection", projection);
this.shader.setUniformMat4f("view", view);
this.shader.setUniformMat4f("transform", this.transform);
this.vertexArray.render();
if (this.texture != null) this.texture.unbind();
this.shader.disable();
}
}

View File

@ -0,0 +1,11 @@
package engine.object;
import java.util.Comparator;
public class SortZ implements Comparator<ObjectGl>
{
public int compare(ObjectGl a, ObjectGl b)
{
return (int) (a.getZPos() - b.getZPos());
}
}

View File

@ -0,0 +1,32 @@
package engine.utils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class BufferUtils {
private BufferUtils() {
}
public static ByteBuffer createByteBuffer(byte[] array){
ByteBuffer result = ByteBuffer.allocateDirect(array.length).order(ByteOrder.nativeOrder());
result.put(array).flip();
return result;
}
public static FloatBuffer createFloatBuffer(float[] array){
FloatBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
result.put(array).flip();
return result;
}
public static IntBuffer createIntBuffer(int[] array){
IntBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
result.put(array).flip();
return result;
}
}

View File

@ -0,0 +1,29 @@
package engine.utils;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileUtils {
private FileUtils() {
}
public static String loadAsString(String file){
StringBuilder result = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String buffer = "";
while ((buffer = reader.readLine()) != null) {
result.append(buffer +"\n");
}
reader.close();
} catch (IOException e){
e.printStackTrace();
}
return result.toString();
}
}

View File

@ -0,0 +1,60 @@
package engine.utils;
import engine.utils.FileUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
public class ShaderUtils {
private ShaderUtils(){
}
public static int load(String vertPath, String fragPath){
String vert = FileUtils.loadAsString(vertPath);
String frag = FileUtils.loadAsString(fragPath);
return create(vert, frag);
}
public static int create(String vert, String frag){
// On crée et compile le vertex et le fragment shader
int vertID = glCreateShader(GL_VERTEX_SHADER);
int fragID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertID, vert);
glShaderSource(fragID, frag);
glCompileShader(vertID);
if (glGetShaderi(vertID, GL_COMPILE_STATUS) == GL_FALSE){
System.err.println("Failed to compile vertex shader");
System.err.println(glGetShaderInfoLog(vertID));
return -1;
}
glCompileShader(fragID);
if (glGetShaderi(fragID, GL_COMPILE_STATUS) == GL_FALSE){
System.err.println("Failed to compile fragment shader");
System.err.println(glGetShaderInfoLog(fragID));
return -1;
}
//on lie les shaders au programme
int program = glCreateProgram();
glAttachShader(program, vertID);
glAttachShader(program, fragID);
glLinkProgram(program);
if(glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) {
System.err.println("Failed to link vertex and fragment shader");
System.err.println(glGetShaderInfoLog(program));
return -1;
}
glValidateProgram(program);
glDeleteShader(vertID);
glDeleteShader(fragID);
return program;
}
}

View File

@ -9,12 +9,26 @@
package launcher;
public class Launcher {
import java.io.FileInputStream;
public void launch() throws Exception {
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.fxml.*;
public class Launcher extends Application {
public void start(Stage primaryStage) throws Exception {
FileInputStream r_launcher = new FileInputStream("ui/launcher.fxml");
FXMLLoader floader = new FXMLLoader();
Parent root = floader.load(r_launcher);
Scene main = root.getScene();
System.out.println("Hello world!");
primaryStage.setTitle("Boulevard Combattant");
primaryStage.setScene(main);
primaryStage.show();
}
}

BIN
textures/awesomeface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
textures/container.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

BIN
textures/zangief_sprite.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

91
ui/launcher.fxml Normal file
View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015, 2019, Gluon and/or its affiliates.
All rights reserved. Use is subject to license terms.
This file is available and licensed under the following license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
- Neither the name of Oracle Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<?import javafx.geometry.Rectangle2D?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: #151619;" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
<children>
<VBox prefHeight="400.0" prefWidth="157.0">
<children>
<ImageView accessibleText="Logo" fitHeight="240.0" fitWidth="158.0" pickOnBounds="true" preserveRatio="true">
<image>
</image>
</ImageView>
<VBox alignment="BOTTOM_CENTER" prefHeight="263.0" prefWidth="158.0">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Button mnemonicParsing="false" text="Run" />
</children>
</VBox>
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="176.0" text="Settings" />
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="161.0" style="-fx-background-color: #e80000;" text="X Quit" textFill="WHITE" />
</children>
</VBox>
</children>
</VBox>
<VBox prefHeight="400.0" prefWidth="455.0">
<children>
<HBox alignment="CENTER" prefHeight="266.0" prefWidth="475.0">
<children>
<VBox alignment="BOTTOM_CENTER" prefHeight="249.0" prefWidth="233.0">
<children>
<ImageView fitHeight="172.0" fitWidth="211.0" pickOnBounds="true" preserveRatio="true">
<image>
</image>
<viewport>
<Rectangle2D />
</viewport>
</ImageView>
</children>
</VBox>
<VBox alignment="BOTTOM_CENTER" prefHeight="249.0" prefWidth="233.0">
<children>
<ImageView fitHeight="200.0" fitWidth="233.0" pickOnBounds="true" preserveRatio="true">
<image>
</image>
</ImageView>
</children>
</VBox>
</children>
</HBox>
<HBox prefHeight="168.0" prefWidth="432.0" />
</children></VBox>
</children>
</HBox>