Compare commits
104 Commits
menu-javaf
...
master
Author | SHA1 | Date | |
---|---|---|---|
512fcc069d | |||
7a5a4a093e | |||
6d53865281 | |||
58810fff0c | |||
a98c3cd3e1 | |||
939f8566cd | |||
03beebaeaf | |||
c7fe7853b4 | |||
35c7ecf471 | |||
229782c772 | |||
2d27786e48 | |||
3bcfdfc084 | |||
878caf1c99 | |||
0bb327abb2 | |||
621be3af64 | |||
9671f8ec53 | |||
2d4462735a | |||
7467abfd11 | |||
59fd891fd9 | |||
e6853ab3d3 | |||
ff5ed0c85f | |||
0330303129 | |||
0354679969 | |||
714e904d1c | |||
d52d1cab77 | |||
9bc66ad6b1 | |||
41be423f94 | |||
774c594cb8 | |||
fed275ba09 | |||
8c8dacadd0 | |||
a726019b18 | |||
391d94afbe | |||
7bd43062d0 | |||
4c185f0a81 | |||
ac6c8611e7 | |||
ff167b4d0f | |||
34ea408202 | |||
c9fdb4a7db | |||
3d4730cfc0 | |||
518a37ba8c | |||
aecbf2cb9a | |||
178d076883 | |||
16d2c89e95 | |||
3dd1b6b059 | |||
3e4b4d257e | |||
d389b22f2d | |||
9fabc8128b | |||
def25d9e38 | |||
e424cdca4e | |||
201eb3ec10 | |||
cb54e753d7 | |||
0f1ecc753b | |||
334e0ad99b | |||
a35d823ec4 | |||
4f821b44bc | |||
9aa09f8fbd | |||
90d6d47cc8 | |||
8ec5a622d8 | |||
e7c7065a8d | |||
a472df26ed | |||
|
24730a1362 | ||
af3489d078 | |||
7320fea2f9 | |||
60bf1fa5d0 | |||
7c37c46830 | |||
6280b39c20 | |||
592780bb73 | |||
e3d28b21b4 | |||
7b6291bda9 | |||
382af6b541 | |||
15e1745ad1 | |||
4583bbd7e6 | |||
c68e680768 | |||
a043cb487f | |||
1af5db700e | |||
752c722b0c | |||
a3ad448fba | |||
a7a3e8b36e | |||
8110a93910 | |||
|
53972cd1ef | ||
|
de146b216d | ||
f1519ba40c | |||
72dcbcbf4f | |||
a43e3b150a | |||
7ac860850c | |||
a076ca12cb | |||
dc5da4956a | |||
c6df656381 | |||
692e22b5b9 | |||
f21c036b1c | |||
b4b89bcd86 | |||
644af67a55 | |||
ee0350c251 | |||
d455b7f450 | |||
02b4ab8a35 | |||
24a7a73f36 | |||
ce99e1faf9 | |||
075bdd9338 | |||
25a6782f3c | |||
|
0baef08205 | ||
|
f71675dd21 | ||
9711be3665 | |||
8749c23333 | |||
ac368a6d19 |
@ -44,6 +44,6 @@ depends_on:
|
|||||||
- Check_Requirement
|
- Check_Requirement
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: 9ca9095fdb69d7b89fda6b4db867877e76666c109607cc7b1e513814ad42bb7e
|
hmac: 6b154c74ec624ce2d5867386bb7a6ee51cae9153457a8ce15f53e54546ccbc0e
|
||||||
|
|
||||||
...
|
...
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -53,3 +53,4 @@ build
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
.settings/
|
.settings/
|
||||||
|
*.slevel
|
||||||
|
2
JournalDeBord/rapport/.gitignore
vendored
Normal file
2
JournalDeBord/rapport/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rapport.aux
|
||||||
|
rapport.toc
|
BIN
JournalDeBord/rapport/rapport.pdf
Normal file
BIN
JournalDeBord/rapport/rapport.pdf
Normal file
Binary file not shown.
274
JournalDeBord/rapport/rapport.tex
Normal file
274
JournalDeBord/rapport/rapport.tex
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
\documentclass[12pt,a4paper]{article}
|
||||||
|
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{listings}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{csquotes}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\title{Rapport du projet informatique 2023 \\ "Road to Master"}
|
||||||
|
\author{Debucquoy Anthony \and Matteo Di Leto}
|
||||||
|
\date{May 2023}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
|
||||||
|
\section*{Introduction}
|
||||||
|
|
||||||
|
Lors de ce deuxième quadrimestre, le projet Informatique proposé par notre université fut partie intégrante de notre emploi du temps.
|
||||||
|
Régulièrement, nous nous sommes rassemblés pour nous organiser et trouver une direction dans laquelle nous voulions voir notre projet évoluer.
|
||||||
|
Grâce aux objectifs fixés par nos enseignants, nous sommes - nous le pensons - maintenant plus aptes à nous confronter à ce genre d'objectifs, tant au niveau personnel qu'en tant que groupe.
|
||||||
|
Il va sans dire que comme pour tout projet, notre chemin a été semé d'embûches. En l'occurrence, nous souhaitons faire part de l'abandon d'un de nos membre. Eddy Jiofak qui souhaite se réorienter.
|
||||||
|
Nous lui souhaitons une bonne reconversion.
|
||||||
|
|
||||||
|
\section*{Objectifs}
|
||||||
|
|
||||||
|
Voici l'objectif fixé par nos enseignants. (document de consignes)
|
||||||
|
|
||||||
|
\begin{displayquote}
|
||||||
|
|
||||||
|
Le but final de ce projet est de réaliser une application graphique en Java permettant de
|
||||||
|
jouer au jeu "Cats Organized Neatly". Ce jeu est un jeu de type "puzzle" où le joueur doit
|
||||||
|
placer des pièces de formes différentes pour combler l'aire de jeu. L'application devra permettre
|
||||||
|
de sauvegarder et charger une partie et de créer des niveaux automatiquement.
|
||||||
|
|
||||||
|
\end{displayquote}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section{Organisation}
|
||||||
|
|
||||||
|
Lors de nos rassemblement pour le projet, toutes les idées émises se sont retrouvés sur un blog afin de pouvoir y accéder de manière efficace.
|
||||||
|
Ce blog nous sert également à garder une trace de l'évolution du projet.
|
||||||
|
|
||||||
|
\subsection{Choix}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item{le VCS \verb|git| pour garder une trace de l'avancement du projet. Avec comme remote une instance privée de gitea nous permettant de vérifier les MR/PR plus efficacement.}
|
||||||
|
\item{Une instance de DroneCI permettant de vérifier que le projet soit toujours compilable et que les tests ne soient pas ratés sans que nous nous en rendions compte.}
|
||||||
|
\item{Javafx, comme recommandé par nos enseignants.}
|
||||||
|
\item{Les pièces et niveaux sont stockées sous forme de matrice de booléen}
|
||||||
|
\item{Un parser de fichiers efficace et donnant des fichier légers.}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsubsection*{Shapes}
|
||||||
|
|
||||||
|
Les pièces ainsi que la carte sont représentés par une matrice de booléen \verb|boolean[][]|.
|
||||||
|
Nous avons donc une classe \verb|shape|, parent de \verb|Map| et de \verb|Piece| dans lequel nous stockons notre matrice.
|
||||||
|
Ensuite, \verb|Map| Contient une liste de \verb|Piece|. Ces pièces contiennent une position représentée par la classe \verb|Vec2|.
|
||||||
|
Cette position est la position du carré supérieur gauche dans la \verb|Map|.
|
||||||
|
Avec toutes ces informations nous avons le nécessaire pour le moteur du jeu.
|
||||||
|
|
||||||
|
Il est facilement possible de manipuler la carte et les pièces. Il nous suffit alors de faire correspondre l'affichage avec
|
||||||
|
ces différentes classes. Ce qui est entrepris par la classe \verb|GameUI|.
|
||||||
|
|
||||||
|
Le tout est géré par la classe \verb|Controller| qui permet de choisir entre l'affichage d'un menu ou d'une partie en cours.
|
||||||
|
|
||||||
|
% \subsection{Difficultés}
|
||||||
|
|
||||||
|
\section{Points Forts}
|
||||||
|
|
||||||
|
\subsection{Parser de fichiers}
|
||||||
|
|
||||||
|
Pour la rétention des niveaux, plusieurs possibilités s'offraient à nous. Nous avons alors décidé d'accomplir une série d'objectifs propres à notre projet avec un parser de fichiers dédié.
|
||||||
|
Nous voulions que ce parser accomplisse les objectifs suivants:
|
||||||
|
\begin{itemize}
|
||||||
|
\item{Les données du niveau seront encapsulées dans un header/footer pour laisser la possibilité d'enregistrer plus d'informations (images/musiques) dans un seul fichier dans le futur.}
|
||||||
|
\item{La taille du fichier devra être aussi petite que possible, tout en gardant les informations nécessaires au bon fonctionnement du jeu.}
|
||||||
|
\item{Il sera possible d'enregistrer l'état d'une partie en cours.}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Ce parser est implémenté par la classe \verb|BinaryParser|.
|
||||||
|
|
||||||
|
\subsubsection*{spécification}
|
||||||
|
|
||||||
|
\begin{description}
|
||||||
|
\item[Header/Footer]{ Les données du niveau commencent par les 3 \emph{caractères} 'S', 'M', 'S' (ou \verb|0x534D53|) et se terminent par les 3 \emph{caractères} 'S', 'M', 'E' (ou \verb|0x534D45|)}
|
||||||
|
\item[Taille de carte]{ Le premier octet des données représente la largeur de la carte, le second sa hauteur.}
|
||||||
|
\item[Forme de la carte]{ Chaque cellule de la carte est représenté par un 1 ou un 0. Le 1 représente un emplacement libre, un 0 une cellule vide.
|
||||||
|
La forme de la carte peut alors être répartie sur un nombre indéterminé d'octets.
|
||||||
|
Nous pouvons déterminer ce nombre grace à
|
||||||
|
$$\frac{\text{largeur} * \text{hauteur } (+1 \text{ si multiple de } 8)}{8}$$
|
||||||
|
en division entière.}
|
||||||
|
\item[Nombre de pièce]{ L' (les) octet(s) qui forme(nt) la carte représente le nombre de pièce}
|
||||||
|
\item[Pour chaque pièces]{
|
||||||
|
\
|
||||||
|
\begin{description}
|
||||||
|
\item[Taille de la pièce]{La taille est représentée sur un seul octet sous forme de nibble\footnote{https://en.wikipedia.org/wiki/Nibble}. La première partie du nibble est la largeur. La seconde partie du nibble est la hauteur }
|
||||||
|
\item[Forme de la pièce]{ Chaque cellules de la pièce est représentée par un 1 ou un 0. La manière de le représenter et exactement la même que pour la forme de la carte }
|
||||||
|
\end{description}
|
||||||
|
Dans le cas où le fichier sauvegarde l'état de la partie, à la fin, et pour chaque pièce dans le même ordre que l'apparition des pièces:
|
||||||
|
\begin{description}
|
||||||
|
\item[Position de la pièce]{2 octets par pièces, 1 octet pour sa position en x et 1 octet pour sa position en y.
|
||||||
|
Dans le cas où la pièce est flottante (n'est pas placée dans la carte.), les octets contenant les caractères F puis L (0x464C) remplacent les coordonnées}
|
||||||
|
\end{description}
|
||||||
|
}
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
\subsubsection*{Exemple}
|
||||||
|
|
||||||
|
Voici le 'hexdump' du niveau 11
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
53 4d 53 05 05 e7 ff ff 80 06 33 ff 80 22 f0 22 |SMS.......3.."."|
|
||||||
|
b0 22 70 22 b0 11 80 53 4d 45 |."p"...SME|
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
Représente une carte de la forme :
|
||||||
|
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\filldraw[blue] (0,0) -- (0,5) -- (3,5) -- (3,4) -- (5,4) -- (5,0) -- cycle;
|
||||||
|
\draw[step=1cm,gray] (0, 0) grid (5,5);
|
||||||
|
\end{tikzpicture}
|
||||||
|
|
||||||
|
Avec les pièces :
|
||||||
|
|
||||||
|
\begin{tikzpicture}
|
||||||
|
\fill[red] (1,1) rectangle (4,4);
|
||||||
|
\fill[red] (5,1) rectangle (7,3);
|
||||||
|
\fill[red] (8,1) -- (8,3) -- (9,3) -- (9,2) -- (10,2) -- (10,1) -- cycle;
|
||||||
|
\fill[red] (11,1) -- (11,2) -- (12,2) -- (12,3) -- (13,3) -- (13,1) -- cycle;
|
||||||
|
\fill[red] (1,-2) -- (1,0) -- (2,0) -- (2,-1) -- (3,-1) -- (3,-2) -- cycle;
|
||||||
|
\fill[red] (4, -2) rectangle (5, -1);
|
||||||
|
\draw[step=1cm,gray] (0.5, -2.5) grid (13.5, 4.5);
|
||||||
|
\end{tikzpicture}
|
||||||
|
|
||||||
|
En plus de ce parser, et dans le cas où ce premier ne serait pas capable de stocker certaine carte (par exemple si une pièce mesure plus de 15x15),
|
||||||
|
nous avons également implémenté un parser très simple en utilisant l'interface \verb|Serialize| de java. Ce parser est implémenté et fonctionnel,
|
||||||
|
mais n'est pas utilisé dans le projet à l'heure actuelle.
|
||||||
|
|
||||||
|
Ces deux parseurs implémentent l'interface \verb|FileParser|.
|
||||||
|
|
||||||
|
Finalement, La classe \verb|FileParserFactory| permet une utilisation simple de ces parseurs. Celle-ci contient deux fonctions statiques.
|
||||||
|
\begin{itemize}
|
||||||
|
\item{\verb|Map loadMapFromFile(File)|}
|
||||||
|
permet de retourner la Map d'un fichier chargé.
|
||||||
|
\item{\verb|void saveFileFromMap(File, Map)|}
|
||||||
|
permet de sauvegarder une map dans un fichier.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Dans le cas d'une sauvegarde ou d'un chargement, le parser est choisi en fonction de l'extension de fichier ('.level', '.slevel', .'serialized', '.sserialized').
|
||||||
|
|
||||||
|
L'avantage de ce système est que nous pouvons facilement ajouter d'autres parser de fichiers dans le futur.
|
||||||
|
|
||||||
|
\subsection{Générateur de niveaux}
|
||||||
|
|
||||||
|
Le générateur de niveaux a été conçu de sorte à proposer 3 difficultés différentes:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item{Niveau Facile}
|
||||||
|
\item{Niveau Moyen}
|
||||||
|
\item{Niveau Difficile}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
L'algorithme derrière est le même. En voici le principe :
|
||||||
|
|
||||||
|
\subsubsection*{Gestion du plateau}
|
||||||
|
|
||||||
|
Le joueur choisit une difficulté. En fonction de la difficulté choisie, la grandeur du plateau de jeu sera différente.
|
||||||
|
Si la difficulté choisie est facile ou moyenne, alors un curseur parcourt les extrémités du niveau.
|
||||||
|
Ce curseur sélectionne aléatoirement les cellules qui seront gardées ou non.
|
||||||
|
Grâce à ça, la forme du plateau n'est pas trop carrée.
|
||||||
|
|
||||||
|
Nous nous sommes basés sur le même principe pour le niveau de difficulté difficile mais en plus d'une taille encore plus grande,
|
||||||
|
le curseur parcourt les extrémités avec une profondeur de 2 afin de faire varier la carte plus grande.
|
||||||
|
Cela introduit le problème des cases isoléss. C'est pourquoi une boucle vérifie chaque cellule et la supprime si celle-ci est isolée.
|
||||||
|
|
||||||
|
\subsubsection*{Gestion des pièces}
|
||||||
|
|
||||||
|
Peu importe la difficulté du niveau, voici le fonctionnement :
|
||||||
|
|
||||||
|
Une taille maximum des pièces a été fixée au préalable à 3x3.
|
||||||
|
Par la suite, un curseur parcourt des cases de la carte préalablement conçue de manière aléatoire.
|
||||||
|
Pour chaque case, l'algorithme teste pour chaque case de la pièce, si l'espace est disponible.
|
||||||
|
Si ça n'est pas le cas, alors la pièce est modifiée afin de faire correspondre la pièce et la carte.
|
||||||
|
|
||||||
|
L'avantage de cette méthode est que les niveaux sont tous très différents.
|
||||||
|
Les désavantages sont que, par malchance, il est possible d'avoir énormément de piece 1x1.
|
||||||
|
il est aussi plus difficile d'appliquer des textures et dessins - à l'image du jeu de base - sur les pièces.
|
||||||
|
|
||||||
|
Malgré tout, avec nos nombreux tests, ce générateur de niveaux nous satisfait vraiment bien et la difficulté des niveaux correspond bien aux attentes.
|
||||||
|
|
||||||
|
\subsection{Interface graphique}
|
||||||
|
L'interface graphique du jeu tient sur 5 classes différentes.
|
||||||
|
|
||||||
|
\subsubsection*{Controller}
|
||||||
|
Classe principale. Elle s'occupe de la gestion des autres classes et de la cohérence entre elles.
|
||||||
|
Toutes les autres classes (présentes dans le package \verb|Scenes|) sont des sous classe de Parents.
|
||||||
|
Cela permet de les afficher grâce à la méthode statique \verb|switchRoot|.
|
||||||
|
C'est aussi le point d'entrée du programme.
|
||||||
|
|
||||||
|
\subsubsection*{MenuAccueil}
|
||||||
|
Classe s'occupant de générer la page d'accueil du jeu.
|
||||||
|
C'est-à-dire la première page que verra l'utilisateur.
|
||||||
|
Cette page permet d'accéder aux niveaux du jeu de base, mais également de générer les niveaux aléatoires.
|
||||||
|
De plus un dernier bouton "Load Game" permet de revenir sur la dernière partie en cours du joueur.
|
||||||
|
|
||||||
|
\subsubsection*{MenuLevel}
|
||||||
|
Classe s'occupant d'afficher les niveaux proposés dans le jeu, et qui,
|
||||||
|
en fonction du jour choisi, change les boutons et les niveaux disponibles.
|
||||||
|
|
||||||
|
\subsubsection*{ScreenLevelFinish}
|
||||||
|
Classe qui s'affiche à l'écran dès que le joueur a fini le niveau.
|
||||||
|
Celle-ci propose également de réessayer le niveau ou de retourner au menu principal.
|
||||||
|
|
||||||
|
\subsubsection*{GameUI}
|
||||||
|
Classe s'occupant de l'affichage d'un niveau.
|
||||||
|
S'occupe dans un premier temps d'afficher le plateau au milieu de l'écran.
|
||||||
|
Par la suite, les pièces sont dispersées à la gauche de l'écran et sont rendues disponibles à l'utilisateur.
|
||||||
|
Ces pièces sont déplaçables à l'aide de la souris.
|
||||||
|
Si elles sont lâchées sur un emplacement disponible du plateau, alors elles vont s'aligner avec ses cellules.
|
||||||
|
Pour se faire, nous regardons si le centre d'une cellule (la plus en haut à gauche) est présente dans une cellule du plateau.
|
||||||
|
Ensuite, on vérifie que toutes les cellules de la pièce ont bien la place dans le plateau pour se poser. Si c'est le cas, alors la pièce est posée.
|
||||||
|
|
||||||
|
\section{Points Faibles}
|
||||||
|
|
||||||
|
Bien que l'interface graphique permet de naviguer de manière fluide dans le jeu, il y a clairement un manque d'animation et de dynamisme
|
||||||
|
\emph{i.e}: transition de page à une autre, apparition des boutons ainsi qu'un manque de musique.
|
||||||
|
Toujours concernant l'affichage l'adaptation à la taille de l'écran peut être revue.
|
||||||
|
|
||||||
|
De plus suite à la perte de notre membre nous n'avons pas su gérer la partie du projet qui concerne le design/textures des pièces ainsi que l'histoire jeu préparée auparavant.
|
||||||
|
|
||||||
|
\section{Apports Positifs et négatifs}
|
||||||
|
|
||||||
|
\subsection{Anthony}
|
||||||
|
|
||||||
|
Personnellement, ce projet m'a permis de me plonger dans la conception d'un format de fichier personnalisé.
|
||||||
|
C’est un exercice que je n’avais pas encore fait jusqu’a maintenant. Malgré mes efforts pour prévoir un maximum de choses à l’avance afin d’éviter de devoir modifier ma spécification pendant le développement, je me suis vite rendu compte que je n’avais pas pensé à tout et que je devrais changer des étapes pour pouvoir arriver à mes fins. Je pense que ce parser de fichier est vraiment améliorable mais je suis relativement fier du résultat.
|
||||||
|
|
||||||
|
J'ai pu présenter ce parser à Dr Quoitin qui a pu me conseiller sur différentes approches à ce problème.
|
||||||
|
J'en prends bonne note.
|
||||||
|
|
||||||
|
\subsection{Matteo}
|
||||||
|
|
||||||
|
Il est clair que je peux tirer plusieurs enseignements grâce à la réalisation de notre projet.
|
||||||
|
Tout d'abord, j'ai pu en apprendre beaucoup plus concernant la P.O.O en java, mais aussi j'en ai appris
|
||||||
|
d'avantage sur l'utilisation de la bibliothèque JavaFx.
|
||||||
|
|
||||||
|
De plus, durant la réalisation du projet, comme dit précédemment, nous avons utilisé plusieurs outils dont la plus grande découverte pour moi est
|
||||||
|
Git qui révèle son intérêt pour les travaux de groupes et qui, selon moi, se révélera tout aussi essentiel pour mes futurs projets
|
||||||
|
scolaires ainsi que professionnels.
|
||||||
|
|
||||||
|
\section{conclusion}
|
||||||
|
|
||||||
|
En conclusion, nous pouvons séparer notre travail en trois parties différentes:
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Le parser de fichier (gestion sauvegarder/charger partie)
|
||||||
|
\item Logique du jeu (Map,Vec2,Shapes)
|
||||||
|
\item Liaison à l'UI (Javafx)
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
Malgré notre travail concentré sur le bon fonctionnement du jeu avec un parser suivant nos objectifs, une utilisation de la P.O.O de manière très efficace
|
||||||
|
ainsi qu'une approche correcte de l'utilisation du framework Javafx, d'autres améliorations sont toujours possibles!
|
||||||
|
En effet, l'idée d'ajouter une histoire, des trophées, un Easter egg, des pièces spéciales ou un encore une table de score basée sur le temps,
|
||||||
|
reste possible afin de rendre notre jeu encore plus complet.
|
||||||
|
|
||||||
|
En conclusion, notre jeu a encore plein de possibilité afin d'être encore plus complet et amusant!
|
||||||
|
|
||||||
|
\end{document}
|
@ -6,6 +6,10 @@
|
|||||||
- [Deuxième entrevue](./rapports/200223.md)
|
- [Deuxième entrevue](./rapports/200223.md)
|
||||||
- [Troisième entrevue](./rapports/230323.md)
|
- [Troisième entrevue](./rapports/230323.md)
|
||||||
|
|
||||||
|
# Specification
|
||||||
|
|
||||||
|
- [File Parser](./spec/FileParser.md)
|
||||||
|
|
||||||
# Histoire
|
# Histoire
|
||||||
|
|
||||||
- [Plot Story](./histoire/plot_story.md)
|
- [Plot Story](./histoire/plot_story.md)
|
50
JournalDeBord/src/spec/FileParser.md
Normal file
50
JournalDeBord/src/spec/FileParser.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!-- --- -->
|
||||||
|
<!-- title: File Parser -->
|
||||||
|
<!-- author: Debucquoy Anthony (tonitch) -->
|
||||||
|
<!-- date: 5 March 2023 -->
|
||||||
|
<!-- --- -->
|
||||||
|
# File Parser Specification
|
||||||
|
|
||||||
|
For the Project, I wanted to challenge myself, I decided to do my own file parser with my own specification that would
|
||||||
|
have the special objective of being really small.
|
||||||
|
|
||||||
|
## The File format
|
||||||
|
|
||||||
|
The file would use the .level file extension.
|
||||||
|
|
||||||
|
The file can contain anything, the used data is enclosed between a header and a footer.
|
||||||
|
This could be used to add: musics, images and other stuff in the level file itself
|
||||||
|
|
||||||
|
Only one Header and One Footer should be present in the file.
|
||||||
|
The parser will only read the first one it finds so to avoid problem, it is best practise to put the
|
||||||
|
level data at the top of the file.
|
||||||
|
|
||||||
|
- The HEADER will be defined by the succesion of the characters 'S', 'M' then 'S'
|
||||||
|
- The FOOTER will be defined by the succesion of the characters 'S', 'M', then 'E'
|
||||||
|
- The bytes in between are the level data
|
||||||
|
- byte 1: Width of the map
|
||||||
|
- byte 2: Height of the map
|
||||||
|
- bytes 3 -> Width * Height (+1 if Width * Height % 8 is not 0)
|
||||||
|
- byte after Map Data: Pieces amount
|
||||||
|
- for each pieces
|
||||||
|
- 1 byte: size of the piece
|
||||||
|
- 4 first bits : width
|
||||||
|
- 4 last bits: height
|
||||||
|
- next bytes -> Width * Height (+1 if Width * Height % 8 is not 0)
|
||||||
|
|
||||||
|
### Saved file
|
||||||
|
|
||||||
|
For saved file, the extension will be .slevel
|
||||||
|
The only difference is that at the end of the map data (after the pieces and before the
|
||||||
|
Footer. there will be the position of each pieces from their top-left corner in the map.
|
||||||
|
following this pattern for each pieces
|
||||||
|
|
||||||
|
- 'F' and 'L' on 2 bytes for floating positions when the piece is not placed
|
||||||
|
- x and y on 2 bytes for position if the piece is placed
|
||||||
|
|
||||||
|
## Known Limitation
|
||||||
|
|
||||||
|
1) by putting the piece size on one byte. We limit the maximum piece size to 15 x 15 (1111 | 1111)
|
||||||
|
I don't think we will ever need a piece larger than 5x5 so this is clearly a feature, not a bug! :-)
|
||||||
|
We might use the same methods for the pieces positions but there could be a posibility to have
|
||||||
|
larger map if I use 2 bytes for the positions.
|
@ -19,7 +19,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Use JUnit Jupiter for testing.
|
// Use JUnit Jupiter for testing.
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.2'
|
||||||
|
|
||||||
// This dependency is used by the application.
|
// This dependency is used by the application.
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
implementation 'com.google.guava:guava:31.1-jre'
|
||||||
@ -27,7 +29,7 @@ dependencies {
|
|||||||
|
|
||||||
application {
|
application {
|
||||||
// Define the main class for the application.
|
// Define the main class for the application.
|
||||||
mainClass = 'school_project.Controller'
|
mainClass = project.hasProperty("mainClass") ? project.getProperty("mainClass") : 'school_project.Controller'
|
||||||
}
|
}
|
||||||
|
|
||||||
javafx {
|
javafx {
|
||||||
@ -39,3 +41,7 @@ tasks.named('test') {
|
|||||||
// Use JUnit Platform for unit tests.
|
// Use JUnit Platform for unit tests.
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run{
|
||||||
|
standardInput = System.in
|
||||||
|
}
|
||||||
|
@ -1,32 +1,77 @@
|
|||||||
/*
|
|
||||||
* This Java source file was generated by the Gradle 'init' task.
|
|
||||||
*/
|
|
||||||
package school_project;
|
package school_project;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Button;
|
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
|
import javafx.stage.Screen;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import school_project.Scenes.GameUI;
|
||||||
|
import school_project.Scenes.MenuAccueil;
|
||||||
|
import school_project.Parsers.FileParserFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
public class Controller extends Application {
|
public class Controller extends Application {
|
||||||
|
private static Stage stage;
|
||||||
|
Parent root;
|
||||||
|
public static Vec2 screen_size;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception {
|
public void start(Stage primaryStage) throws IOException {
|
||||||
primaryStage.setTitle("test");
|
new File("save.slevel");
|
||||||
Button btn = new Button("test");
|
stage = primaryStage;
|
||||||
btn.setOnAction(event -> System.out.println("hey"));
|
screen_size = new Vec2(
|
||||||
|
(int) Screen.getPrimary().getBounds().getWidth(),
|
||||||
|
(int) Screen.getPrimary().getBounds().getHeight()
|
||||||
|
);
|
||||||
|
|
||||||
Group root = new Group();
|
stage.setTitle("ROAD TO MASTER YOU");
|
||||||
root.getChildren().add(btn);
|
|
||||||
|
|
||||||
Scene scene = new Scene(root, 300,300);
|
// Full Screen mode
|
||||||
primaryStage.setScene(scene);
|
|
||||||
|
|
||||||
primaryStage.show();
|
root = new MenuAccueil();
|
||||||
|
|
||||||
|
switchRoot(root);
|
||||||
|
stage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void switchRoot(Parent root){
|
||||||
|
Scene scene = new Scene(root);
|
||||||
|
if(root instanceof GameUI){
|
||||||
|
scene.setOnKeyPressed(event ->{
|
||||||
|
GameUI game = (GameUI) root;
|
||||||
|
if(event.getCode() == KeyCode.ESCAPE){
|
||||||
|
try {
|
||||||
|
FileParserFactory.saveFileFromMap(new File("save.slevel"), game.getLevel());
|
||||||
|
switchRoot(new MenuAccueil());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(root instanceof MenuAccueil){
|
||||||
|
scene.setOnKeyPressed(event ->{
|
||||||
|
if(event.getCode()==KeyCode.ESCAPE){
|
||||||
|
stage.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
stage.setScene(scene);
|
||||||
|
|
||||||
|
stage.setFullScreen(true);
|
||||||
|
stage.setFullScreenExitHint("");
|
||||||
|
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
|
||||||
|
}
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
launch();
|
launch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,11 +14,72 @@ public class Map extends Shape{
|
|||||||
super(matrix);
|
super(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
public void addPiece(Piece piece){
|
public void addPiece(Piece piece){
|
||||||
piece.setLinked_map(this);
|
piece.setLinked_map(this);
|
||||||
pieces.add(piece);
|
pieces.add(piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addPiece(Piece[] pieces) {
|
||||||
|
for (Piece p : pieces)
|
||||||
|
this.addPiece(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* try to place a piece on the map, return true if succeed and false if it failed
|
||||||
|
* @param piece the piece to place
|
||||||
|
* @param pos the position to place the piece in matrix position
|
||||||
|
* @return true if the piece can and is placed and false if it can't and won't not be palced
|
||||||
|
*/
|
||||||
|
public boolean placePiece(Piece piece, Vec2 pos){
|
||||||
|
|
||||||
|
if(!pieces.contains(piece))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
piece.setPosition(null);
|
||||||
|
// In the map limits
|
||||||
|
if ( pos.x + piece.height > height
|
||||||
|
|| pos.y+piece.width > width
|
||||||
|
|| pos.x < 0
|
||||||
|
|| pos.y < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ArrayList<Vec2> occupation = new ArrayList<>();
|
||||||
|
for(Piece p: pieces){
|
||||||
|
if(p.getPosition() == null || p == piece)
|
||||||
|
continue;
|
||||||
|
for (Vec2 o : p.getOccupation()) {
|
||||||
|
occupation.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = pos.x; x < pos.x + piece.height; x++) {
|
||||||
|
for (int y = pos.y; y < pos.y + piece.width; y++) {
|
||||||
|
if ((!getShape()[x][y] || occupation.contains(new Vec2(x, y))) && piece.getShape()[x - pos.x][y - pos.y]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
piece.setPosition(pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if every pieces has a space on the board to know if the game is finished
|
||||||
|
* @return true if the game is finished, false if not
|
||||||
|
*/
|
||||||
|
public boolean gameDone(){
|
||||||
|
ArrayList<Vec2> posList = getPosList();
|
||||||
|
for(Piece p: pieces){
|
||||||
|
posList.removeAll(p.getOccupation());
|
||||||
|
}
|
||||||
|
return posList.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a matrix with all used space on the map to see if a piece can fit in a space
|
* Return a matrix with all used space on the map to see if a piece can fit in a space
|
||||||
*
|
*
|
||||||
@ -33,6 +94,8 @@ public class Map extends Shape{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Piece p : pieces) {
|
for (Piece p : pieces) {
|
||||||
|
if(p.getPosition() == null)
|
||||||
|
continue;
|
||||||
for(int x = 0; x < p.height; x++){
|
for(int x = 0; x < p.height; x++){
|
||||||
for(int y = 0; y < p.width; y++){
|
for(int y = 0; y < p.width; y++){
|
||||||
if (p.getShape()[x][y]){
|
if (p.getShape()[x][y]){
|
||||||
@ -43,4 +106,31 @@ public class Map extends Shape{
|
|||||||
}
|
}
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<Piece> getPieces() {
|
||||||
|
return pieces;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return a new Clean Map without any pieces on it for saving purpose
|
||||||
|
* @return a New Map Object without any pieces or saved data
|
||||||
|
*/
|
||||||
|
public Map getCleanedMap() {
|
||||||
|
try {
|
||||||
|
Map ret = (Map) this.clone();
|
||||||
|
ret.getPieces().clear();
|
||||||
|
return ret;
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the position of each pieces in the map to null
|
||||||
|
*/
|
||||||
|
public void resetPiecesPositions(){
|
||||||
|
for (Piece p : pieces) {
|
||||||
|
p.setPosition(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
104
app/src/main/java/school_project/MapGenerator.java
Normal file
104
app/src/main/java/school_project/MapGenerator.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package school_project;
|
||||||
|
|
||||||
|
import school_project.Utils.Array;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MapGenerator {
|
||||||
|
private static final Random rand = new Random();
|
||||||
|
public enum Difficulty {
|
||||||
|
Easy,
|
||||||
|
Medium,
|
||||||
|
Difficult,
|
||||||
|
}
|
||||||
|
public static Map generate(Difficulty difficulty){
|
||||||
|
Vec2 map_size;
|
||||||
|
int depth = 1; // how much the map shape generator could grind
|
||||||
|
|
||||||
|
// define map size depending on the difficulty
|
||||||
|
switch (difficulty){
|
||||||
|
case Easy:
|
||||||
|
map_size = new Vec2(rand.nextInt(2) + 3, rand.nextInt(2) + 3);
|
||||||
|
break;
|
||||||
|
case Medium:
|
||||||
|
map_size = new Vec2(rand.nextInt(3)+5, rand.nextInt(3)+5);
|
||||||
|
break;
|
||||||
|
case Difficult:
|
||||||
|
map_size = new Vec2(rand.nextInt(2)+8, rand.nextInt(2)+8);
|
||||||
|
depth = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
map_size = new Vec2();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut edges
|
||||||
|
boolean[][] map_shape = new boolean[map_size.x][map_size.y];
|
||||||
|
for (boolean[] b : map_shape) {
|
||||||
|
Arrays.fill(b, true);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < map_shape.length; i++) {
|
||||||
|
for (int j = 0; j < map_shape[0].length; j++) {
|
||||||
|
if(i > depth - 1 && i < map_shape.length - depth && j > depth - 1 && j < map_shape[0].length - depth){
|
||||||
|
j = map_shape[0].length - depth;
|
||||||
|
}
|
||||||
|
map_shape[i][j] = rand.nextBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//delete lonely piece
|
||||||
|
for (int i =0;i<map_shape.length;i++){
|
||||||
|
for (int j = 0; j<map_shape[i].length;j++){
|
||||||
|
boolean test = false;
|
||||||
|
if(map_shape[i][j]){
|
||||||
|
for(int k = Math.max(i - 1, 0); k<= Math.min(i+1,map_shape.length-1); k++){
|
||||||
|
for (int l = Math.max(j - 1, 0); l<= Math.min(j+1,map_shape[i].length-1); l++){
|
||||||
|
if (k==i && l == j)
|
||||||
|
continue;
|
||||||
|
if (map_shape[k][l])
|
||||||
|
test = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!test)
|
||||||
|
map_shape[i][j] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map ret = new Map(map_shape);
|
||||||
|
boolean[][] piece_layout = Array.MatrixCopyOf(map_shape);
|
||||||
|
ArrayList<Vec2> EmptySlots = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < piece_layout.length; i++) {
|
||||||
|
for (int j = 0; j < piece_layout[i].length; j++) {
|
||||||
|
if(piece_layout[i][j]){
|
||||||
|
EmptySlots.add(new Vec2(i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (EmptySlots.size() > 0){
|
||||||
|
Collections.shuffle(EmptySlots);
|
||||||
|
Vec2 selected = EmptySlots.get(0);
|
||||||
|
int size = 3;
|
||||||
|
boolean[][] shape = new boolean[size][size];
|
||||||
|
for(int i = 0; i < size; i++){
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
Vec2 checked = new Vec2(i, j).add(selected);
|
||||||
|
if(EmptySlots.contains(checked)){
|
||||||
|
EmptySlots.remove(checked);
|
||||||
|
piece_layout[checked.x][checked.y] = false;
|
||||||
|
shape[i][j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Piece piece = new Piece(shape);
|
||||||
|
piece.RotateRight(rand.nextInt(4));
|
||||||
|
ret.addPiece(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate pieces
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
221
app/src/main/java/school_project/Parsers/BinaryParser.java
Normal file
221
app/src/main/java/school_project/Parsers/BinaryParser.java
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import school_project.Map;
|
||||||
|
import school_project.Piece;
|
||||||
|
import school_project.Utils.Bitwise;
|
||||||
|
import school_project.Vec2;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class BinaryParser implements FileParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map getLevel(File file, boolean saved_data) throws IOException {
|
||||||
|
Map ret;
|
||||||
|
|
||||||
|
FileInputStream fileStream = new FileInputStream(file);
|
||||||
|
|
||||||
|
byte[] level_data = ExtractLevelData(fileStream);
|
||||||
|
|
||||||
|
ret = new Map(ExtractMapFromLevelData(level_data));
|
||||||
|
|
||||||
|
ret.addPiece(ExtractPiecesFromLevelData(level_data, saved_data));
|
||||||
|
|
||||||
|
fileStream.close();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveLevel(File file, Map level_data, boolean save_data) throws IOException {
|
||||||
|
int byteSize = getByteSizeForMap(level_data, save_data);
|
||||||
|
byte[] data = new byte[byteSize];
|
||||||
|
int i = 0;
|
||||||
|
data[i++] = 'S'; data[i++] = 'M'; data[i++] = 'S';
|
||||||
|
data[i++] = (byte) level_data.getWidth(); data[i++] = (byte) level_data.getHeight();
|
||||||
|
for(byte b : BuildByteFromMatrix(level_data.getShape())){
|
||||||
|
data[i++] = b;
|
||||||
|
}
|
||||||
|
data[i++] = (byte) level_data.getPieces().size();
|
||||||
|
for (Piece p : level_data.getPieces()) {
|
||||||
|
data[i++] = Bitwise.NibbleToByte((byte) p.getWidth(), (byte) p.getHeight());
|
||||||
|
for(byte b : BuildByteFromMatrix(p.getShape())){
|
||||||
|
data[i++] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (save_data){
|
||||||
|
for (Piece p : level_data.getPieces()) {
|
||||||
|
Vec2 _piece_pos = p.getPosition();
|
||||||
|
if(_piece_pos == null){
|
||||||
|
data[i++] = 'F';
|
||||||
|
data[i++] = 'L';
|
||||||
|
}else{
|
||||||
|
data[i++] = (byte) _piece_pos.x;
|
||||||
|
data[i++] = (byte) _piece_pos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data[i++] = 'S'; data[i++] = 'M'; data[i++] = 'E';
|
||||||
|
FileOutputStream save_file = new FileOutputStream(file);
|
||||||
|
save_file.write(data);
|
||||||
|
save_file.flush();
|
||||||
|
save_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract Level data from file content
|
||||||
|
* @param fileStream file stream to read extract data from
|
||||||
|
* @return Level data as an array of byte
|
||||||
|
* @throws IOException Expected if we can't read the file
|
||||||
|
*/
|
||||||
|
static byte[] ExtractLevelData(InputStream fileStream) throws IOException {
|
||||||
|
|
||||||
|
byte[] bytes = fileStream.readAllBytes();
|
||||||
|
|
||||||
|
int start_position = 0, end_position = 0;
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 83){ // SMS
|
||||||
|
start_position = i+3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = start_position; i < bytes.length - 2; i++) {
|
||||||
|
if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 69){ // SME
|
||||||
|
end_position = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.copyOfRange(bytes, start_position, end_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Pieces out of the level data
|
||||||
|
*
|
||||||
|
* @param levelData full data of the level without header and footer
|
||||||
|
* @param saved_data Should extract saved data and included it in the pieces
|
||||||
|
* @return array of Piece from level data
|
||||||
|
*/
|
||||||
|
static Piece[] ExtractPiecesFromLevelData(byte[] levelData, boolean saved_data) {
|
||||||
|
byte map_width = levelData[0], map_height = levelData[1];
|
||||||
|
byte piece_count = levelData[2 + map_width * map_height / 8 + (map_height * map_width % 8 != 0 ? 1 : 0)];
|
||||||
|
Piece[] ret = new Piece[piece_count];
|
||||||
|
byte[] pieces_data = Arrays.copyOfRange(levelData, 3 + map_width * map_height / 8 + (map_height * map_width % 8 != 0 ? 1 : 0), levelData.length);
|
||||||
|
byte[] pieces_positions = saved_data ? Arrays.copyOfRange(levelData, levelData.length - piece_count*2,levelData.length ): null;
|
||||||
|
int piece_offset = 0;
|
||||||
|
for (int piece_index = 0; piece_index < piece_count; piece_index++) {
|
||||||
|
Vec2 _piece_size = Bitwise.ByteToNible(pieces_data[piece_index + piece_offset]);
|
||||||
|
|
||||||
|
byte[] _piece_data = Arrays.copyOfRange(pieces_data, piece_index + piece_offset + 1, piece_index + piece_offset + 1 + _piece_size.x * _piece_size.y / 8 + (_piece_size.x * _piece_size.y % 8 != 0 ? 1 : 0));
|
||||||
|
|
||||||
|
boolean[][] _piece_matrix = BuildMatrixFromBytes(_piece_size.x, _piece_size.y, _piece_data);
|
||||||
|
|
||||||
|
ret[piece_index] = new Piece(_piece_matrix);
|
||||||
|
|
||||||
|
if(saved_data){
|
||||||
|
Vec2 _piece_pos = (pieces_positions[piece_index*2] == 70 && pieces_positions[piece_index*2+1] == 76) ?
|
||||||
|
null : new Vec2(pieces_positions[piece_index*2], pieces_positions[piece_index*2 + 1]);
|
||||||
|
ret[piece_index].setPosition(_piece_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
piece_offset += _piece_size.x * _piece_size.y / 8 + (_piece_size.x * _piece_size.y % 8 != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Map Matrix out of the level data
|
||||||
|
* @param level_data full data of the level without header and footer
|
||||||
|
* @return boolean matrix of the map
|
||||||
|
*/
|
||||||
|
static boolean[][] ExtractMapFromLevelData(byte[] level_data){
|
||||||
|
int map_width = level_data[0], map_height = level_data[1];
|
||||||
|
byte[] map_data = Arrays.copyOfRange(level_data, 2, 2 + map_width * map_height / 8 + (map_height * map_width % 8 != 0 ? 1 : 0));
|
||||||
|
return BuildMatrixFromBytes(map_width, map_height, map_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* take a boolean matrix and build an array of byte following the specs of the parser
|
||||||
|
* @param shape bolean matrix where true are 1 and false are 0
|
||||||
|
* @return byte array with each element compiled for file format
|
||||||
|
*/
|
||||||
|
static byte[] BuildByteFromMatrix(boolean[][] shape){
|
||||||
|
int width = shape[0].length , height = shape.length;
|
||||||
|
boolean[] b_list = new boolean[width * height];
|
||||||
|
for (int x = 0; x < shape.length; x++) {
|
||||||
|
for (int y = 0; y < shape[x].length; y++) {
|
||||||
|
b_list[x * shape[x].length + y] = shape[x][y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
byte[] ret = new byte[width * height / 8 + (width * height % 8 == 0 ? 0 : 1)];
|
||||||
|
for (int i = 0; i < ret.length; i++) {
|
||||||
|
byte current_byte = 0;
|
||||||
|
boolean[] current_byte_data = Arrays.copyOfRange(b_list, i * 8, i * 8 + 8);
|
||||||
|
for (boolean curr_data: current_byte_data) {
|
||||||
|
current_byte = (byte) (current_byte << 1);
|
||||||
|
current_byte = (byte) (current_byte | (curr_data ? 1 : 0));
|
||||||
|
}
|
||||||
|
ret[i] = current_byte;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a boolean Matrix From a byte array
|
||||||
|
* Each Byte is composed of 8 bit, each bit is 1 or 0
|
||||||
|
* if the bit is 0 then it's a false for this cell
|
||||||
|
* else it's true for this cell
|
||||||
|
* @param matrix_width width of the matrix
|
||||||
|
* @param matrix_height height of the matrix
|
||||||
|
* @param matrix_data byte array of the data to export
|
||||||
|
* @return boolean Matrix of the data decompiled
|
||||||
|
*/
|
||||||
|
static boolean[][] BuildMatrixFromBytes(int matrix_width, int matrix_height, byte[] matrix_data){
|
||||||
|
boolean[][] ret = new boolean[matrix_height][matrix_width];
|
||||||
|
|
||||||
|
// Transforming the bit from matrix_data's byte into boolean array for better manipulation
|
||||||
|
boolean[] b_array = new boolean[matrix_height * matrix_width];
|
||||||
|
int index = 0;
|
||||||
|
for(byte b: matrix_data){
|
||||||
|
for (int i = 0; i < 8; i++) { // because 8 bit in a byte
|
||||||
|
b_array[index] = Bitwise.IsBitSetAt(b, i);
|
||||||
|
index++;
|
||||||
|
if(index >= matrix_height * matrix_width)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforming b_array to a 2D matrix
|
||||||
|
for (int x = 0; x < matrix_height; x++) {
|
||||||
|
for (int y = 0; y < matrix_width; y++) {
|
||||||
|
ret[x][y] = b_array[y + x * matrix_width];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* give the amount of byte needed to store the given Map
|
||||||
|
* following the binary file format
|
||||||
|
* @param level the map to check
|
||||||
|
* @param data should add save data or only level data
|
||||||
|
* @return integer of the ammount of byte needed
|
||||||
|
*/
|
||||||
|
public static int getByteSizeForMap(Map level, boolean data){
|
||||||
|
int ret = 6; // header + footer
|
||||||
|
ret += 2; //size of the piece
|
||||||
|
ret += ((level.getWidth() * level.getHeight()) / 8); // size of the map
|
||||||
|
ret += level.getHeight() * level.getWidth() % 8 == 0 ? 0 : 1; // Add 1 if the size of map is not a mult of 8
|
||||||
|
ret += 1; // amount of pieces
|
||||||
|
for(Piece p: level.getPieces()){
|
||||||
|
ret += 1; // size of the piece
|
||||||
|
ret += p.getHeight() * p.getWidth() / 8;
|
||||||
|
ret += p.getHeight() * p.getWidth() % 8 == 0 ? 0 : 1; // add 1 if the size of the piece is not mult of 8
|
||||||
|
if(data){
|
||||||
|
ret += 2; // if the piece is not placed, only one byte else 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
33
app/src/main/java/school_project/Parsers/FileParser.java
Normal file
33
app/src/main/java/school_project/Parsers/FileParser.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import school_project.Map;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface FileParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the file and create a Map with its shape and pieces setup
|
||||||
|
*
|
||||||
|
* @param file file to parse
|
||||||
|
* @param saved_data does the saved data should be added to the map
|
||||||
|
* @return Map Object parsed with file data
|
||||||
|
* @see <a href="http://school.debucquoy.me/spec/FileParser.html#file-parser-specification"> Parser Specification</a>
|
||||||
|
* @throws FileNotFoundException if the file was not found or was not accessible
|
||||||
|
* @throws IOException if an I/O occurs
|
||||||
|
*/
|
||||||
|
Map getLevel(File file, boolean saved_data) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save Map to a file without all it's data
|
||||||
|
* Could be used for generating level file. might not be used in game.
|
||||||
|
* @param file the file where to save
|
||||||
|
* @param levelData the map to save
|
||||||
|
* @param save_data should save the map data (need to be false only in development I think)
|
||||||
|
* @throws FileNotFoundException The file could not be created
|
||||||
|
* @throws IOException if an I/O occurs
|
||||||
|
*/
|
||||||
|
void saveLevel(File file, Map levelData, boolean save_data) throws IOException;
|
||||||
|
}
|
132
app/src/main/java/school_project/Parsers/FileParserFactory.java
Normal file
132
app/src/main/java/school_project/Parsers/FileParserFactory.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import javafx.util.Pair;
|
||||||
|
import school_project.Map;
|
||||||
|
import school_project.Piece;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.NotSerializableException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to find the right parser to parser a save/level file.
|
||||||
|
* This should be the only right way to save/load a file! you can just use `Map loadMapFromFile(File)` to load a file
|
||||||
|
* and `void saveFileFromMap(File, Map)` to save a file
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* there is currently 2 file format with 2 variation each (save file or level file)
|
||||||
|
* - BinaryParser
|
||||||
|
* - ".level"
|
||||||
|
* - ".slevel"
|
||||||
|
* - SerializeParser
|
||||||
|
* - ".serialized"
|
||||||
|
* - ".sserialized"
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* More file format can be added in the future by adding a new class that implement parser
|
||||||
|
* and adding it to this file
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author tonitch
|
||||||
|
*/
|
||||||
|
public class FileParserFactory {
|
||||||
|
/**
|
||||||
|
* Load a file and return a map
|
||||||
|
* If this is a save map, return the map with its save data
|
||||||
|
* @param file file to get data from
|
||||||
|
* @return Map generated from the file
|
||||||
|
* @throws FileNotFoundException if the file was not found or was not accessible
|
||||||
|
* @throws IOException if an I/O occurs
|
||||||
|
*/
|
||||||
|
public static Map loadMapFromFile(File file) throws IOException {
|
||||||
|
Pair<FileParser, Boolean> parser= getFileParser(file);
|
||||||
|
return parser.getKey().getLevel(file, parser.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a file in a specific format, this format is defined by the file extension
|
||||||
|
* This file extention could be: ".level", ".slevel", ".serialized", ".sserialized"
|
||||||
|
* for save file use the .s variations
|
||||||
|
* @param file file name to be saved to with the right extension
|
||||||
|
* @param map map file to save
|
||||||
|
* @throws NotSerializableException the file extension is not recognised
|
||||||
|
* @throws FileNotFoundException The file could not be created
|
||||||
|
* @throws IOException if an I/O occurs
|
||||||
|
*/
|
||||||
|
public static void saveFileFromMap(File file, Map map) throws IOException {
|
||||||
|
Pair<FileParser, Boolean> parser= getFileParser(file);
|
||||||
|
parser.getKey().saveLevel(file, map, parser.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<FileParser, Boolean> getFileParser(File file) throws NotSerializableException {
|
||||||
|
FileParser fileParser;
|
||||||
|
boolean save_data;
|
||||||
|
|
||||||
|
if (file.toString().toLowerCase().endsWith(".level")){
|
||||||
|
fileParser = new BinaryParser();
|
||||||
|
save_data = false;
|
||||||
|
}else if(file.toString().toLowerCase().endsWith(".slevel")){
|
||||||
|
fileParser = new BinaryParser();
|
||||||
|
save_data = true;
|
||||||
|
}else if(file.toString().toLowerCase().endsWith(".serialized")){
|
||||||
|
fileParser = new SerializeParser();
|
||||||
|
save_data = false;
|
||||||
|
}else if(file.toString().toLowerCase().endsWith(".sserialized")) {
|
||||||
|
fileParser = new SerializeParser();
|
||||||
|
save_data = true;
|
||||||
|
}else {
|
||||||
|
throw new NotSerializableException("This file format is not supported");
|
||||||
|
}
|
||||||
|
return new Pair<FileParser, Boolean>(fileParser, save_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
Scanner in = new Scanner(System.in);
|
||||||
|
Map level = new Map();
|
||||||
|
|
||||||
|
System.out.print("Entrez le nom du fichier:");
|
||||||
|
File file = new File(in.nextLine());
|
||||||
|
|
||||||
|
System.out.print("Entrez la largeur de la map:");
|
||||||
|
int map_width = in.nextInt();
|
||||||
|
|
||||||
|
System.out.print("Entrez la hauteur de la map:");
|
||||||
|
int map_height = in.nextInt();
|
||||||
|
|
||||||
|
boolean[][] map_shape = new boolean[map_height][map_width];
|
||||||
|
|
||||||
|
for (int i = 0; i < map_height; i++) {
|
||||||
|
for (int j = 0; j < map_width; j++) {
|
||||||
|
System.out.print("mur (" + i + ", " + j + ")? (y/n):");
|
||||||
|
map_shape[i][j] = in.next(".").charAt(0) != 'y';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level.setShape(map_shape);
|
||||||
|
System.out.println(level);
|
||||||
|
System.out.print("Entrez le nombre de pieces:");
|
||||||
|
int piece_amount = in.nextInt();
|
||||||
|
|
||||||
|
for (int i = 0; i < piece_amount; i++) {
|
||||||
|
System.out.print("Entrez la largeur de la piece" + (i+1) +": ");
|
||||||
|
int _piece_width = in.nextInt();
|
||||||
|
|
||||||
|
System.out.print("Entrez la hauteur de la piece" + (i+1) +": ");
|
||||||
|
int _piece_height = in.nextInt();
|
||||||
|
boolean[][] _piece_shape = new boolean[_piece_height][_piece_width];
|
||||||
|
|
||||||
|
for (int k = 0; k < _piece_height; k++) {
|
||||||
|
for (int j = 0; j < _piece_width; j++) {
|
||||||
|
System.out.print("mur (" + k + ", " + j + ")? (y/n):");
|
||||||
|
_piece_shape[k][j] = in.next(".").charAt(0) != 'y';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level.addPiece(new Piece(_piece_shape));
|
||||||
|
}
|
||||||
|
saveFileFromMap(file, level);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import school_project.Map;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class SerializeParser implements FileParser{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map getLevel(File file, boolean saved_data) throws IOException {
|
||||||
|
// saved_data is ignored in this case because the file is serialized data and it already knows if should have saved_data or not at this point
|
||||||
|
FileInputStream fileStream = new FileInputStream(file);
|
||||||
|
ObjectInputStream objectStream = new ObjectInputStream(fileStream);
|
||||||
|
try {
|
||||||
|
return (Map) objectStream.readObject();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new IOException("the serialized file format has not found any object in the file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveLevel(File file, Map levelData, boolean save_data) throws IOException {
|
||||||
|
FileOutputStream fileStream = new FileOutputStream(file);
|
||||||
|
ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
|
||||||
|
objectStream.writeObject(save_data ? levelData : levelData.getCleanedMap());
|
||||||
|
|
||||||
|
objectStream.close();
|
||||||
|
fileStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
package school_project;
|
package school_project;
|
||||||
|
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.paint.Paint;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent a Piece in the game.
|
* Represent a Piece in the game.
|
||||||
* Every Piece should be contained in a Map Object.
|
* Every Piece should be contained in a Map Object.
|
||||||
@ -10,13 +16,21 @@ public class Piece extends Shape{
|
|||||||
|
|
||||||
private Vec2 Position;
|
private Vec2 Position;
|
||||||
private Map linked_map;
|
private Map linked_map;
|
||||||
|
private transient Paint color; // https://www.baeldung.com/java-transient-keyword
|
||||||
public Piece() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Piece(boolean[][] matrix) {
|
public Piece(boolean[][] matrix) {
|
||||||
super(matrix);
|
super(matrix);
|
||||||
|
Random rand = new Random();
|
||||||
|
// the %.8 is there to avoid pieces that are too "white" so that we can see them
|
||||||
|
color = new Color(rand.nextDouble()%.8, rand.nextDouble() %.8, rand.nextDouble()%.8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(Paint p){
|
||||||
|
color = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paint getColor(){
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec2 getPosition() {
|
public Vec2 getPosition() {
|
||||||
@ -24,13 +38,23 @@ public class Piece extends Shape{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Vec2 position){
|
public void setPosition(Vec2 position){
|
||||||
if (linked_map == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Position = position;
|
this.Position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<Vec2> getOccupation(){
|
||||||
|
ArrayList<Vec2> ret = new ArrayList<>();
|
||||||
|
if(Position == null)
|
||||||
|
return ret;
|
||||||
|
for (int x = 0; x < height; x++) {
|
||||||
|
for (int y = 0; y < width; y++) {
|
||||||
|
if(getShape()[x][y]){
|
||||||
|
ret.add(new Vec2(getPosition().x + x, getPosition().y + y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the map the piece is into the the map argument
|
* set the map the piece is into the the map argument
|
||||||
* @param map map where to place the piece
|
* @param map map where to place the piece
|
||||||
@ -54,6 +78,20 @@ public class Piece extends Shape{
|
|||||||
}
|
}
|
||||||
times--;
|
times--;
|
||||||
matrix = temp_matrix;
|
matrix = temp_matrix;
|
||||||
|
height = matrix.length;
|
||||||
|
width = matrix[0].length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(obj instanceof Piece){
|
||||||
|
Piece pieceObj = (Piece) obj;
|
||||||
|
if (pieceObj.getPosition() != null && this.getPosition() != null){
|
||||||
|
return pieceObj.getPosition().equals(this.getPosition()) && pieceObj.getShape().equals(getShape());
|
||||||
|
}
|
||||||
|
return pieceObj.getShape().equals(getShape());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
100
app/src/main/java/school_project/Scenes/GameUI.java
Normal file
100
app/src/main/java/school_project/Scenes/GameUI.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package school_project.Scenes;
|
||||||
|
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.input.MouseButton;
|
||||||
|
|
||||||
|
import school_project.Controller;
|
||||||
|
import school_project.Map;
|
||||||
|
import school_project.Piece;
|
||||||
|
import school_project.Scenes.ScreenLevelFinish;
|
||||||
|
import school_project.Utils.MatrixShape;
|
||||||
|
import school_project.Vec2;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
public class GameUI extends Group{
|
||||||
|
public final static int SEGMENT_SIZE = 50;
|
||||||
|
public final static int SPACE_SIZE = 5;
|
||||||
|
private final Vec2 piece_pos_click = new Vec2();
|
||||||
|
|
||||||
|
private Map level;
|
||||||
|
|
||||||
|
public GameUI(Map level) throws FileNotFoundException {
|
||||||
|
super();
|
||||||
|
this.level = level;
|
||||||
|
|
||||||
|
MatrixShape grid = new MatrixShape(level);
|
||||||
|
|
||||||
|
//center the grid
|
||||||
|
grid.setLayoutX((Controller.screen_size.x - grid.boundary_size.x) >> 1);
|
||||||
|
grid.setLayoutY((Controller.screen_size.y - grid.boundary_size.y) >> 1);
|
||||||
|
|
||||||
|
getChildren().add(grid);
|
||||||
|
|
||||||
|
Vec2 piece_space = new Vec2(SPACE_SIZE, SPACE_SIZE);
|
||||||
|
int column = 0;
|
||||||
|
for (Piece p : level.getPieces()) {
|
||||||
|
MatrixShape _piece = new MatrixShape(p);
|
||||||
|
|
||||||
|
if(piece_space.y + _piece.boundary_size.y >= Controller.screen_size.y){
|
||||||
|
column++;
|
||||||
|
piece_space.y = SPACE_SIZE;
|
||||||
|
piece_space.x = (SEGMENT_SIZE*3 + SPACE_SIZE*4 )* column;
|
||||||
|
}
|
||||||
|
|
||||||
|
_piece.setLayoutX(piece_space.x);
|
||||||
|
_piece.setLayoutY(piece_space.y);
|
||||||
|
|
||||||
|
piece_space.y += _piece.boundary_size.y;
|
||||||
|
|
||||||
|
if(p.getPosition() != null){
|
||||||
|
_piece.setLayoutX(grid.getLayoutX() + p.getPosition().y * (SEGMENT_SIZE+SPACE_SIZE));
|
||||||
|
_piece.setLayoutY(grid.getLayoutY() + p.getPosition().x * (SEGMENT_SIZE+SPACE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pieces Events
|
||||||
|
_piece.setOnMouseClicked(event -> {
|
||||||
|
if(event.getButton() == MouseButton.SECONDARY){
|
||||||
|
((Piece) _piece.shape).RotateRight(1);
|
||||||
|
_piece.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_piece.setOnMousePressed(event -> {
|
||||||
|
piece_pos_click.x = (int) event.getX();
|
||||||
|
piece_pos_click.y = (int) event.getY();
|
||||||
|
});
|
||||||
|
_piece.setOnMouseDragged(event -> {
|
||||||
|
_piece.toFront();
|
||||||
|
_piece.setLayoutX(event.getSceneX() - piece_pos_click.x);
|
||||||
|
_piece.setLayoutY(event.getSceneY() - piece_pos_click.y);
|
||||||
|
});
|
||||||
|
_piece.setOnMouseReleased(event -> {
|
||||||
|
if(event.getButton() != MouseButton.PRIMARY)
|
||||||
|
return;
|
||||||
|
p.setPosition(null);
|
||||||
|
if(event.getSceneX() > grid.getLayoutX() && event.getSceneX() < grid.getLayoutX() + grid.boundary_size.x
|
||||||
|
&& event.getSceneY() > grid.getLayoutY() && event.getSceneY() < grid.getLayoutY() + grid.boundary_size.y )
|
||||||
|
{
|
||||||
|
// Inverted because screen is x →; y ↓ and matrix is x ↓; y →
|
||||||
|
Vec2 piece_position_in_grid = new Vec2(
|
||||||
|
(int) (_piece.getLayoutY() + (SEGMENT_SIZE+SPACE_SIZE)/2 - grid.getLayoutY())/(SEGMENT_SIZE+SPACE_SIZE),
|
||||||
|
(int) (_piece.getLayoutX() + (SEGMENT_SIZE+SPACE_SIZE)/2 - grid.getLayoutX())/(SEGMENT_SIZE+SPACE_SIZE)
|
||||||
|
);
|
||||||
|
level.placePiece(p, piece_position_in_grid);
|
||||||
|
if(p.getPosition() != null){
|
||||||
|
_piece.setLayoutX(grid.getLayoutX() + p.getPosition().y * (SEGMENT_SIZE+SPACE_SIZE));
|
||||||
|
_piece.setLayoutY(grid.getLayoutY() + p.getPosition().x * (SEGMENT_SIZE+SPACE_SIZE));
|
||||||
|
}
|
||||||
|
if(level.gameDone()){
|
||||||
|
Controller.switchRoot(new ScreenLevelFinish(level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getChildren().add(_piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
}
|
88
app/src/main/java/school_project/Scenes/MenuAccueil.java
Normal file
88
app/src/main/java/school_project/Scenes/MenuAccueil.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package school_project.Scenes;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ChoiceBox;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import school_project.Controller;
|
||||||
|
import school_project.MapGenerator;
|
||||||
|
import school_project.Parsers.FileParserFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class MenuAccueil extends StackPane {
|
||||||
|
public MenuAccueil(){
|
||||||
|
super();
|
||||||
|
//create all the objet that I need
|
||||||
|
ChoiceBox<String> SlctDifficulty = new ChoiceBox<>();
|
||||||
|
SlctDifficulty.getItems().addAll("Easy", "Medium", "Difficult");
|
||||||
|
|
||||||
|
Label RdmLvl = new Label("Random Level : ");
|
||||||
|
Button LoadLvl = new Button("Load game");
|
||||||
|
Button SelectLevel= new Button("Select Level");
|
||||||
|
|
||||||
|
Label Title = new Label("Welcome to Road to Master");
|
||||||
|
SlctDifficulty.setOnAction(event -> {
|
||||||
|
String choosediff = SlctDifficulty.getSelectionModel().getSelectedItem();
|
||||||
|
switch (choosediff) {
|
||||||
|
case "Easy":
|
||||||
|
try {
|
||||||
|
Controller.switchRoot(new GameUI(MapGenerator.generate(MapGenerator.Difficulty.Easy)));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Medium":
|
||||||
|
try {
|
||||||
|
Controller.switchRoot(new GameUI(MapGenerator.generate(MapGenerator.Difficulty.Medium)));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Difficult":
|
||||||
|
try {
|
||||||
|
Controller.switchRoot(new GameUI(MapGenerator.generate(MapGenerator.Difficulty.Difficult)));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//set up all the Button where I need
|
||||||
|
|
||||||
|
getChildren().addAll(Title,SlctDifficulty,SelectLevel,RdmLvl,LoadLvl);
|
||||||
|
RdmLvl.setFont(Font.font(25));
|
||||||
|
RdmLvl.setTextFill(Color.GOLD);
|
||||||
|
Title.setFont(Font.font(40));
|
||||||
|
Title.setTextFill(Color.RED);
|
||||||
|
setAlignment(Title, Pos.TOP_CENTER);
|
||||||
|
setAlignment(LoadLvl,Pos.BOTTOM_CENTER);
|
||||||
|
setAlignment(SlctDifficulty,Pos.CENTER_LEFT);
|
||||||
|
setAlignment(SelectLevel,Pos.CENTER_RIGHT);
|
||||||
|
setAlignment(RdmLvl, Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
setMargin(RdmLvl,new Insets(0,0,0,100));
|
||||||
|
setMargin(SlctDifficulty,new Insets(0,0,0,300));
|
||||||
|
setMargin(SelectLevel,new Insets(0,300,0,0));
|
||||||
|
setMargin(Title,new Insets(200,0,0,0));
|
||||||
|
setMargin(LoadLvl,new Insets(0,0,200,0));
|
||||||
|
|
||||||
|
SelectLevel.setOnAction(event -> Controller.switchRoot(new MenuLevel(1)));
|
||||||
|
LoadLvl.setOnAction(event -> {
|
||||||
|
try {
|
||||||
|
Controller.switchRoot(new GameUI(FileParserFactory.loadMapFromFile(new File("save.slevel"))));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getStyleClass().add("BorderPane");
|
||||||
|
getStylesheets().add(String.valueOf(getClass().getResource("StyleMenuAcceuil.css")));
|
||||||
|
}
|
||||||
|
}
|
121
app/src/main/java/school_project/Scenes/MenuLevel.java
Normal file
121
app/src/main/java/school_project/Scenes/MenuLevel.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package school_project.Scenes;
|
||||||
|
|
||||||
|
import javafx.geometry.HPos;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.layout.ColumnConstraints;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.RowConstraints;
|
||||||
|
import school_project.Controller;
|
||||||
|
import school_project.Parsers.FileParserFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class MenuLevel extends GridPane {
|
||||||
|
private int StartLevel;
|
||||||
|
public MenuLevel(int choose_day) {
|
||||||
|
|
||||||
|
//create all Object that I need
|
||||||
|
RowConstraints[] Rows = new RowConstraints[5];
|
||||||
|
ColumnConstraints[] Columns = new ColumnConstraints[3];
|
||||||
|
Button[] Days = new Button[3];
|
||||||
|
Button BckMenu = new Button("Back to menu");
|
||||||
|
|
||||||
|
BckMenu.setOnAction(event -> Controller.switchRoot(new MenuAccueil()));
|
||||||
|
setHalignment(BckMenu,HPos.CENTER);
|
||||||
|
add(BckMenu,2,4);
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < Days.length; i++){
|
||||||
|
Days[i] = new Button("Day"+(i+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
//it's here that I know which day I can show on the screen
|
||||||
|
|
||||||
|
if (choose_day == 1) {
|
||||||
|
StartLevel = 1;
|
||||||
|
add(Days[1],0,0);
|
||||||
|
add(Days[2],2,0);
|
||||||
|
setHalignment(Days[1], HPos.CENTER);
|
||||||
|
setHalignment(Days[2], HPos.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (choose_day == 2) {
|
||||||
|
StartLevel = 11;
|
||||||
|
add(Days[0], 0, 0);
|
||||||
|
add(Days[2], 2, 0);
|
||||||
|
setHalignment(Days[0], HPos.CENTER);
|
||||||
|
setHalignment(Days[2], HPos.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (choose_day == 3) {
|
||||||
|
StartLevel = 21;
|
||||||
|
add(Days[0], 0, 0);
|
||||||
|
add(Days[1], 2, 0);
|
||||||
|
setHalignment(Days[0], HPos.CENTER);
|
||||||
|
setHalignment(Days[1], HPos.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
Days[0].setOnAction(event -> Controller.switchRoot(new MenuLevel(1)));
|
||||||
|
Days[1].setOnAction(event -> Controller.switchRoot(new MenuLevel(2)));
|
||||||
|
Days[2].setOnAction(event -> Controller.switchRoot(new MenuLevel(3)));
|
||||||
|
|
||||||
|
//It's here that I put all buttons where I need (base on column not row)
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
for (int j = 1; j < 5; j++) {
|
||||||
|
Button levelButton = new Button("level "+(StartLevel));
|
||||||
|
levelButton.setOnAction(event -> {
|
||||||
|
try {
|
||||||
|
String levelName = ((Button)event.getSource()).getText().replace(" ", "") + ".level";
|
||||||
|
GameUI level = new GameUI(FileParserFactory.loadMapFromFile(new File(Controller.class.getResource("levels/" + levelName).getFile())));
|
||||||
|
Controller.switchRoot(level);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("Le niveau " + StartLevel + "n'existe pas.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(i==0){
|
||||||
|
StartLevel+=3;
|
||||||
|
add(levelButton,i,j);
|
||||||
|
setHalignment(levelButton,HPos.CENTER);
|
||||||
|
if(j==4){
|
||||||
|
StartLevel-=11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(i==1&&j!=4) {
|
||||||
|
StartLevel += 3;
|
||||||
|
add(levelButton, i, j);
|
||||||
|
setHalignment(levelButton,HPos.CENTER);
|
||||||
|
if (j == 3) {
|
||||||
|
StartLevel -=8;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(i==2&&j!=4){
|
||||||
|
StartLevel+=3;
|
||||||
|
add(levelButton,i,j);
|
||||||
|
setHalignment(levelButton,HPos.CENTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<=2;i++){
|
||||||
|
Columns[i] = new ColumnConstraints();
|
||||||
|
Columns[i].setPercentWidth(33);
|
||||||
|
getColumnConstraints().addAll(Columns[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i= 0;i<=4;i++){
|
||||||
|
Rows[i] = new RowConstraints();
|
||||||
|
Rows[i].setPercentHeight(20);
|
||||||
|
getRowConstraints().addAll(Rows[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setHgap(20);
|
||||||
|
setVgap(20);
|
||||||
|
setPadding(new Insets(20,10,10,20));
|
||||||
|
getStyleClass().add("GridPane");
|
||||||
|
getStylesheets().add(String.valueOf(getClass().getResource("StyleMenuAcceuil.css")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package school_project.Scenes;
|
||||||
|
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import school_project.Controller;
|
||||||
|
import school_project.Map;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
public class ScreenLevelFinish extends StackPane {
|
||||||
|
|
||||||
|
public ScreenLevelFinish(Map lastlevel){
|
||||||
|
super();
|
||||||
|
Button retry = new Button("Retry Level");
|
||||||
|
Label CongraMess = new Label(" LEVEL DONE GREAT JOB ");
|
||||||
|
CongraMess.setFont(Font.font(40));
|
||||||
|
Button BckMenu = new Button("Back to Menu");
|
||||||
|
BckMenu.setFont(Font.font(25));
|
||||||
|
Button ChooseLvl = new Button("Choose level");
|
||||||
|
ChooseLvl.setFont(Font.font(25));
|
||||||
|
|
||||||
|
BckMenu.setOnAction(event -> Controller.switchRoot(new MenuAccueil()));
|
||||||
|
ChooseLvl.setOnAction(event -> Controller.switchRoot(new MenuLevel(1)));
|
||||||
|
retry.setOnAction(event -> {
|
||||||
|
try {
|
||||||
|
lastlevel.resetPiecesPositions();
|
||||||
|
Controller.switchRoot(new GameUI(lastlevel));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getChildren().addAll(BckMenu,ChooseLvl,CongraMess,retry);
|
||||||
|
setAlignment(retry,Pos.BOTTOM_CENTER);
|
||||||
|
setAlignment(BckMenu, Pos.CENTER_RIGHT);
|
||||||
|
setAlignment(ChooseLvl, Pos.CENTER_LEFT);
|
||||||
|
setAlignment(CongraMess, Pos.TOP_CENTER);
|
||||||
|
setMargin(BckMenu, new Insets(0,300,0,0 ));
|
||||||
|
setMargin(ChooseLvl,new Insets(0,0,0,300));
|
||||||
|
setMargin(CongraMess,new Insets(300,0,0,0));
|
||||||
|
setMargin(retry,new Insets(0,0,300,0));
|
||||||
|
|
||||||
|
getStyleClass().add("StackPane");
|
||||||
|
getStylesheets().add(String.valueOf(getClass().getResource("StyleMenuAcceuil.css")));
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,16 @@
|
|||||||
package school_project;
|
package school_project;
|
||||||
|
|
||||||
|
|
||||||
|
import school_project.Utils.Array;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for everything that is a shape kind, like map and pieces
|
* Base class for everything that is a shape kind, like map and pieces
|
||||||
* it contain a matrix of boolean where the shape is defined by the true's
|
* it contain a matrix of boolean where the shape is defined by the true's
|
||||||
*/
|
*/
|
||||||
public class Shape {
|
public class Shape implements Serializable, Cloneable{
|
||||||
|
|
||||||
protected boolean[][] matrix;
|
protected boolean[][] matrix;
|
||||||
protected int height, width;
|
protected int height, width;
|
||||||
@ -19,14 +24,52 @@ public class Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setShape(boolean[][] matrix) throws IllegalArgumentException{
|
public void setShape(boolean[][] matrix) throws IllegalArgumentException{
|
||||||
height = matrix.length;
|
|
||||||
width = matrix[0].length;
|
|
||||||
|
|
||||||
for (boolean[] row: matrix){
|
for (boolean[] row: matrix){
|
||||||
if(row.length != width){
|
if(row.length != matrix[0].length){
|
||||||
throw new IllegalArgumentException("The argument should be a square matrix");
|
throw new IllegalArgumentException("The argument should be a square matrix");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < matrix.length; i++) {
|
||||||
|
if(!Array.isRowOnlyFalse(matrix, i)) {
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
matrix = Array.MatrixRemoveRow(matrix, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = matrix.length-1; i >= 0; i--) {
|
||||||
|
if(!Array.isRowOnlyFalse(matrix, i)) {
|
||||||
|
for (int j = matrix.length-1; j > i; j--) {
|
||||||
|
matrix = Array.MatrixRemoveRow(matrix, j);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < matrix[0].length; i++) {
|
||||||
|
if(!Array.isColumnOnlyFalse(matrix, i)) {
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
matrix = Array.MatrixRemoveColumn(matrix, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = matrix[0].length-1; i >= 0; i--){
|
||||||
|
if(!Array.isColumnOnlyFalse(matrix, i)) {
|
||||||
|
for (int j = matrix[0].length-1; j > i; j--) {
|
||||||
|
matrix = Array.MatrixRemoveColumn(matrix, j);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
height = matrix.length;
|
||||||
|
width = matrix[0].length;
|
||||||
|
|
||||||
this.matrix = matrix;
|
this.matrix = matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,4 +84,33 @@ public class Shape {
|
|||||||
public boolean[][] getShape() {
|
public boolean[][] getShape() {
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of all the open possition of the map
|
||||||
|
* @return ArrayList of vec2 of all the positions
|
||||||
|
*/
|
||||||
|
public ArrayList<Vec2> getPosList(){
|
||||||
|
ArrayList<Vec2> ret = new ArrayList<>();
|
||||||
|
for (int x = 0; x < height; x++) {
|
||||||
|
for (int y = 0; y < width; y++) {
|
||||||
|
if(matrix[x][y]){
|
||||||
|
ret.add(new Vec2(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String ret = "";
|
||||||
|
for (boolean[] row : matrix) {
|
||||||
|
for (boolean el : row) {
|
||||||
|
if(el) ret = ret.concat("⬛");
|
||||||
|
else ret = ret.concat("⬜");
|
||||||
|
}
|
||||||
|
ret = ret.concat("\n");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
61
app/src/main/java/school_project/Utils/Array.java
Normal file
61
app/src/main/java/school_project/Utils/Array.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package school_project.Utils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Array{
|
||||||
|
public static boolean[][] MatrixCopyOf(boolean[][] o){
|
||||||
|
boolean[][] ret = new boolean[o.length][];
|
||||||
|
for (int i = 0; i < o.length; i++){
|
||||||
|
ret[i] = Arrays.copyOf(o[i], o[i].length);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean[][] MatrixRemoveRow(boolean[][] o, int row){
|
||||||
|
boolean[][] newMatrix = new boolean[o.length - 1][o[0].length];
|
||||||
|
int newRow = 0;
|
||||||
|
for (int i = 0; i < o.length; i++) {
|
||||||
|
if(i == row)
|
||||||
|
i++;
|
||||||
|
if(i >= o.length)
|
||||||
|
continue;
|
||||||
|
newMatrix[newRow] = o[i];
|
||||||
|
newRow++;
|
||||||
|
}
|
||||||
|
return newMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean[][] MatrixRemoveColumn(boolean[][] o, int col){
|
||||||
|
boolean[][] newMatrix = new boolean[o.length][o[0].length - 1];
|
||||||
|
for (int i = 0; i < o.length; i++) {
|
||||||
|
int newCol = 0;
|
||||||
|
for(int j = 0; j < o[0].length; j++){
|
||||||
|
if(j == col)
|
||||||
|
j++;
|
||||||
|
if(j >= o[0].length)
|
||||||
|
continue;
|
||||||
|
newMatrix[i][newCol] = o[i][j];
|
||||||
|
newCol++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRowOnlyFalse(boolean[][] o, int row){
|
||||||
|
boolean mark = true;
|
||||||
|
for (int i = 0; i < o[row].length; i++) {
|
||||||
|
if(o[row][i])
|
||||||
|
mark = false;
|
||||||
|
}
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isColumnOnlyFalse(boolean[][] o, int column){
|
||||||
|
boolean mark = true;
|
||||||
|
for (int i = 0; i < o.length; i++) {
|
||||||
|
if(o[i][column])
|
||||||
|
mark = false;
|
||||||
|
}
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
}
|
43
app/src/main/java/school_project/Utils/Bitwise.java
Normal file
43
app/src/main/java/school_project/Utils/Bitwise.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package school_project.Utils;
|
||||||
|
|
||||||
|
import school_project.Vec2;
|
||||||
|
|
||||||
|
public class Bitwise {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the bit at pos is 1 or 0
|
||||||
|
* @param b byte to test
|
||||||
|
* @param pos position in b to check
|
||||||
|
* @return true if the bit at pos is 1 or false if it is 0
|
||||||
|
*/
|
||||||
|
public static boolean IsBitSetAt(byte b, int pos){
|
||||||
|
pos = 7 - pos;
|
||||||
|
return (b & (1 << pos))!= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a byte (8 bit) to two Nible (4 bit) with a split in the middle
|
||||||
|
* Exemple:
|
||||||
|
* in = 01000101 (=69)
|
||||||
|
* out = { 00000100, 00000101 } (={4, 5})
|
||||||
|
*
|
||||||
|
* @param in the byte to split
|
||||||
|
* @return an arrya of 2 byte ret[0] = left part; ret[1] = right part
|
||||||
|
*/
|
||||||
|
public static Vec2 ByteToNible(byte in){
|
||||||
|
Vec2 ret = new Vec2();
|
||||||
|
ret.x = (byte) (in >> 4);
|
||||||
|
ret.y = (byte) (in & 15); // apply the mask '00001111'
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform 2 byte into 1 with a left part ( 4 bits ) and a right part ( 4 bits)
|
||||||
|
* @param left first 4 bits
|
||||||
|
* @param right last 4 bits
|
||||||
|
* @return concatenated byte
|
||||||
|
*/
|
||||||
|
public static byte NibbleToByte(byte left, byte right){
|
||||||
|
return (byte) ((left << 4) | right);
|
||||||
|
}
|
||||||
|
}
|
65
app/src/main/java/school_project/Utils/MatrixShape.java
Normal file
65
app/src/main/java/school_project/Utils/MatrixShape.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package school_project.Utils;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.paint.Paint;
|
||||||
|
import javafx.scene.shape.Rectangle;
|
||||||
|
import school_project.*;
|
||||||
|
import school_project.Scenes.GameUI;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
public class MatrixShape extends GridPane {
|
||||||
|
public Shape shape;
|
||||||
|
public Vec2 boundary_size = new Vec2();
|
||||||
|
private Paint color;
|
||||||
|
public MatrixShape(Shape shape) {
|
||||||
|
super();
|
||||||
|
this.shape = shape;
|
||||||
|
if(shape instanceof Piece){
|
||||||
|
Piece p = (Piece) shape;
|
||||||
|
color = p.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
setHgap(GameUI.SPACE_SIZE);
|
||||||
|
setVgap(GameUI.SPACE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(){
|
||||||
|
getChildren().clear();
|
||||||
|
boolean[][] shape_matrix = shape.getShape();
|
||||||
|
for (int i = 0; i < shape_matrix.length; i++) {
|
||||||
|
for (int j = 0; j < shape_matrix[i].length; j++) {
|
||||||
|
Node _cell;
|
||||||
|
if(shape_matrix[i][j]){
|
||||||
|
if(shape instanceof Piece){
|
||||||
|
Piece p = (Piece) shape;
|
||||||
|
_cell = new Rectangle(GameUI.SEGMENT_SIZE, GameUI.SEGMENT_SIZE);
|
||||||
|
((Rectangle) _cell).setFill(color);
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
_cell = new ImageView(new Image(new FileInputStream(Controller.class.getResource("tile.png").getFile())));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_cell = new Pane();
|
||||||
|
((Pane) _cell).setPrefSize(GameUI.SEGMENT_SIZE, GameUI.SEGMENT_SIZE);
|
||||||
|
}
|
||||||
|
add(_cell, j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boundary_size = new Vec2((GameUI.SEGMENT_SIZE + GameUI.SPACE_SIZE) * shape.getWidth(), (GameUI.SEGMENT_SIZE + GameUI.SPACE_SIZE) * shape.getHeight());
|
||||||
|
}
|
||||||
|
public void setColor(Paint p) {
|
||||||
|
color = p;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package school_project;
|
package school_project;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to represent a position/vector/... any ensemble of 2 elements that have to work together in
|
* This is used to represent a position/vector/... any ensemble of 2 elements that have to work together in
|
||||||
* a plan. This way we can use some basic operations over them.
|
* a plan. This way we can use some basic operations over them.
|
||||||
*/
|
*/
|
||||||
public class Vec2 {
|
public class Vec2 implements Serializable {
|
||||||
public int x, y;
|
public int x, y;
|
||||||
|
|
||||||
public Vec2() {
|
public Vec2() {
|
||||||
@ -16,4 +18,22 @@ public class Vec2 {
|
|||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof Vec2) {
|
||||||
|
Vec2 vec = (Vec2) obj;
|
||||||
|
return this.x == vec.x && this.y == vec.y;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2 add(Vec2 o){
|
||||||
|
return new Vec2(x + o.x, y + o.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "("+x+","+y+")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 237 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
After Width: | Height: | Size: 423 KiB |
@ -0,0 +1,11 @@
|
|||||||
|
.BorderPane{
|
||||||
|
-fx-background-image: url("BackGround-menu.jpg");
|
||||||
|
-fx-background-position:center;
|
||||||
|
}
|
||||||
|
.GridPane{
|
||||||
|
-fx-background-image: url("Background-select-level.jpg");
|
||||||
|
-fx-background-position:right;
|
||||||
|
}
|
||||||
|
.StackPane{
|
||||||
|
-fx-background-image: url("BackGround-LvlFinish.jpg");
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
SMSààSME
|
@ -0,0 +1 @@
|
|||||||
|
SMS<04><>"<22>"<22>"p1<70>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSη<><CEB7>€3<>€"π"°"p"°€SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿ€"°1àà2ü"p3í€SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS?ÿÿýðà"°3í€à"ð2ü3í€SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSfÿÿŸ< 1à"°"p€&ÿð"ð"ð"°àSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿð"°1à€"p#üÀ!ÀSME
|
@ -0,0 +1 @@
|
|||||||
|
SMS˙˙˙€"đŕ€"p3í€3o€SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿÿð3ÿ€3í€1à1à#ü#üSME
|
BIN
app/src/main/resources/school_project/levels/level18.level
Normal file
BIN
app/src/main/resources/school_project/levels/level18.level
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
SMSó˙˙óŕŕ3ü€3o€4đ"°SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSà1àSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿ€À3í€"ð2ø3ü€SME
|
BIN
app/src/main/resources/school_project/levels/level21.level
Normal file
BIN
app/src/main/resources/school_project/levels/level21.level
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿ€"pàÀ"°#ü#è#èSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿ€2Üà"Ð#è#¼BSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSv˙˙€#쀀#ě#ĽBSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿÿð#¼#|!À#\#ü2ô2äBSME
|
BIN
app/src/main/resources/school_project/levels/level26.level
Normal file
BIN
app/src/main/resources/school_project/levels/level26.level
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿÿð#ø#´!À!À#¼4ð3o€SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS<07><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<>B#|3?<3F>3<EFBFBD><33>#<23>&<26><>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSy<><79>y<EFBFBD>B<>!<21>B<EFBFBD>$<24>#<23>#<23>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS<03><>#<23><13>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS<07><><EFBFBD>}<7D>߀$<24>3ۀ2<DB80><11><11>"<22>2x"p2<70>"<22>2<EFBFBD>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS<04><>#<23>#<23><11>1<EFBFBD>SME
|
@ -0,0 +1 @@
|
|||||||
|
SMS÷p€€1à#ü#üSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿ3ÿ€à1àSME
|
@ -0,0 +1 @@
|
|||||||
|
SMS3ÿ2üà"°SME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿÿ€2ü"°"°"p1à€1à"pSME
|
@ -0,0 +1 @@
|
|||||||
|
SMSÿÿ߀1à1à3ÿ€#ü"°SME
|
BIN
app/src/main/resources/school_project/tile.png
Normal file
BIN
app/src/main/resources/school_project/tile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
26
app/src/test/java/school_project/MapGeneratorTest.java
Normal file
26
app/src/test/java/school_project/MapGeneratorTest.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package school_project;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class MapGeneratorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void generate() {
|
||||||
|
Map[] maps = new Map[] {
|
||||||
|
MapGenerator.generate(MapGenerator.Difficulty.Easy),
|
||||||
|
MapGenerator.generate(MapGenerator.Difficulty.Medium),
|
||||||
|
MapGenerator.generate(MapGenerator.Difficulty.Difficult),
|
||||||
|
};
|
||||||
|
|
||||||
|
for(Map m: maps){
|
||||||
|
System.out.println("==========");
|
||||||
|
System.out.println(m);
|
||||||
|
System.out.println("++++++++++++++++++++");
|
||||||
|
for (Piece p: m.getPieces()){
|
||||||
|
System.out.println(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
177
app/src/test/java/school_project/Parsers/BinaryParserTest.java
Normal file
177
app/src/test/java/school_project/Parsers/BinaryParserTest.java
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import school_project.Map;
|
||||||
|
import school_project.Piece;
|
||||||
|
import school_project.Vec2;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BinaryParserTest {
|
||||||
|
|
||||||
|
static byte[] file_data = {
|
||||||
|
'S', 'M', 'S',
|
||||||
|
6, 5, (byte) 0x31, (byte) 0xEC, (byte) 0xF3, (byte) 0xFC,
|
||||||
|
4,
|
||||||
|
(byte) 0x22, (byte) 0x70,
|
||||||
|
(byte) 0x33, (byte) 0x99, (byte) 0x80,
|
||||||
|
(byte) 0x32, (byte) 0x7C,
|
||||||
|
(byte) 0x33, (byte) 0xDB, (byte) 0x80,
|
||||||
|
'S', 'M', 'E'
|
||||||
|
};
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getByteSizeForMap() {
|
||||||
|
boolean[][] map_shape = {
|
||||||
|
{ true, true, true },
|
||||||
|
{ true, false, true },
|
||||||
|
{ true, true, true },
|
||||||
|
|
||||||
|
};
|
||||||
|
boolean[][] piece1_shape = {
|
||||||
|
{ true, true },
|
||||||
|
{ true, false },
|
||||||
|
{ true, true },
|
||||||
|
|
||||||
|
};
|
||||||
|
boolean[][] piece2_shape = {
|
||||||
|
{ true },
|
||||||
|
{ true },
|
||||||
|
{ true },
|
||||||
|
|
||||||
|
};
|
||||||
|
Map map = new Map(map_shape);
|
||||||
|
Piece piece1 = new Piece(piece1_shape);
|
||||||
|
Piece piece2 = new Piece(piece2_shape);
|
||||||
|
|
||||||
|
map.addPiece(new Piece[]{piece1, piece2});
|
||||||
|
piece2.setPosition(new Vec2(0, 2));
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(15, BinaryParser.getByteSizeForMap(map, false));
|
||||||
|
assertEquals(19, BinaryParser.getByteSizeForMap(map, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildByteFromMatrix(){
|
||||||
|
byte[] map_data = Arrays.copyOfRange(file_data, 5, 9);
|
||||||
|
boolean[][] map_shape = {
|
||||||
|
{false, false, true, true, false, false},
|
||||||
|
{false, true, true, true, true, false},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, true, true, true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(map_data, BinaryParser.BuildByteFromMatrix(map_shape));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildMatrixFromByte_map(){
|
||||||
|
byte[] map_data = Arrays.copyOfRange(file_data, 5, 9);
|
||||||
|
boolean[][] map_shape = {
|
||||||
|
{false, false, true, true, false, false},
|
||||||
|
{false, true, true, true, true, false},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, true, true, true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(map_shape, BinaryParser.BuildMatrixFromBytes(6, 5, map_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildMatrixFromByte_piece1(){
|
||||||
|
byte[] piece1_data = Arrays.copyOfRange(file_data, 11, 12);
|
||||||
|
boolean[][] piece1_shape = {
|
||||||
|
{false, true},
|
||||||
|
{true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(piece1_shape, BinaryParser.BuildMatrixFromBytes(2, 2, piece1_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildMatrixFromByte_piece2(){
|
||||||
|
byte[] piece2_data = Arrays.copyOfRange(file_data, 13, 15);
|
||||||
|
boolean[][] piece2_shape = {
|
||||||
|
{true, false, false},
|
||||||
|
{true, true, false},
|
||||||
|
{false, true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(piece2_shape, BinaryParser.BuildMatrixFromBytes(3, 3, piece2_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildMatrixFromByte_piece3(){
|
||||||
|
byte[] piece3_data = Arrays.copyOfRange(file_data, 16, 17);
|
||||||
|
boolean[][] piece3_shape = {
|
||||||
|
{false, true, true},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(piece3_shape, BinaryParser.BuildMatrixFromBytes(3, 2, piece3_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void BuildMatrixFromByte_piece4(){
|
||||||
|
byte[] piece4_data = Arrays.copyOfRange(file_data, 18, 20);
|
||||||
|
boolean[][] piece4_shape = {
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
assertArrayEquals(piece4_shape, BinaryParser.BuildMatrixFromBytes(3, 3, piece4_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void ExtractLevelData() throws IOException {
|
||||||
|
boolean[][] expected_map_shape = {
|
||||||
|
{false, false, true, true, false, false},
|
||||||
|
{false, true, true, true, true, false},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, true, true, true, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] level_data = BinaryParser.ExtractLevelData(new ByteArrayInputStream(file_data));
|
||||||
|
boolean[][] map = BinaryParser.ExtractMapFromLevelData(level_data);
|
||||||
|
|
||||||
|
assertArrayEquals(expected_map_shape, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void ExtractPiecesFronLevelDataTest() throws IOException {
|
||||||
|
boolean[][] piece1_shape = {
|
||||||
|
{false, true},
|
||||||
|
{true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece2_shape = {
|
||||||
|
{true, false, false},
|
||||||
|
{true, true, false},
|
||||||
|
{false, true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece3_shape = {
|
||||||
|
{false, true, true},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece4_shape = {
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
boolean[][][] pieces_shapes = {
|
||||||
|
piece1_shape,
|
||||||
|
piece2_shape,
|
||||||
|
piece3_shape,
|
||||||
|
piece4_shape
|
||||||
|
};
|
||||||
|
byte[] level_data = BinaryParser.ExtractLevelData(new ByteArrayInputStream(file_data));
|
||||||
|
Piece[] pieces = BinaryParser.ExtractPiecesFromLevelData(level_data, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < pieces_shapes.length; i++) {
|
||||||
|
assertArrayEquals(pieces_shapes[i], pieces[i].getShape());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package school_project.Parsers;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import school_project.Map;
|
||||||
|
import school_project.Piece;
|
||||||
|
import school_project.Vec2;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class FileParserFactoryTest {
|
||||||
|
|
||||||
|
static Map generateMapTest(){
|
||||||
|
boolean[][] map_shape = {
|
||||||
|
{false, false, true, true, false, false},
|
||||||
|
{false, true, true, true, true, false},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, false, false, true, true},
|
||||||
|
{true, true, true, true, true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece1_shape = {
|
||||||
|
{false, true},
|
||||||
|
{true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece2_shape = {
|
||||||
|
{true, false, false},
|
||||||
|
{true, true, false},
|
||||||
|
{false, true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece3_shape = {
|
||||||
|
{false, true, true},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
boolean[][] piece4_shape = {
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, false},
|
||||||
|
{true, true, true},
|
||||||
|
};
|
||||||
|
Piece[] pieces = { new Piece(piece1_shape), new Piece(piece2_shape), new Piece(piece3_shape), new Piece(piece4_shape) };
|
||||||
|
Map map = new Map(map_shape);
|
||||||
|
map.addPiece(pieces);
|
||||||
|
|
||||||
|
pieces[0].setPosition(new Vec2(1, 0));
|
||||||
|
pieces[1].setPosition(new Vec2(3, 0));
|
||||||
|
pieces[2].setPosition(new Vec2(3, 3));
|
||||||
|
pieces[3].setPosition(new Vec2(0, 2));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveLoadFileFromMap_Binary(@TempDir Path tmpFolder) throws IOException {
|
||||||
|
Map map = generateMapTest();
|
||||||
|
FileParserFactory.saveFileFromMap(tmpFolder.resolve("TestBinaryLevel.level").toFile(), map);
|
||||||
|
|
||||||
|
Map testMap = FileParserFactory.loadMapFromFile(tmpFolder.resolve("TestBinaryLevel.level").toFile());
|
||||||
|
assertArrayEquals(map.getCleanedMap().getShape(), testMap.getShape());
|
||||||
|
for (int i = 0; i < map.getPieces().size(); i++) {
|
||||||
|
assertArrayEquals(map.getPieces().get(i).getShape(), testMap.getPieces().get(i).getShape());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveLoadFileFromMap_save_Binary(@TempDir Path tmpFolder) throws IOException {
|
||||||
|
Map map = generateMapTest();
|
||||||
|
FileParserFactory.saveFileFromMap(tmpFolder.resolve("TestBinarySave.slevel").toFile(), map);
|
||||||
|
|
||||||
|
Map testMap = FileParserFactory.loadMapFromFile(tmpFolder.resolve("TestBinarySave.slevel").toFile());
|
||||||
|
assertArrayEquals(map.getShape(), testMap.getShape());
|
||||||
|
for (int i = 0; i < map.getPieces().size(); i++) {
|
||||||
|
assertArrayEquals(map.getPieces().get(i).getShape(), testMap.getPieces().get(i).getShape());
|
||||||
|
assertEquals(map.getPieces().get(i).getPosition(), testMap.getPieces().get(i).getPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void saveLoadFileFromMap_Serialized(@TempDir Path tmpFolder) throws IOException {
|
||||||
|
Map map = generateMapTest();
|
||||||
|
FileParserFactory.saveFileFromMap( tmpFolder.resolve("TestSerializedLevel.serialized").toFile(), map);
|
||||||
|
|
||||||
|
Map testMap = FileParserFactory.loadMapFromFile( tmpFolder.resolve("TestSerializedLevel.serialized").toFile());
|
||||||
|
assertArrayEquals(map.getShape(), testMap.getShape());
|
||||||
|
for (int i = 0; i < map.getPieces().size(); i++) {
|
||||||
|
assertArrayEquals(map.getPieces().get(i).getShape(), testMap.getPieces().get(i).getShape());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveLoadFileFromMap_save_Serialized(@TempDir Path tmpFolder) throws IOException{
|
||||||
|
Map map = generateMapTest();
|
||||||
|
FileParserFactory.saveFileFromMap(tmpFolder.resolve("TestSerializedSave.sserialized").toFile(), map);
|
||||||
|
|
||||||
|
Map testMap = FileParserFactory.loadMapFromFile(tmpFolder.resolve("TestSerializedSave.sserialized").toFile());
|
||||||
|
assertArrayEquals(map.getShape(), testMap.getShape());
|
||||||
|
for (int i = 0; i < map.getPieces().size(); i++) {
|
||||||
|
assertArrayEquals(map.getPieces().get(i).getShape(), testMap.getPieces().get(i).getShape());
|
||||||
|
assertEquals(map.getPieces().get(i).getPosition(), testMap.getPieces().get(i).getPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,6 @@ class PieceTest {
|
|||||||
boolean[][] piece1_matrix_result = {
|
boolean[][] piece1_matrix_result = {
|
||||||
{true, false, true},
|
{true, false, true},
|
||||||
{true, true, false},
|
{true, true, false},
|
||||||
{false, false, false},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
boolean[][] piece2_matrix = {
|
boolean[][] piece2_matrix = {
|
||||||
@ -31,12 +30,11 @@ class PieceTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
boolean[][] piece3_matrix_result = {
|
boolean[][] piece3_matrix_result = {
|
||||||
{false, false, false},
|
|
||||||
{false, true, true},
|
{false, true, true},
|
||||||
{true, false, true},
|
{true, false, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
Piece piece1 = new Piece();
|
Piece piece1 = new Piece(piece2_matrix);
|
||||||
piece1.setShape(piece1_matrix);
|
piece1.setShape(piece1_matrix);
|
||||||
|
|
||||||
Piece piece2 = new Piece(piece2_matrix);
|
Piece piece2 = new Piece(piece2_matrix);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package school_project;
|
package school_project;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import school_project.Utils.Array;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
@ -29,6 +32,30 @@ class ShapeTest {
|
|||||||
{true}
|
{true}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boolean[][] matrix_shape5 = {
|
||||||
|
{false, false, false, false, false},
|
||||||
|
{false, false, false, false, false},
|
||||||
|
{false, true, true, true, false},
|
||||||
|
{false, true, false, true, false},
|
||||||
|
{false, false, false, false, false},
|
||||||
|
{false, false, false, false, false},
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[][] matrix_shape5_result = {
|
||||||
|
{true, true, true},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[][] matrix_shape6 = {
|
||||||
|
{true, false},
|
||||||
|
{false, false}
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[][] matrix_shape6_result = {
|
||||||
|
{true},
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println(Array.isRowOnlyFalse(matrix_shape1, 0));
|
||||||
Shape shape1 = new Shape();
|
Shape shape1 = new Shape();
|
||||||
shape1.setShape(matrix_shape1);
|
shape1.setShape(matrix_shape1);
|
||||||
assertEquals(3, shape1.getHeight());
|
assertEquals(3, shape1.getHeight());
|
||||||
@ -44,5 +71,11 @@ class ShapeTest {
|
|||||||
assertEquals(3, shape4.getHeight());
|
assertEquals(3, shape4.getHeight());
|
||||||
assertEquals(1, shape4.getWidth());
|
assertEquals(1, shape4.getWidth());
|
||||||
|
|
||||||
|
Shape shape5 = new Shape(matrix_shape5);
|
||||||
|
assertArrayEquals(matrix_shape5_result, shape5.getShape());
|
||||||
|
|
||||||
|
Shape shape6 = new Shape(matrix_shape6);
|
||||||
|
assertArrayEquals(matrix_shape6_result, shape6.getShape());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
81
app/src/test/java/school_project/Utils/ArrayTest.java
Normal file
81
app/src/test/java/school_project/Utils/ArrayTest.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package school_project.Utils;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ArrayTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matrixCopyOf() {
|
||||||
|
boolean[][] a = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
boolean[][] b = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
boolean[][] c = Array.MatrixCopyOf(a);
|
||||||
|
assertArrayEquals(a, c);
|
||||||
|
a[1][1] = true;
|
||||||
|
assertArrayEquals(b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matrixRemoveRow() {
|
||||||
|
boolean[][] a = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
boolean[][] b = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[][] result = Array.MatrixRemoveRow(a, 1);
|
||||||
|
assertArrayEquals(b, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matrixRemoveColumn() {
|
||||||
|
boolean[][] a = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
boolean[][] b = new boolean[][] {
|
||||||
|
{true, true},
|
||||||
|
{false, false},
|
||||||
|
{true, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[][] result = Array.MatrixRemoveColumn(a, 1);
|
||||||
|
assertArrayEquals(b, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isRowOnlyFalse() {
|
||||||
|
boolean[][] a = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
assertTrue(Array.isRowOnlyFalse(a, 1));
|
||||||
|
assertFalse(Array.isRowOnlyFalse(a, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isColumnOnlyFalse() {
|
||||||
|
boolean[][] a = new boolean[][] {
|
||||||
|
{true, false, true},
|
||||||
|
{false, false, false},
|
||||||
|
{true, false, true},
|
||||||
|
};
|
||||||
|
assertTrue(Array.isColumnOnlyFalse(a, 1));
|
||||||
|
assertFalse(Array.isColumnOnlyFalse(a, 0));
|
||||||
|
}
|
||||||
|
}
|
BIN
prototypes/interface-menu/BackGround-menu.jpg
Normal file
BIN
prototypes/interface-menu/BackGround-menu.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
@ -1,38 +0,0 @@
|
|||||||
target/
|
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
|
||||||
!**/src/main/**/target/
|
|
||||||
!**/src/test/**/target/
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea/modules.xml
|
|
||||||
.idea/jarRepositories.xml
|
|
||||||
.idea/compiler.xml
|
|
||||||
.idea/libraries/
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
|
|
||||||
### Eclipse ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
build/
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
### Mac OS ###
|
|
||||||
.DS_Store
|
|
Binary file not shown.
@ -1,2 +0,0 @@
|
|||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
|
|
||||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
|
@ -1,316 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
# or more contributor license agreements. See the NOTICE file
|
|
||||||
# distributed with this work for additional information
|
|
||||||
# regarding copyright ownership. The ASF licenses this file
|
|
||||||
# to you under the Apache License, Version 2.0 (the
|
|
||||||
# "License"); you may not use this file except in compliance
|
|
||||||
# with the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing,
|
|
||||||
# software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
# KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Maven Start Up Batch script
|
|
||||||
#
|
|
||||||
# Required ENV vars:
|
|
||||||
# ------------------
|
|
||||||
# JAVA_HOME - location of a JDK home dir
|
|
||||||
#
|
|
||||||
# Optional ENV vars
|
|
||||||
# -----------------
|
|
||||||
# M2_HOME - location of maven2's installed home dir
|
|
||||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
# e.g. to debug Maven itself, use
|
|
||||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
|
||||||
|
|
||||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
|
||||||
. /usr/local/etc/mavenrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f /etc/mavenrc ] ; then
|
|
||||||
. /etc/mavenrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$HOME/.mavenrc" ] ; then
|
|
||||||
. "$HOME/.mavenrc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific support. $var _must_ be set to either true or false.
|
|
||||||
cygwin=false;
|
|
||||||
darwin=false;
|
|
||||||
mingw=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN*) cygwin=true ;;
|
|
||||||
MINGW*) mingw=true;;
|
|
||||||
Darwin*) darwin=true
|
|
||||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
|
||||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
if [ -x "/usr/libexec/java_home" ]; then
|
|
||||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
|
||||||
else
|
|
||||||
export JAVA_HOME="/Library/Java/Home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
if [ -r /etc/gentoo-release ] ; then
|
|
||||||
JAVA_HOME=`java-config --jre-home`
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$M2_HOME" ] ; then
|
|
||||||
## resolve links - $0 may be a link to maven's home
|
|
||||||
PRG="$0"
|
|
||||||
|
|
||||||
# need this for relative symlinks
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG="`dirname "$PRG"`/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
saveddir=`pwd`
|
|
||||||
|
|
||||||
M2_HOME=`dirname "$PRG"`/..
|
|
||||||
|
|
||||||
# make it fully qualified
|
|
||||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
|
||||||
|
|
||||||
cd "$saveddir"
|
|
||||||
# echo Using m2 at $M2_HOME
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $mingw ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
javaExecutable="`which javac`"
|
|
||||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
|
||||||
# readlink(1) is not available as standard on Solaris 10.
|
|
||||||
readLink=`which readlink`
|
|
||||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
|
||||||
if $darwin ; then
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
|
||||||
else
|
|
||||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
|
||||||
fi
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
|
||||||
JAVA_HOME="$javaHome"
|
|
||||||
export JAVA_HOME
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVACMD" ] ; then
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="`\\unset -f command; \\command -v java`"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
|
||||||
echo " We cannot execute $JAVACMD" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
echo "Warning: JAVA_HOME environment variable is not set."
|
|
||||||
fi
|
|
||||||
|
|
||||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
|
||||||
|
|
||||||
# traverses directory structure from process work directory to filesystem root
|
|
||||||
# first directory with .mvn subdirectory is considered project base directory
|
|
||||||
find_maven_basedir() {
|
|
||||||
|
|
||||||
if [ -z "$1" ]
|
|
||||||
then
|
|
||||||
echo "Path not specified to find_maven_basedir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
basedir="$1"
|
|
||||||
wdir="$1"
|
|
||||||
while [ "$wdir" != '/' ] ; do
|
|
||||||
if [ -d "$wdir"/.mvn ] ; then
|
|
||||||
basedir=$wdir
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
|
||||||
if [ -d "${wdir}" ]; then
|
|
||||||
wdir=`cd "$wdir/.."; pwd`
|
|
||||||
fi
|
|
||||||
# end of workaround
|
|
||||||
done
|
|
||||||
echo "${basedir}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# concatenates all lines of a file
|
|
||||||
concat_lines() {
|
|
||||||
if [ -f "$1" ]; then
|
|
||||||
echo "$(tr -s '\n' ' ' < "$1")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
|
||||||
if [ -z "$BASE_DIR" ]; then
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
##########################################################################################
|
|
||||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
##########################################################################################
|
|
||||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
|
||||||
fi
|
|
||||||
if [ -n "$MVNW_REPOURL" ]; then
|
|
||||||
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
|
||||||
else
|
|
||||||
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
|
||||||
fi
|
|
||||||
while IFS="=" read key value; do
|
|
||||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
|
||||||
esac
|
|
||||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Downloading from: $jarUrl"
|
|
||||||
fi
|
|
||||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
|
||||||
if $cygwin; then
|
|
||||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v wget > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found wget ... using wget"
|
|
||||||
fi
|
|
||||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
|
||||||
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
|
||||||
else
|
|
||||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
|
||||||
fi
|
|
||||||
elif command -v curl > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found curl ... using curl"
|
|
||||||
fi
|
|
||||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
|
||||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
|
||||||
else
|
|
||||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Falling back to using Java to download"
|
|
||||||
fi
|
|
||||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
|
||||||
# For Cygwin, switch paths to Windows format before running javac
|
|
||||||
if $cygwin; then
|
|
||||||
javaClass=`cygpath --path --windows "$javaClass"`
|
|
||||||
fi
|
|
||||||
if [ -e "$javaClass" ]; then
|
|
||||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
# Compiling the Java class
|
|
||||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
|
||||||
fi
|
|
||||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
# Running the downloader
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Running MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
##########################################################################################
|
|
||||||
# End of extension
|
|
||||||
##########################################################################################
|
|
||||||
|
|
||||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo $MAVEN_PROJECTBASEDIR
|
|
||||||
fi
|
|
||||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
|
||||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
|
||||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Provide a "standardized" way to retrieve the CLI args that will
|
|
||||||
# work with both Windows and non-Windows executions.
|
|
||||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
|
||||||
export MAVEN_CMD_LINE_ARGS
|
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
|
||||||
$MAVEN_OPTS \
|
|
||||||
$MAVEN_DEBUG_OPTS \
|
|
||||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
|
||||||
"-Dmaven.home=${M2_HOME}" \
|
|
||||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
|
||||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -1,188 +0,0 @@
|
|||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
@REM or more contributor license agreements. See the NOTICE file
|
|
||||||
@REM distributed with this work for additional information
|
|
||||||
@REM regarding copyright ownership. The ASF licenses this file
|
|
||||||
@REM to you under the Apache License, Version 2.0 (the
|
|
||||||
@REM "License"); you may not use this file except in compliance
|
|
||||||
@REM with the License. You may obtain a copy of the License at
|
|
||||||
@REM
|
|
||||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@REM
|
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
|
||||||
@REM software distributed under the License is distributed on an
|
|
||||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
@REM KIND, either express or implied. See the License for the
|
|
||||||
@REM specific language governing permissions and limitations
|
|
||||||
@REM under the License.
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Maven Start Up Batch script
|
|
||||||
@REM
|
|
||||||
@REM Required ENV vars:
|
|
||||||
@REM JAVA_HOME - location of a JDK home dir
|
|
||||||
@REM
|
|
||||||
@REM Optional ENV vars
|
|
||||||
@REM M2_HOME - location of maven2's installed home dir
|
|
||||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
|
||||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
|
||||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
@REM e.g. to debug Maven itself, use
|
|
||||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
|
||||||
@echo off
|
|
||||||
@REM set title of command window
|
|
||||||
title %0
|
|
||||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
|
||||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
|
||||||
|
|
||||||
@REM set %HOME% to equivalent of $HOME
|
|
||||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
|
||||||
|
|
||||||
@REM Execute a user defined script before this one
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
|
||||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
|
||||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
|
||||||
:skipRcPre
|
|
||||||
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
set ERROR_CODE=0
|
|
||||||
|
|
||||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
@REM ==== START VALIDATION ====
|
|
||||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME not found in your environment. >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
:OkJHome
|
|
||||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
|
||||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
@REM ==== END VALIDATION ====
|
|
||||||
|
|
||||||
:init
|
|
||||||
|
|
||||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
|
||||||
@REM Fallback to current working directory if not found.
|
|
||||||
|
|
||||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
|
||||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
|
||||||
|
|
||||||
set EXEC_DIR=%CD%
|
|
||||||
set WDIR=%EXEC_DIR%
|
|
||||||
:findBaseDir
|
|
||||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
|
||||||
cd ..
|
|
||||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
|
||||||
set WDIR=%CD%
|
|
||||||
goto findBaseDir
|
|
||||||
|
|
||||||
:baseDirFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
goto endDetectBaseDir
|
|
||||||
|
|
||||||
:baseDirNotFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
|
|
||||||
:endDetectBaseDir
|
|
||||||
|
|
||||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
|
||||||
|
|
||||||
@setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
|
||||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
|
||||||
|
|
||||||
:endReadAdditionalConfig
|
|
||||||
|
|
||||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
|
||||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
|
||||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
|
||||||
|
|
||||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
|
||||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
|
||||||
)
|
|
||||||
|
|
||||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
if exist %WRAPPER_JAR% (
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Found %WRAPPER_JAR%
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
if not "%MVNW_REPOURL%" == "" (
|
|
||||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
|
||||||
)
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
|
||||||
echo Downloading from: %DOWNLOAD_URL%
|
|
||||||
)
|
|
||||||
|
|
||||||
powershell -Command "&{"^
|
|
||||||
"$webclient = new-object System.Net.WebClient;"^
|
|
||||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
|
||||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
|
||||||
"}"^
|
|
||||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
|
||||||
"}"
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Finished downloading %WRAPPER_JAR%
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@REM End of extension
|
|
||||||
|
|
||||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
|
||||||
@REM work with both Windows and non-Windows executions.
|
|
||||||
set MAVEN_CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
%MAVEN_JAVA_EXE% ^
|
|
||||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
|
||||||
%MAVEN_OPTS% ^
|
|
||||||
%MAVEN_DEBUG_OPTS% ^
|
|
||||||
-classpath %WRAPPER_JAR% ^
|
|
||||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
|
||||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
|
||||||
if ERRORLEVEL 1 goto error
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:error
|
|
||||||
set ERROR_CODE=1
|
|
||||||
|
|
||||||
:end
|
|
||||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
|
||||||
|
|
||||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
|
||||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
|
||||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
|
||||||
:skipRcPost
|
|
||||||
|
|
||||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
|
||||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
|
||||||
|
|
||||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
|
||||||
|
|
||||||
cmd /C exit /B %ERROR_CODE%
|
|
@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>menu_road_to_masterU</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
<name>menu_road_to_masterU</name>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<junit.version>5.9.1</junit.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjfx</groupId>
|
|
||||||
<artifactId>javafx-controls</artifactId>
|
|
||||||
<version>17.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjfx</groupId>
|
|
||||||
<artifactId>javafx-fxml</artifactId>
|
|
||||||
<version>17.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.10.1</version>
|
|
||||||
<configuration>
|
|
||||||
<source>17</source>
|
|
||||||
<target>17</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.openjfx</groupId>
|
|
||||||
<artifactId>javafx-maven-plugin</artifactId>
|
|
||||||
<version>0.0.8</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<!-- Default configuration for running with: mvn clean javafx:run -->
|
|
||||||
<id>default-cli</id>
|
|
||||||
<configuration>
|
|
||||||
<mainClass>
|
|
||||||
com.example.menu_road_to_masteru/com.example.menu_road_to_masteru.HelloApplication
|
|
||||||
</mainClass>
|
|
||||||
<launcher>app</launcher>
|
|
||||||
<jlinkZipName>app</jlinkZipName>
|
|
||||||
<jlinkImageName>app</jlinkImageName>
|
|
||||||
<noManPages>true</noManPages>
|
|
||||||
<stripDebug>true</stripDebug>
|
|
||||||
<noHeaderFiles>true</noHeaderFiles>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.example.menu_road_to_masteru;
|
|
||||||
|
|
||||||
import javafx.application.Application;
|
|
||||||
import javafx.fxml.FXMLLoader;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class HelloApplication extends Application {
|
|
||||||
@Override
|
|
||||||
public void start(Stage stage) throws IOException {
|
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
|
|
||||||
Scene scene = new Scene(fxmlLoader.load());
|
|
||||||
stage.setTitle("Welcome to Road to masterU");
|
|
||||||
scene.getStylesheets().add("menu.css");
|
|
||||||
stage.setHeight(700);
|
|
||||||
stage.setWidth((1000));
|
|
||||||
stage.setResizable(false);
|
|
||||||
stage.setFullScreen(true);
|
|
||||||
stage.setFullScreenExitHint("");
|
|
||||||
stage.setScene(scene);
|
|
||||||
stage.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
launch();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package com.example.menu_road_to_masteru;
|
|
||||||
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
|
|
||||||
public class HelloController {
|
|
||||||
@FXML
|
|
||||||
private Label welcomeText;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
protected void onHelloButtonClick() {
|
|
||||||
welcomeText.setText("Welcome to JavaFX Application!");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
module com.example.menu_road_to_masteru {
|
|
||||||
requires javafx.controls;
|
|
||||||
requires javafx.fxml;
|
|
||||||
|
|
||||||
|
|
||||||
opens com.example.menu_road_to_masteru to javafx.fxml;
|
|
||||||
exports com.example.menu_road_to_masteru;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import javafx.scene.control.Label?>
|
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.text.Font?>
|
|
||||||
|
|
||||||
|
|
||||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<children>
|
|
||||||
<Button fx:id="PlaySelect" layoutX="251.0" layoutY="200.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="94.0" text="Play" />
|
|
||||||
<Button fx:id="LevelSelect" layoutX="224.0" layoutY="263.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="147.0" text="Select level" />
|
|
||||||
<Label fx:id="titlegame" layoutY="88.0" prefHeight="30.0" prefWidth="600.0" text="Road to MasterU">
|
|
||||||
<font>
|
|
||||||
<Font size="20.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Button fx:id="TrophyOption" layoutX="492.0" layoutY="361.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="94.0" text="Trophy" />
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
@ -1,13 +0,0 @@
|
|||||||
.root{
|
|
||||||
-fx-background-image:url("BackGround-menu.jpg");
|
|
||||||
-fx-background-position:center;
|
|
||||||
}
|
|
||||||
.label{
|
|
||||||
-fx-font-size: 75;
|
|
||||||
-fx-text-fill: gold;
|
|
||||||
-fx-alignment: center;
|
|
||||||
-fx-underline: on;
|
|
||||||
}
|
|
||||||
.button{
|
|
||||||
-fx-start-margin: 20;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user