diff --git a/.gitignore b/.gitignore index 5217bcf..0dacc34 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ img.png image.png /maps/ /assets/ +lib/ out/ +project/ +target/ TheGame.jar diff --git a/README.md b/README.md index 977d1b7..b8b23e0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ --- title: Projet programmation 2 -author: Yohann D'ANELLO +author: Yohann D'ANELLO, Édouard Némery --- # The Game @@ -30,7 +30,7 @@ Une tour contient également diverses propriétés : * Des dégâts par tir * Une vitesse de tir * Un prix -* Une fonction permettant de récupérer les mobs sur lesquels tirer +* Une fonction indiquant ce qu'il se passe lorsque la tour tire Le jeu fonctionne par tick. Toutes les 50 millisecondes a lieu un tick. Toutes les tours sont mises à jour, puis les mobs se déplacent éventuellement. La vitesse des tours et des mobs influe sur le fait de faire quelque chose pendant le @@ -43,6 +43,122 @@ Si un mob doit se déplacer, un chemin est calculé jusqu'au bord de la fenêtre de collisions est en effet géré, empêchant 2 mobs ou tours de se trouver au même endroit. Si un tel chemin existe, alors le mob avance d'une case selon ce chemin. Sinon, il reste sur place. +### Différents mobs + +Il existe différents types de mobs. Ils contiennent 3 propriétés : points de vie (dégâts nécessaires pour être tués), +lenteur (nombre de ticks de jeu nécessaires à déclencher un tick chez le mob), butin (nombre de pièces ramassé par +le joueur lorsque le mob est tué). + +À chaque tick de mob, une fonction de tick spécifique au mob est appelée, qui permet des actions supplémentaires. + +Les mobs peuvent être gelés, si tel est le cas le nombre de ticks d'attente est multiplié par 2. Par ailleurs, un facteur +aléatoire compris entre 0.95 et 1.05 est appliqué. + +#### Mob1 + +Ne fait rien de spécial. + +* Points de vie : 2 +* Lenteur : 50 +* Butin : 10 + +#### Mob2 + +Ne fait rien de spécial. + +* Points de vie : 6 +* Lenteur : 20 +* Butin : 20 + +#### MobStrong + +Ne fait rien de spécial. + +* Points de vie : 50 +* Lenteur : 100 +* Butin : 100 + +#### MobHealer + +Soigne de 2 points de vie à chacun de ses ticks tous les mobs à 3 blocs à la ronde, à l'exception de lui-même. + +* Points de vie : 20 +* Lenteur : 60 +* Butin : 20 + +#### MobSpeeder + +Accélère d'un facteur 3 les ticks des mobs à 3 blocs à la ronde, à l'exception de lui-même. + +* Point de vie : 25 +* Lenteur : 60 +* Butin : 30 + +#### MobBreaker + +Casse les tours sur son passage (à tuer à distance) + +* Points de vie : 110 +* Lenteur : 120 +* Butin : 70 + +### Différentes tours + +Différentes tours sont à la disposition du joueur, avec des prix différents (rendant toutes les tours non accessibles +au début du jeu). Elles ont toutes un nombre de dégât indicatif, un nombre de ticks à attendre entre 2 tirs, et si +elle est améliorée ou non (voir UpgradeTower). Elles disposent aussi d'une fonction `shot` précisant l'action de la tour +à chaque tir. + +#### BasicTower + +Cette tour tire sur une unique cible aléatoire à 3 blocs à la ronde. + +* Période : 5 +* Prix : 10 +* Dégâts : 1 (3 si améliorée) + +#### WallTower + +Cette tour ne fait rien, agit uniquement comme un mur empêchant les mobs de passer par là. + +* Période : +infini +* Prix : 5 +* Dégâts : 0 + +#### FreezeTower + +Cette tour ne faît aucun dégât et gêle pendant 40 ticks (2 secondes), 100 ticks (5 secondes) si améliorée, tous les mobs +à 3 blocs à la ronde. + +* Période : 10 +* Prix : 40 +* Dégâts : 0 (1 si améliorée) + +#### ExploderTower + +Cette tour lance des projectiles explosifs, qui inflige le double des dégâts à la cible ainsi que des dégâts aux mobs +présents à 3 blocs à la ronde de ce mob. La portée est de 5 blocs. + +* Période : 20 +* Prix : 70 +* Dégâts : 3 (7 si améliorée) + +#### UpgradeTower + +Cette tour améliore de façon permanente toutes les tours à 5 blocs à la ronde (sauf elle-même). + +* Période : 60 +* Prix : 65 +* Dégâts : 0 (1 si améliorée) + +#### LaserTower + +Cette tour tire des rayons laser dans les quatre directions et chaque mob reçoit des dégâts. + +* Période : 40 +* Prix : 80 +* Dégâts : 3 (8 si améliorée) + ## Implémentation Le projet est intégralement fait en Java. On ne détaillera pas ici la partie éditeur de niveau, bien qu'elle soit @@ -67,10 +183,10 @@ Une case est une position et 3 sprites (couche 1, couche 2, couche 3). Un sprite est une image de taille 16x16, qui contient des informations sur l'endroit où le chercher. Un Mob est une classe abstraite contenant des informations abstraites (détaillées plus haut). Un type de mob sera donc -une classe héritant de `Mob`, telles que `Mob1`, `Mob2` et `MobCancer`. +une classe héritant de `Mob`. -Il en est de même pour les tours, avec `BasicTower`, `NullTower` et `AutoTower`. +Il en est de même pour les tours, qui hérite de `Tower`. L'intérêt de l'héritage par rapport à un type donné à une classe Mob (paramètres donnés dans une enumération `MobType` -par exemple) est de pouvoir mieux personnaliser les fonctions, par exemple en imaginant des dégâts aléatoires. +par exemple) est de pouvoir mieux personnaliser les fonctions, par exemple en intégrant les dégâts aléatoires. diff --git a/README.pdf b/README.pdf index 109e9e2..3640db0 100644 Binary files a/README.pdf and b/README.pdf differ diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..781bd08 --- /dev/null +++ b/build.sbt @@ -0,0 +1,8 @@ +scalaVersion := "2.13.1" + +name := "TheGame" +organization := "fr.ynerant" +version := "1.0" + +// https://mvnrepository.com/artifact/net.liftweb/lift-json +libraryDependencies += "net.liftweb" %% "lift-json" % "3.4.1" diff --git a/compile.sh b/compile.sh deleted file mode 100755 index a9c58ab..0000000 --- a/compile.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -chmod +x lib/*.jar -rm -rf tmp -mkdir tmp -javac -cp src/main/java:lib/gson-2.8.6.jar:lib/jopt-simple-6.0-alpha-3.jar \ - -target 1.9 -source 1.9 \ - -d tmp --module-path src/main/java \ - src/main/java/fr/ynerant/leveleditor/api/editor/*.java \ - src/main/java/fr/ynerant/leveleditor/client/main/*.java \ - src/main/java/fr/ynerant/leveleditor/editor/*.java \ - src/main/java/fr/ynerant/leveleditor/frame/*.java \ - src/main/java/fr/ynerant/leveleditor/game/*.java \ - src/main/java/fr/ynerant/leveleditor/game/mobs/*.java \ - src/main/java/fr/ynerant/leveleditor/game/towers/*.java -cp -r src/main/resources/* tmp/ -unzip lib/gson-2.8.6.jar -x META-INF/MANIFEST.MF -d tmp -unzip lib/jopt-simple-6.0-alpha-3.jar -x META-INF/MANIFEST.MF -d tmp -cd tmp -zip -r TheGame.jar * -mv TheGame.jar ../ -cd .. -rm -rf tmp -chmod +x TheGame.jar -echo "Successfully compiled to \"TheGame.jar\". To run: \"java -jar TheGame.jar\"". diff --git a/lib/gson-2.8.6.jar b/lib/gson-2.8.6.jar deleted file mode 100755 index 4765c4a..0000000 Binary files a/lib/gson-2.8.6.jar and /dev/null differ diff --git a/lib/jopt-simple-6.0-alpha-3.jar b/lib/jopt-simple-6.0-alpha-3.jar deleted file mode 100755 index 5838e90..0000000 Binary files a/lib/jopt-simple-6.0-alpha-3.jar and /dev/null differ diff --git a/samples/Test.gmap b/samples/Test.gmap index 966847e..eb7a7d8 100644 Binary files a/samples/Test.gmap and b/samples/Test.gmap differ diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/Case.java b/src/main/java/fr/ynerant/leveleditor/api/editor/Case.java deleted file mode 100644 index 7c939f8..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/Case.java +++ /dev/null @@ -1,52 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; - -public class Case { - private int x; - private int y; - private Sprite couche1; - private Sprite couche2; - private Sprite couche3; - private Collision collision; - - public static Case create(int posX, int posY, Sprite couche1, Sprite couche2, Sprite couche3, Collision collision) { - Case c = new Case(); - c.x = posX; - c.y = posY; - c.couche1 = couche1; - c.couche2 = couche2; - c.couche3 = couche3; - c.collision = collision; - return c; - } - - public int getPosX() { - return x; - } - - public int getPosY() { - return y; - } - - public Sprite getCoucheOne() { - return couche1; - } - - public Sprite getCoucheTwo() { - return couche2; - } - - public Sprite getCoucheThree() { - return couche3; - } - - public Collision getCollision() { - return collision; - } - - @Override - public String toString() { - return "{Case x=" + x + " y=" + y + " couche1=" + couche1 + " couche2=" + couche2 + " couche3=" + couche3 + " collision=" + collision.name().toUpperCase() + "}\n"; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/Collision.java b/src/main/java/fr/ynerant/leveleditor/api/editor/Collision.java deleted file mode 100644 index 6b3f229..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/Collision.java +++ /dev/null @@ -1,5 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -public enum Collision { - FULL, PARTIAL, ANY -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/EditorAPI.java b/src/main/java/fr/ynerant/leveleditor/api/editor/EditorAPI.java deleted file mode 100644 index b91f1ee..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/EditorAPI.java +++ /dev/null @@ -1,162 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import fr.ynerant.leveleditor.editor.Map; - -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -public class EditorAPI { - private static File LAST_FILE; - - public static RawMap toRawMap(int width, int height) { - List cases = new ArrayList<>(); - - for (int y = 1; y < height; y += 16) { - for (int x = 1; x < width; x += 16) { - RawCase c = RawCase.create(x / 16, y / 16, RawSprite.BLANK, RawSprite.BLANK, RawSprite.BLANK, Collision.ANY); - cases.add(c); - } - } - - return RawMap.create(cases, width, height); - } - - public static Gson createGson() { - GsonBuilder builder = new GsonBuilder(); - - builder.enableComplexMapKeySerialization(); - builder.serializeNulls(); - builder.setPrettyPrinting(); - - return builder.create(); - } - - public static JFileChooser createJFC() { - JFileChooser jfc = new JFileChooser(); - - jfc.setFileFilter(new FileNameExtensionFilter("Fichiers monde (*.gmap, *.dat)", "gmap", "dat")); - jfc.setFileHidingEnabled(true); - jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); - File dir = new File("maps"); - assert dir.mkdirs(); - jfc.setCurrentDirectory(dir); - - return jfc; - } - - public static void saveAs(RawMap map) { - JFileChooser jfc = createJFC(); - File file; - jfc.showSaveDialog(null); - file = jfc.getSelectedFile(); - - if (file == null) - return; - - if (!file.getName().toLowerCase().endsWith(".gmap") && !file.getName().toLowerCase().endsWith(".dat")) { - file = new File(file.getParentFile(), file.getName() + ".gmap"); - } - - LAST_FILE = file; - - save(file, map); - } - - public static void save(RawMap map) { - if (LAST_FILE != null) - save(LAST_FILE, map); - else - saveAs(map); - } - - public static void save(File file, RawMap map) { - String json = createGson().toJson(map); - - try { - assert file.createNewFile(); - BufferedOutputStream bos = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(file))); - - bos.write(json.getBytes(StandardCharsets.UTF_8)); - - bos.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - public static Map open() { - JFileChooser jfc = createJFC(); - File file; - - jfc.showOpenDialog(null); - file = jfc.getSelectedFile(); - - if (file == null) - return null; - - LAST_FILE = file; - - return open(file); - } - - public static RawMap getRawMap(File f) { - String json = null; - try { - GZIPInputStream gis = new GZIPInputStream(new BufferedInputStream(new FileInputStream(f))); - byte[] bytes = new byte[512 * 1024]; - int count; - StringBuilder text = new StringBuilder(); - while ((count = gis.read(bytes)) != -1) { - text.append(new String(bytes, 0, count, StandardCharsets.UTF_8)); - } - gis.close(); - - json = text.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - - return createGson().fromJson(json, RawMap.class); - } - - public static Map open(File f) { - return open(getRawMap(f)); - } - - public static Map open(RawMap map) { - if (map.getFont() == null) { - int baseWidth = map.getWidth(); - int baseHeight = map.getHeight(); - int width = baseWidth + (baseWidth / 16) + 1; - int height = baseHeight + (baseHeight / 16) + 1; - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - g.setColor(Color.white); - g.fillRect(0, 0, width, height); - g.setColor(Color.black); - g.drawLine(0, 0, width, 0); - g.drawLine(0, 0, 0, height); - for (int x = 17; x <= width; x += 17) { - g.drawLine(x, 0, x, height); - } - - for (int y = 17; y <= height; y += 17) { - g.drawLine(0, y, width, y); - } - - map.setFont(image); - } - - return new Map(map); - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/RawCase.java b/src/main/java/fr/ynerant/leveleditor/api/editor/RawCase.java deleted file mode 100644 index 3169474..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/RawCase.java +++ /dev/null @@ -1,60 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -public class RawCase { - private int x; - private int y; - private RawSprite couche1; - private RawSprite couche2; - private RawSprite couche3; - private Collision collision; - - public static RawCase create(int posX, int posY, RawSprite couche1, RawSprite couche2, RawSprite couche3, Collision collision) { - RawCase c = new RawCase(); - c.x = posX; - c.y = posY; - c.couche1 = couche1; - c.couche2 = couche2; - c.couche3 = couche3; - c.collision = collision; - return c; - } - - public static RawCase create(Case c) { - RawCase raw = new RawCase(); - raw.x = c.getPosX(); - raw.y = c.getPosY(); - raw.couche1 = RawSprite.create(c.getCoucheOne()); - raw.couche2 = RawSprite.create(c.getCoucheTwo()); - raw.couche3 = RawSprite.create(c.getCoucheThree()); - raw.collision = c.getCollision(); - return raw; - } - - public int getPosX() { - return x; - } - - public int getPosY() { - return y; - } - - public RawSprite getCoucheOne() { - return couche1; - } - - public RawSprite getCoucheTwo() { - return couche2; - } - - public RawSprite getCoucheThree() { - return couche3; - } - - public Collision getCollision() { - return collision; - } - - public void setCollision(Collision collision) { - this.collision = collision; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/RawMap.java b/src/main/java/fr/ynerant/leveleditor/api/editor/RawMap.java deleted file mode 100644 index 10af484..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/RawMap.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -import fr.ynerant.leveleditor.editor.Map; - -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; - -public class RawMap { - private List cases; - private java.util.Map cases_map; - private int width; - private int height; - private transient BufferedImage font; - - public static RawMap create(List cases, int width, int height) { - RawMap rm = new RawMap(); - rm.cases = cases; - rm.width = width; - rm.height = height; - return rm; - } - - public static RawMap create(Map map) { - RawMap raw = new RawMap(); - raw.width = map.getWidth(); - raw.height = map.getHeight(); - raw.cases = new ArrayList<>(); - for (Case c : map.getAllCases()) { - RawCase rc = RawCase.create(c); - raw.cases.add(rc); - } - return raw; - } - - public List getCases() { - return cases; - } - - public RawCase getCase(int x, int y) { - if (cases_map == null) { - cases_map = new HashMap<>(); - for (RawCase c : getCases()) - cases_map.put(c.getPosY() * width + c.getPosX(), c); - } - - return cases_map.get(y * getWidth() + x); - } - - public Collection getNeighbours(RawCase c) { - List list = new ArrayList<>(); - list.add(getCase(c.getPosX() - 1, c.getPosY())); - list.add(getCase(c.getPosX(), c.getPosY() - 1)); - list.add(getCase(c.getPosX() + 1, c.getPosY())); - list.add(getCase(c.getPosX(), c.getPosY() + 1)); - return list.stream().filter(_c -> _c != null && _c.getCollision() == Collision.ANY).collect(Collectors.toList()); - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public BufferedImage getFont() { - return font; - } - - public void setFont(BufferedImage font) { - this.font = font; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/RawSprite.java b/src/main/java/fr/ynerant/leveleditor/api/editor/RawSprite.java deleted file mode 100644 index de4ff34..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/RawSprite.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.ynerant.leveleditor.api.editor; - -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; - -public class RawSprite { - public static transient final RawSprite BLANK = new RawSprite(); - private String category = "blank"; - private int index = 0; - - public static RawSprite create(Sprite spr) { - RawSprite raw = new RawSprite(); - raw.category = spr.getCategory().getName(); - raw.index = spr.getIndex(); - return raw; - } - - public String getCategory() { - return category; - } - - public int getIndex() { - return index; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/package-info.java b/src/main/java/fr/ynerant/leveleditor/api/editor/package-info.java deleted file mode 100644 index e736761..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * @author ÿnérant - */ -package fr.ynerant.leveleditor.api.editor; \ No newline at end of file diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Category.java b/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Category.java deleted file mode 100644 index 6fd66e6..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Category.java +++ /dev/null @@ -1,33 +0,0 @@ -package fr.ynerant.leveleditor.api.editor.sprites; - -import java.util.List; - -public class Category { - private List sprites; - private String name; - - private Category() { - } - - public static Category create(String name, List sprites) { - Category c = new Category(); - - c.name = name; - c.sprites = sprites; - - return c; - } - - public String getName() { - return name; - } - - public List getSprites() { - return sprites; - } - - @Override - public String toString() { - return name; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Sprite.java b/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Sprite.java deleted file mode 100644 index f019baa..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/Sprite.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.ynerant.leveleditor.api.editor.sprites; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - -public class Sprite { - public static final Sprite BLANK = new Sprite(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB), Category.create("blank", new ArrayList<>()), 0); - - static { - Graphics2D g = BLANK.getImage().createGraphics(); - g.setComposite(AlphaComposite.Clear); - g.setColor(new Color(0, true)); - g.fillRect(0, 0, 16, 16); - } - - private final Category cat; - private final BufferedImage img; - private final int index; - - public Sprite(BufferedImage img, Category cat, int index) { - this.img = img; - this.cat = cat; - this.index = index; - - if (!this.cat.getSprites().contains(this)) - this.cat.getSprites().add(this); - } - - public BufferedImage getImage() { - return this.img; - } - - public Category getCategory() { - return cat; - } - - public int getIndex() { - return index; - } - - @Override - public int hashCode() { - return cat.hashCode() ^ getIndex(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Sprite)) - return false; - - Sprite other = (Sprite) o; - - return hashCode() == other.hashCode(); - } - - @Override - public String toString() { - return "{Sprite img=" + img + " cat=" + cat.getName() + "}"; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.java b/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.java deleted file mode 100644 index 3dd7d1a..0000000 --- a/src/main/java/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.java +++ /dev/null @@ -1,125 +0,0 @@ -package fr.ynerant.leveleditor.api.editor.sprites; - -import com.google.gson.Gson; -import fr.ynerant.leveleditor.client.main.Main; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.*; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.*; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -public class SpriteRegister { - private static Map>> nameToCoords; - private static final Map sprites = new HashMap<>(); - - public static void unpack() throws IOException { - if (Main.isInDevelopmentMode()) { - try { - File dir = new File(SpriteRegister.class.getResource("/assets").toURI()).getParentFile(); - unpackDir(dir); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - } - else { - @SuppressWarnings("deprecation") - String path = URLDecoder.decode(SpriteRegister.class.getProtectionDomain().getCodeSource().getLocation().getPath()); - File jarFile = new File(path); - - if (jarFile.isFile()) { - JarFile jar = new JarFile(jarFile); - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry je = entries.nextElement(); - String name = je.getName(); - if (name.startsWith("assets/")) { - File f = new File(name); - if (name.endsWith("/")) { - if (!f.mkdirs() && !f.isDirectory()) - throw new IOException("Unable to make dir: " + f); - } - else if (!f.isFile()) - Files.copy(jar.getInputStream(je), Paths.get(f.toURI())); - } - } - jar.close(); - } - } - } - - private static void unpackDir(File dir) throws IOException { - for (File f : Objects.requireNonNull(dir.listFiles())) { - if (f.isDirectory()) { - unpackDir(f); - continue; - } - - String path = f.getAbsolutePath().substring(f.getAbsolutePath().indexOf(File.separatorChar + "assets") + 1); - File local = new File(path); - assert local.getParentFile().mkdirs(); - assert !local.exists() || local.delete(); - Files.copy(Paths.get(f.toURI()), Paths.get(local.toURI())); - } - } - - @SuppressWarnings("unchecked") - public static void refreshAllSprites() { - if (nameToCoords != null && !nameToCoords.isEmpty() && !sprites.isEmpty()) { - return; - } - - File assetsDir = new File("assets"); - List assets = new ArrayList<>(); - - for (File dir : Objects.requireNonNull(assetsDir.listFiles())) { - assets.add(dir.getName()); - } - - for (String asset : assets) { - try { - File f = new File(assetsDir.getAbsolutePath() + "/" + asset + "/textures/sprites"); - assert f.mkdirs(); - BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(f, "sprites.json")))); - nameToCoords = new Gson().fromJson(br, Map.class); - br.close(); - - for (String key : nameToCoords.keySet()) { - try { - BufferedInputStream is = new BufferedInputStream(new FileInputStream(new File(f, key + ".png"))); - BufferedImage img = ImageIO.read(is); - Category cat = Category.create(key, new ArrayList<>()); - - for (List list : nameToCoords.get(key)) { - int x = list.get(0).intValue(); - int y = list.get(1).intValue(); - BufferedImage child = img.getSubimage(x, y, 16, 16); - new Sprite(child, cat, nameToCoords.get(key).indexOf(list)); - } - - sprites.put(key, cat); - } catch (Throwable t) { - System.err.println("Erreur lors de la lecture du sprite '" + key + "'"); - t.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static Category getCategory(String name) { - return sprites.get(name); - } - - public static List getAllCategories() { - return new ArrayList<>(sprites.values()); - } - -} diff --git a/src/main/java/fr/ynerant/leveleditor/client/main/Main.java b/src/main/java/fr/ynerant/leveleditor/client/main/Main.java deleted file mode 100644 index 9fd8f84..0000000 --- a/src/main/java/fr/ynerant/leveleditor/client/main/Main.java +++ /dev/null @@ -1,226 +0,0 @@ -package fr.ynerant.leveleditor.client.main; - -import fr.ynerant.leveleditor.api.editor.EditorAPI; -import fr.ynerant.leveleditor.api.editor.RawMap; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; -import fr.ynerant.leveleditor.frame.MainFrame; -import fr.ynerant.leveleditor.game.GameFrame; -import joptsimple.OptionParser; -import joptsimple.OptionSet; -import joptsimple.OptionSpec; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Locale; -import java.util.Map; - -/** - * Class principale qui lance le jeu - * - * @author ÿnérant - * @see #main(String...) - */ -public class Main { - /** - * Variable disant si le jeu est lancé en développement ou non. - * - * @see #isInDevelopmentMode() - * @see #main(String...) - * @since 0.1-aplha - */ - private static boolean DEV; - - /** - * @param args arguments du jeu. Possibilités :
    --edit lancera un éditeur
    --help lance l'aide affichant toutes les options possibles - * @see #launchEditMode() - * @since 0.1-alpha - */ - public static void main(String... args) { - System.setProperty("sun.java2d.noddraw", "true"); - - Locale.setDefault(Locale.FRANCE); - - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { - new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace(); - System.err.print("Caused by "); - e.printStackTrace(); - } - - try { - new File(Main.class.getResource("/assets").toURI()); - DEV = true; - } catch (Throwable t) { - DEV = false; - } - - checkJava(); - - OptionParser parser = new OptionParser(); - - OptionSpec edit = parser.accepts("edit", "Lancer l'\u00e9diteur de monde").withOptionalArg(); - OptionSpec help = parser.accepts("help", "Affiche ce menu d'aide").withOptionalArg().forHelp(); - - OptionSet set = parser.parse(args); - - if (set.has(help)) { - try { - parser.printHelpOn(System.out); - } catch (IOException e) { - e.printStackTrace(); - } finally { - System.exit(0); - } - } - - try { - SpriteRegister.unpack(); - } catch (IOException e) { - e.printStackTrace(); - } - - SpriteRegister.refreshAllSprites(); - - if (set.has(edit)) { - launchEditMode(); - return; - } - - launchFrame(); - } - - private static void checkJava() { - if (GraphicsEnvironment.isHeadless()) { - HeadlessException ex = new HeadlessException("Impossible de lancer un jeu sans \u00e9cran !"); - System.err.println("Cette application est un jeu, sans écran, elle aura du mal \u00e0 tourner ..."); - ex.printStackTrace(); - System.exit(1); - } - - try { - Map.class.getDeclaredMethod("getOrDefault", Object.class, Object.class); - } catch (NoSuchMethodException ex) { - ex.printStackTrace(); - JOptionPane.showMessageDialog(null, "Cette application requiert Java 8.
La page de t\u00e9l\u00e9chargement va maintenant s'ouvrir."); - JOptionPane.showMessageDialog(null, "Si vous êtes certain que Java 8 est installé sur votre machine, assurez-vous qu'il n'y a pas de versions obsolètes de Java,
ou si vous êtes plus expérimentés si le path vers Java est bien défini vers la bonne version."); - try { - if (Desktop.isDesktopSupported()) - Desktop.getDesktop().browse(new URL("http://java.com/download").toURI()); - else - JOptionPane.showMessageDialog(null, "Votre machine ne supporte pas la classe Desktop, impossible d'ouvrir la page.
Rendez-vous y manuellement sur http://java.com/download pour installer Java."); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - System.exit(1); - } - } - - /** - * Lance la fenêtre principale - * - * @see #main(String...) - * @see #launchEditMode() - */ - private static void launchFrame() { - MainFrame.getInstance().setVisible(true); - } - - /** - * Permet de lancer l'éditeur de carte - * - * @see #main(String...) - * @see #launchFrame() - * @since 0.1-aplha - */ - public static boolean launchEditMode() { - System.out.println("Lancement de l'\u00e9diteur de monde ..."); - int baseWidth; - int baseHeight; - int width; - int height; - while (true) { - try { - String baseWidthStr = JOptionPane.showInputDialog(null, "Veuillez entrez le nombre de cases longueur de votre carte (0 pour annuler) :"); - if (baseWidthStr == null) - return false; - baseWidth = Integer.parseInt(baseWidthStr) * 16; - if (baseWidth < 0) - throw new NumberFormatException(); - if (baseWidth == 0) - return false; - break; - } catch (NumberFormatException ignored) { - } - } - - while (true) { - try { - String baseHeightStr = JOptionPane.showInputDialog("Veuillez entrez le nombre de cases hauteur de votre carte (0 pour annuler) :"); - if (baseHeightStr == null) - return false; - baseHeight = Integer.parseInt(baseHeightStr) * 16; - if (baseHeight < 0) - throw new NumberFormatException(); - if (baseHeight == 0) - return false; - break; - } catch (NumberFormatException ignored) { - } - } - - width = baseWidth + (baseWidth / 16) + 1; - height = baseHeight + (baseHeight / 16) + 1; - - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - g.setColor(Color.white); - g.fillRect(0, 0, width, height); - g.setColor(Color.black); - g.drawLine(0, 0, width, 0); - g.drawLine(0, 0, 0, height); - for (int x = 17; x <= width; x += 17) { - g.drawLine(x, 0, x, height); - } - - for (int y = 17; y <= height; y += 17) { - g.drawLine(0, y, width, y); - } - - RawMap rm = EditorAPI.toRawMap(baseWidth, baseHeight); - rm.setFont(image); - - EditorAPI.open(rm); - - return true; - } - - public static boolean launchGameMode() { - System.out.println("Lancement du jeu ..."); - JFileChooser jfc = EditorAPI.createJFC(); - jfc.showOpenDialog(MainFrame.getInstance()); - if (jfc.getSelectedFile() == null) - return false; - - RawMap map = EditorAPI.getRawMap(jfc.getSelectedFile()); - - new GameFrame(map); - - return true; - } - - /** - * Accesseur disant si le jeu est lancé en développement ou non. - * - * @see #DEV - * @since 0.1-alpha - */ - public static boolean isInDevelopmentMode() { - return DEV; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/client/main/package-info.java b/src/main/java/fr/ynerant/leveleditor/client/main/package-info.java deleted file mode 100644 index e5f506f..0000000 --- a/src/main/java/fr/ynerant/leveleditor/client/main/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Ce package comprend uniquement la classe Main, qui lance l'application. - * - * @author ÿnérant - */ -package fr.ynerant.leveleditor.client.main; \ No newline at end of file diff --git a/src/main/java/fr/ynerant/leveleditor/editor/CollidPanel.java b/src/main/java/fr/ynerant/leveleditor/editor/CollidPanel.java deleted file mode 100644 index c786fc7..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/CollidPanel.java +++ /dev/null @@ -1,83 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import fr.ynerant.leveleditor.api.editor.Case; -import fr.ynerant.leveleditor.api.editor.Collision; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; - -public class CollidPanel extends JPanel { - private static final long serialVersionUID = -138754019431984881L; - - private final EditorFrame frame; - - public CollidPanel(EditorFrame frame) { - super(); - this.frame = frame; - } - - public Map getMap() { - return frame.getMap(); - } - - @Override - public void paintComponent(Graphics g) { - g.fillRect(0, 0, getWidth(), getHeight()); - BufferedImage img = getMap().getFont(); - int x = getWidth() / 2 - img.getWidth(); - int y = getHeight() / 2 - img.getHeight(); - int width = img.getWidth() * 2; - int height = img.getHeight() * 2; - g.drawImage(getMap().getFont(), x, y, width, height, null); - - for (Case c : getMap().getAllCases()) { - if (isEmpty(c.getCoucheOne().getImage())) - continue; - - g.drawImage(c.getCoucheOne().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - - if (isEmpty(c.getCoucheTwo().getImage())) - continue; - - g.drawImage(c.getCoucheTwo().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - - if (isEmpty(c.getCoucheThree().getImage())) - continue; - - g.drawImage(c.getCoucheThree().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - } - - for (Case c : getMap().getAllCases()) { - if (c.getCollision() != Collision.ANY) { - BufferedImage alpha = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); - - if (c.getCollision() == Collision.FULL) { - Graphics2D grap = alpha.createGraphics(); - grap.setColor(new Color(0, 0, 0, 100)); - grap.fillRect(0, 0, 16, 16); - grap.dispose(); - } else if (c.getCollision() == Collision.PARTIAL) { - Graphics2D grap = alpha.createGraphics(); - grap.setColor(new Color(255, 0, 255, 70)); - grap.fillRect(0, 0, 16, 16); - grap.dispose(); - } - - g.drawImage(alpha, x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - } - } - } - - public static boolean isEmpty(BufferedImage image) { - int allrgba = 0; - - for (int x = 0; x < image.getWidth(); ++x) { - for (int y = 0; y < image.getHeight(); ++y) { - allrgba += image.getRGB(x, y) + 1; - } - } - - return allrgba == 0; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/editor/EditorFrame.java b/src/main/java/fr/ynerant/leveleditor/editor/EditorFrame.java deleted file mode 100644 index fabc479..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/EditorFrame.java +++ /dev/null @@ -1,322 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import fr.ynerant.leveleditor.api.editor.EditorAPI; -import fr.ynerant.leveleditor.api.editor.RawMap; -import fr.ynerant.leveleditor.api.editor.sprites.Category; -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; -import fr.ynerant.leveleditor.frame.listeners.*; - -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.*; -import java.awt.event.*; -import java.awt.image.BufferedImage; -import java.io.File; - -public class EditorFrame extends JFrame implements ChangeListener, ActionListener, WindowListener { - private static final long serialVersionUID = -2705122356101556462L; - - private final Map map; - - private final JMenuItem save = new JMenuItem("Sauvegarder"); - private final JMenuItem saveAs = new JMenuItem("Sauvegarder sous ..."); - private final JMenuItem exit = new JMenuItem("Quitter"); - private final JRadioButtonMenuItem pen = new JRadioButtonMenuItem("Pinceau"); - private final JRadioButtonMenuItem pot = new JRadioButtonMenuItem("Pot de peinture"); - private final JTabbedPane tabs = new JTabbedPane(); - private final CollidPanel tabColl; - private final MapPanel mapPanel; - private final JTabbedPane resources = new JTabbedPane(); - private final JPanel couche1 = new JPanel(); - private final JPanel couche2 = new JPanel(); - private final JPanel couche3 = new JPanel(); - final ButtonGroup group = new ButtonGroup(); - private SpriteComp selectedSprite; - - public EditorFrame(Map map) { - super("Level Editor"); - this.map = map; - this.setSize(600, 600); - this.setPreferredSize(getSize()); - this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - this.setLocationRelativeTo(null); - this.addWindowListener(this); - JPanel content = new JPanel(); - content.setLayout(new BorderLayout()); - this.setContentPane(content); - this.setVisible(true); - this.setVisible(false); - - JMenu fichier = new JMenu("Fichier"); - fichier.setMnemonic(KeyEvent.VK_F + KeyEvent.ALT_DOWN_MASK); - - JMenuItem nouveau = new JMenuItem("Nouveau"); - nouveau.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK, true)); - nouveau.addActionListener(new CreateMapListener()); - fichier.add(nouveau); - - JMenuItem open = new JMenuItem("Ouvrir"); - open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK, true)); - open.addActionListener(new OpenMapListener()); - fichier.add(open); - - fichier.addSeparator(); - - save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK, true)); - save.addActionListener(this); - fichier.add(save); - - saveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK + KeyEvent.SHIFT_DOWN_MASK, true)); - saveAs.addActionListener(this); - fichier.add(saveAs); - - fichier.addSeparator(); - - exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_DOWN_MASK, true)); - exit.addActionListener(this); - fichier.add(exit); - - JMenuBar menuBar = new JMenuBar(); - menuBar.add(fichier); - - pen.setSelected(true); - pen.addActionListener(this); - pot.addActionListener(this); - group.add(pen); - group.add(pot); - JMenu selectionMode = new JMenu("Mode de s\u00e9lection"); - selectionMode.add(pen); - selectionMode.add(pot); - - JMenu tools = new JMenu("Outils"); - tools.setMnemonic(KeyEvent.VK_O + KeyEvent.ALT_DOWN_MASK); - - tools.add(selectionMode); - - menuBar.add(tools); - - this.setJMenuBar(menuBar); - - mapPanel = new MapPanel(this); - mapPanel.addMouseListener(new MapMouseListener(mapPanel, this)); - mapPanel.addMouseMotionListener(new MapMouseListener(mapPanel, this)); - - tabColl = new CollidPanel(this); - tabColl.addMouseListener(new CollidMapMouseListener(tabColl, this)); - tabColl.addMouseMotionListener(new CollidMapMouseListener(tabColl, this)); - - JScrollPane scrollMap = new JScrollPane(mapPanel); - scrollMap.getHorizontalScrollBar().setUnitIncrement(34); - scrollMap.getVerticalScrollBar().setUnitIncrement(34); - JScrollPane scrollCollidMap = new JScrollPane(tabColl); - scrollCollidMap.getHorizontalScrollBar().setUnitIncrement(34); - scrollCollidMap.getVerticalScrollBar().setUnitIncrement(34); - - tabs.addTab("Carte", scrollMap); - JPanel tabEvents = new JPanel(); - tabs.addTab("\u00c9vennments", new JScrollPane(tabEvents)); - tabs.addTab("Collisions", scrollCollidMap); - tabs.addChangeListener(this); - - content.add(tabs, BorderLayout.CENTER); - - couche1.setLayout(new WrapLayout(WrapLayout.LEFT)); - couche2.setLayout(new WrapLayout(WrapLayout.LEFT)); - couche3.setLayout(new WrapLayout(WrapLayout.LEFT)); - - JScrollPane scroll1 = new JScrollPane(couche1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - JScrollPane scroll2 = new JScrollPane(couche2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - JScrollPane scroll3 = new JScrollPane(couche3, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - - scroll1.getHorizontalScrollBar().setMaximum(0); - scroll2.getHorizontalScrollBar().setMaximum(0); - scroll3.getHorizontalScrollBar().setMaximum(0); - - resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 1.png").getAbsolutePath()), scroll1); - resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 2.png").getAbsolutePath()), scroll2); - resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 3.png").getAbsolutePath()), scroll3); - resources.addChangeListener(this); - resources.setBackgroundAt(0, Color.white); - resources.setBackgroundAt(1, Color.white); - resources.setBackgroundAt(2, Color.white); - - content.add(resources, BorderLayout.EAST); - - resize(); - - drawResources(); - - revalidate(); - repaint(); - } - - private void drawResources() { - couche1.removeAll(); - couche2.removeAll(); - couche3.removeAll(); - - if (couche1.getComponents().length > 0) { - return; - } - - if (couche1.getWidth() == 0 || couche2.getWidth() == 0 || couche3.getWidth() == 0) { - couche1.repaint(); - couche2.repaint(); - couche3.repaint(); - } - - for (Category cat : SpriteRegister.getAllCategories()) { - for (Sprite spr : cat.getSprites()) { - SpriteComp sprc1 = new SpriteComp(spr, 0); - SpriteComp sprc2 = new SpriteComp(spr, 1); - SpriteComp sprc3 = new SpriteComp(spr, 2); - sprc1.addMouseListener(new SpriteMouseListener(sprc1, this)); - sprc2.addMouseListener(new SpriteMouseListener(sprc2, this)); - sprc3.addMouseListener(new SpriteMouseListener(sprc3, this)); - couche1.add(sprc1); - couche2.add(sprc2); - couche3.add(sprc3); - } - } - - couche1.revalidate(); - couche2.revalidate(); - couche3.revalidate(); - couche1.repaint(); - couche2.repaint(); - couche3.repaint(); - } - - public void resize() { - - int cursorPos = ((JScrollPane) resources.getSelectedComponent()).getVerticalScrollBar().getValue(); - tabs.setPreferredSize(new Dimension(getWidth(), getHeight() / 5)); - tabs.setLocation(0, 0); - BufferedImage img = getMap().getFont(); - int width = img.getWidth() * 2; - int height = img.getHeight() * 2; - mapPanel.setPreferredSize(new Dimension(width, height)); - mapPanel.setLocation(0, getHeight() / 5); - tabColl.setPreferredSize(new Dimension(width, height)); - tabColl.setLocation(0, getHeight() / 5); - resources.setPreferredSize(new Dimension(getWidth() / 4 - 15, getHeight() / 5 * 4 - 40)); - resources.setLocation(getWidth() / 4 * 3, getHeight() / 5); - - JScrollPane scroll1 = (JScrollPane) resources.getComponent(0); - JScrollPane scroll2 = (JScrollPane) resources.getComponent(1); - JScrollPane scroll3 = (JScrollPane) resources.getComponent(2); - - scroll1.getHorizontalScrollBar().setMaximum(0); - scroll2.getHorizontalScrollBar().setMaximum(0); - scroll3.getHorizontalScrollBar().setMaximum(0); - - drawResources(); - - ((JScrollPane) resources.getSelectedComponent()).getVerticalScrollBar().setValue(cursorPos); - } - - public Map getMap() { - return map; - } - - public SpriteComp getSelectedSprite() { - return selectedSprite; - } - - public void setSelectedSprite(SpriteComp sprite) { - this.selectedSprite = sprite; - } - - @Override - public void stateChanged(ChangeEvent event) { - if (event.getSource() == resources) { - if (getSelectedLayerIndex() == 0) { - resources.setBackgroundAt(0, Color.white); - resources.setBackgroundAt(1, Color.white); - resources.setBackgroundAt(2, Color.white); - } else if (getSelectedLayerIndex() == 1) { - resources.setBackgroundAt(0, Color.black); - resources.setBackgroundAt(1, Color.white); - resources.setBackgroundAt(2, Color.white); - } else if (getSelectedLayerIndex() == 2) { - resources.setBackgroundAt(0, Color.black); - resources.setBackgroundAt(1, Color.black); - resources.setBackgroundAt(2, Color.white); - } - - repaint(); - } else if (event.getSource() == tabs) { - resources.setEnabled(tabs.getSelectedIndex() == 0); - couche1.setEnabled(resources.isEnabled()); - couche2.setEnabled(resources.isEnabled()); - couche3.setEnabled(resources.isEnabled()); - - repaint(); - } - } - - public int getSelectedLayerIndex() { - return resources.getSelectedIndex(); - } - - @Override - public void actionPerformed(ActionEvent event) { - if (event.getSource() == save) { - EditorAPI.save(RawMap.create(map)); - } else if (event.getSource() == saveAs) { - EditorAPI.saveAs(RawMap.create(map)); - } else if (event.getSource() == exit) { - int result = JOptionPane.showConfirmDialog(null, "Voulez-vous sauvegarder votre carte avant de quitter ? Toute modification sera perdue", "Confirmation", JOptionPane.YES_NO_CANCEL_OPTION); - - if (result == 0) - save.doClick(); - - if (result != 2) - dispose(); - } - } - - public int getSelectedPaintingMode() { - return pen.isSelected() ? 0 : pot.isSelected() ? 1 : -1; - } - - @Override - public void windowActivated(WindowEvent event) { - } - - @Override - public void windowClosed(WindowEvent event) { - } - - @Override - public void windowClosing(WindowEvent event) { - int result = JOptionPane.showConfirmDialog(null, "Voulez-vous sauvegarder avant de quitter ?", "Confirmation", JOptionPane.YES_NO_CANCEL_OPTION); - - if (result == 0) { - EditorAPI.save(RawMap.create(map)); - } - - if (result != 2) { - dispose(); - } - } - - @Override - public void windowDeactivated(WindowEvent event) { - } - - @Override - public void windowDeiconified(WindowEvent event) { - } - - @Override - public void windowIconified(WindowEvent event) { - } - - @Override - public void windowOpened(WindowEvent event) { - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/editor/Map.java b/src/main/java/fr/ynerant/leveleditor/editor/Map.java deleted file mode 100644 index 83d7ea4..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/Map.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import fr.ynerant.leveleditor.api.editor.Case; -import fr.ynerant.leveleditor.api.editor.RawCase; -import fr.ynerant.leveleditor.api.editor.RawMap; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; - -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class Map { - @Deprecated - private static List cases; - private final EditorFrame frame; - private final int width; - private final int height; - private final java.util.Map> casesMap = new HashMap<>(); - private final transient BufferedImage font; - - public Map(RawMap raw) { - cases = new ArrayList<>(); - this.width = raw.getWidth(); - this.height = raw.getHeight(); - this.font = raw.getFont(); - - for (RawCase rc : raw.getCases()) { - cases.add(Case.create(rc.getPosX(), rc.getPosY(), SpriteRegister.getCategory(rc.getCoucheOne().getCategory()).getSprites().get(rc.getCoucheOne().getIndex()), SpriteRegister.getCategory(rc.getCoucheTwo().getCategory()).getSprites().get(rc.getCoucheTwo().getIndex()), SpriteRegister.getCategory(rc.getCoucheThree().getCategory()).getSprites().get(rc.getCoucheThree().getIndex()), rc.getCollision())); - } - - reorganizeMap(); - - frame = new EditorFrame(this); - - getFrame().setVisible(true); - } - - public EditorFrame getFrame() { - return frame; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public Case getCase(int x, int y) { - return casesMap.getOrDefault(x, new HashMap<>()).get(y); - } - - public void setCase(int x, int y, Case c) { - casesMap.get(x).put(y, c); - } - - public BufferedImage getFont() { - return font; - } - - private void reorganizeMap() { - for (int i = 0; i < width; ++i) { - casesMap.put(i, new HashMap<>()); - } - - for (Case c : cases) { - setCase(c.getPosX(), c.getPosY(), c); - } - } - - public List getAllCases() { - List list = new ArrayList<>(); - - for (java.util.Map l : casesMap.values()) { - list.addAll(l.values()); - } - - return list; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/editor/MapPanel.java b/src/main/java/fr/ynerant/leveleditor/editor/MapPanel.java deleted file mode 100644 index dbe9316..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/MapPanel.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import fr.ynerant.leveleditor.api.editor.Case; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; - -public class MapPanel extends JPanel { - private static final long serialVersionUID = 2629019576253690557L; - - private final EditorFrame frame; - - public MapPanel(EditorFrame frame) { - super(); - this.frame = frame; - } - - public Map getMap() { - return frame.getMap(); - } - - @Override - public void paintComponent(Graphics g) { - g.fillRect(0, 0, getWidth(), getHeight()); - BufferedImage img = getMap().getFont(); - int x = getWidth() / 2 - img.getWidth(); - int y = getHeight() / 2 - img.getHeight(); - int width = img.getWidth() * 2; - int height = img.getHeight() * 2; - g.drawImage(getMap().getFont(), x, y, width, height, null); - - for (Case c : getMap().getAllCases()) { - // BufferedImage image; - - if (!isEmpty(c.getCoucheOne().getImage())) { - g.drawImage(c.getCoucheOne().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - } - /* if (frame.getSelectedLayerIndex() != 0) - { - image = recalculateAplha(c.getCoucheOne().getImage(), 0); - g.drawImage(image, x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - }*/ - - if (!isEmpty(c.getCoucheTwo().getImage()) && frame.getSelectedLayerIndex() >= 1) { - g.drawImage(c.getCoucheTwo().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - } - /* if (frame.getSelectedLayerIndex() != 1) - { - image = recalculateAplha(c.getCoucheTwo().getImage(), 1); - g.drawImage(image, x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - }*/ - - if (!isEmpty(c.getCoucheThree().getImage()) && frame.getSelectedLayerIndex() == 2) { - g.drawImage(c.getCoucheThree().getImage(), x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - } - /* if (frame.getSelectedLayerIndex() != 2) - { - image = recalculateAplha(c.getCoucheThree().getImage(), 2); - g.drawImage(image, x + c.getPosX() * 34 + 2, y + c.getPosY() * 34 + 2, 32, 32, null); - }*/ - } - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - private boolean isEmpty(BufferedImage image) { - int allrgba = 0; - - for (int x = 0; x < image.getWidth(); ++x) { - for (int y = 0; y < image.getHeight(); ++y) { - allrgba += image.getRGB(x, y) + 1; - } - } - - return allrgba == 0; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/editor/SpriteComp.java b/src/main/java/fr/ynerant/leveleditor/editor/SpriteComp.java deleted file mode 100644 index 63186db..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/SpriteComp.java +++ /dev/null @@ -1,59 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; - -import javax.swing.*; -import java.awt.*; - -public class SpriteComp extends JComponent { - private static final long serialVersionUID = -6512257366877053285L; - - private final Sprite sprite; - private final int couche; - private boolean selected; - - public SpriteComp(Sprite sprite, int couche) { - super(); - this.sprite = sprite; - this.couche = couche; - this.setMinimumSize(new Dimension(32, 32)); - this.setMaximumSize(new Dimension(32, 32)); - this.setPreferredSize(new Dimension(32, 32)); - this.setSize(new Dimension(32, 32)); - - repaint(); - } - - public Sprite getSprite() { - return sprite; - } - - public int getCouche() { - return couche; - } - - public boolean isSelected() { - return selected; - } - - public void setSelected(boolean selected) { - this.selected = selected; - } - - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - - g.setColor(Color.white); - g.fillRect(0, 0, getWidth(), getHeight()); - g.drawImage(sprite.getImage(), 0, 0, 32, 32, Color.white, null); - - if (isSelected()) { - g.setColor(Color.black); - g.drawLine(0, 0, getWidth() - 1, 0); - g.drawLine(0, 0, 0, getHeight() - 1); - g.drawLine(0, getHeight() - 1, getWidth() - 1, getHeight() - 1); - g.drawLine(getWidth() - 1, 0, getWidth() - 1, getHeight() - 1); - } - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/editor/WrapLayout.java b/src/main/java/fr/ynerant/leveleditor/editor/WrapLayout.java deleted file mode 100644 index 36d402f..0000000 --- a/src/main/java/fr/ynerant/leveleditor/editor/WrapLayout.java +++ /dev/null @@ -1,88 +0,0 @@ -package fr.ynerant.leveleditor.editor; - -import javax.swing.*; -import java.awt.*; - -public class WrapLayout extends FlowLayout { - private static final long serialVersionUID = 8777237960365591646L; - - public WrapLayout(int align) { - super(align); - } - - @Override - public Dimension preferredLayoutSize(Container target) { - return layoutSize(target, true); - } - - @Override - public Dimension minimumLayoutSize(Container target) { - Dimension minimum = layoutSize(target, false); - minimum.width -= (getHgap() + 1); - return minimum; - } - - private Dimension layoutSize(Container target, boolean preferred) { - synchronized (target.getTreeLock()) { - int targetWidth = target.getSize().width; - - if (targetWidth == 0) - targetWidth = Integer.MAX_VALUE; - - int hgap = getHgap(); - int vgap = getVgap(); - Insets insets = target.getInsets(); - int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2); - int maxWidth = targetWidth - horizontalInsetsAndGap; - - Dimension dim = new Dimension(0, 0); - int rowWidth = 0; - int rowHeight = 0; - - int nmembers = target.getComponentCount(); - - for (int i = 0; i < nmembers; i++) { - Component m = target.getComponent(i); - - if (m.isVisible()) { - Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize(); - - if (rowWidth + d.width > maxWidth) { - addRow(dim, rowWidth, rowHeight); - rowWidth = 0; - rowHeight = 0; - } - - if (rowWidth != 0) { - rowWidth += hgap; - } - - rowWidth += d.width; - rowHeight = Math.max(rowHeight, d.height); - } - } - - addRow(dim, rowWidth, rowHeight); - - dim.width += horizontalInsetsAndGap; - dim.height += insets.top + insets.bottom + vgap * 2; - - Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target); - if (scrollPane != null) { - dim.width -= (hgap + 1); - } - - return dim; - } - } - - private void addRow(Dimension dim, int rowWidth, int rowHeight) { - dim.width = Math.max(dim.width, rowWidth); - - if (dim.height > 0) { - dim.height += getVgap(); - } - - dim.height += rowHeight; - } -} \ No newline at end of file diff --git a/src/main/java/fr/ynerant/leveleditor/frame/MainFrame.java b/src/main/java/fr/ynerant/leveleditor/frame/MainFrame.java deleted file mode 100644 index 8464484..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/MainFrame.java +++ /dev/null @@ -1,102 +0,0 @@ -package fr.ynerant.leveleditor.frame; - -import fr.ynerant.leveleditor.client.main.Main; -import fr.ynerant.leveleditor.frame.listeners.ChangeLAFListener; -import fr.ynerant.leveleditor.frame.listeners.CreateMapListener; -import fr.ynerant.leveleditor.frame.listeners.OpenMapListener; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; - -/** - * Fenêtre principale du jeu - * - * @author ÿnérant - */ -public class MainFrame extends JFrame { - /** - * ID de série - */ - private static final long serialVersionUID = -3168760121879418534L; - - /** - * Instance unique principale - * - * @see #MainFrame() - * @see #getInstance() - */ - private static MainFrame INSTANCE; - - /** - * Constructeur - * - * @see Main#launchFrame() - */ - @SuppressWarnings("JavadocReference") - private MainFrame() { - super(); - System.out.println("Initialisation de la fen\u00eatre"); - this.setTitle("Level Editor"); - this.setPreferredSize(new Dimension(1000, 800)); - this.setSize(800, 700); - this.setLocationRelativeTo(null); - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JMenu fichier = new JMenu("Fichier"); - fichier.setMnemonic(KeyEvent.VK_F + KeyEvent.ALT_DOWN_MASK); - JMenu display = new JMenu("Affichage"); - display.setMnemonic(KeyEvent.VK_A + KeyEvent.ALT_DOWN_MASK); - - JMenuItem createMap = new JMenuItem("Cr\u00e9er"); - createMap.addActionListener(new CreateMapListener()); - JMenu editMaps = new JMenu("Cartes"); - editMaps.add(createMap); - JMenuItem openMap = new JMenuItem("Ouvrir"); - openMap.addActionListener(new OpenMapListener()); - editMaps.add(openMap); - - fichier.add(editMaps); - - JMenuItem systemLAF = new JMenuItem("Apparence syst\u00e8me"); - systemLAF.addActionListener(new ChangeLAFListener(systemLAF, this)); - JMenu changeLAF = new JMenu("Modfier l'apparence"); - changeLAF.add(systemLAF); - JMenuItem javaLAF = new JMenuItem("Apparence Java"); - javaLAF.addActionListener(new ChangeLAFListener(javaLAF, this)); - changeLAF.add(javaLAF); - JMenuItem darkLAF = new JMenuItem("Apparence sombre"); - darkLAF.addActionListener(new ChangeLAFListener(darkLAF, this)); - changeLAF.add(darkLAF); - - display.add(changeLAF); - - JMenuBar menuBar = new JMenuBar(); - menuBar.add(fichier); - menuBar.add(display); - - this.setJMenuBar(menuBar); - - JButton start = new JButton("Commencer la partie !"); - start.addActionListener(actionEvent -> { - if (Main.launchGameMode()) - getInstance().dispose(); - }); - this.setContentPane(start); - } - - /** - * Cet accesseur renvoie l'accesseur unique de la classe - * - * @return l'instance unique de la classe - * @see #INSTANCE - * @see #MainFrame() - */ - public static MainFrame getInstance() { - if (INSTANCE == null) - return INSTANCE = new MainFrame(); - - return INSTANCE; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.java deleted file mode 100644 index 023a74f..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.java +++ /dev/null @@ -1,49 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.frame.MainFrame; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class ChangeLAFListener implements ActionListener { - private final JMenuItem item; - private final JFrame frame; - - public ChangeLAFListener(JMenuItem LAF, MainFrame f) { - this.item = LAF; - this.frame = f; - } - - @Override - public void actionPerformed(ActionEvent event) { - if (item.getText().toLowerCase().contains("sys")) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { - new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace(); - System.err.print("Caused by "); - e.printStackTrace(); - } - SwingUtilities.updateComponentTreeUI(frame); - } else if (item.getText().toLowerCase().contains("java")) { - try { - UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } catch (Exception e) { - new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace(); - System.err.print("Caused by "); - e.printStackTrace(); - } - SwingUtilities.updateComponentTreeUI(frame); - } else if (item.getText().toLowerCase().contains("sombre")) { - try { - UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); - } catch (Exception e) { - new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace(); - System.err.print("Caused by "); - e.printStackTrace(); - } - SwingUtilities.updateComponentTreeUI(frame); - } - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.java deleted file mode 100644 index bd229ef..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.api.editor.Case; -import fr.ynerant.leveleditor.api.editor.Collision; -import fr.ynerant.leveleditor.editor.CollidPanel; -import fr.ynerant.leveleditor.editor.EditorFrame; -import fr.ynerant.leveleditor.editor.Map; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -public class CollidMapMouseListener extends MouseAdapter { - private final EditorFrame frame; - private final CollidPanel panel; - - public CollidMapMouseListener(CollidPanel panel, EditorFrame frame) { - this.frame = frame; - this.panel = panel; - } - - public EditorFrame getFrame() { - return frame; - } - - @Override - public void mouseReleased(MouseEvent event) { - Map map = getFrame().getMap(); - - int x = panel.getWidth() / 2 - map.getFont().getWidth(); - int y = panel.getHeight() / 2 - map.getFont().getHeight(); - Case c; - - if ((c = map.getCase((event.getX() - x + 2) / 34, (event.getY() - y + 2) / 34)) != null && event.getX() - x >= 2 && event.getY() - y >= 2) { - int colIndex = c.getCollision().ordinal(); - int newColIndex = colIndex + 1; - if (newColIndex >= Collision.values().length) - newColIndex = 0; - Collision col = Collision.values()[newColIndex]; - Case n = Case.create(c.getPosX(), c.getPosY(), c.getCoucheOne(), c.getCoucheTwo(), c.getCoucheThree(), col); - - map.setCase((event.getX() - x + 2) / 34, (event.getY() - y + 2) / 34, n); - panel.repaint(); - } - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.java deleted file mode 100644 index 1403be4..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.client.main.Main; -import fr.ynerant.leveleditor.frame.MainFrame; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * @author ÿnérant - */ -public class CreateMapListener implements ActionListener { - /* !CodeTemplates.overridecomment.nonjd! - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - @Override - public void actionPerformed(ActionEvent event) { - if (Main.launchEditMode()) - MainFrame.getInstance().dispose(); - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.java deleted file mode 100644 index 705e83f..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.java +++ /dev/null @@ -1,95 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.api.editor.Case; -import fr.ynerant.leveleditor.editor.EditorFrame; -import fr.ynerant.leveleditor.editor.Map; -import fr.ynerant.leveleditor.editor.MapPanel; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -public class MapMouseListener extends MouseAdapter { - private final EditorFrame frame; - private final MapPanel panel; - - public MapMouseListener(MapPanel panel, EditorFrame frame) { - this.frame = frame; - this.panel = panel; - } - - public EditorFrame getFrame() { - return frame; - } - - @Override - public void mouseClicked(MouseEvent event) { - if (frame.getSelectedPaintingMode() == 0) { - Map map = getFrame().getMap(); - - int x = panel.getWidth() / 2 - map.getFont().getWidth(); - int y = panel.getHeight() / 2 - map.getFont().getHeight(); - Case c; - - if ((c = map.getCase((event.getX() - x + 2) / 34, (event.getY() - y + 2) / 34)) != null && event.getX() - x >= 2 && event.getY() - y >= 2) { - if (getFrame().getSelectedSprite() != null) { - Case n; - - switch (getFrame().getSelectedSprite().getCouche()) { - case 0: - n = Case.create(c.getPosX(), c.getPosY(), getFrame().getSelectedSprite().getSprite(), c.getCoucheTwo(), c.getCoucheThree(), c.getCollision()); - break; - case 1: - n = Case.create(c.getPosX(), c.getPosY(), c.getCoucheOne(), getFrame().getSelectedSprite().getSprite(), c.getCoucheThree(), c.getCollision()); - break; - case 2: - n = Case.create(c.getPosX(), c.getPosY(), c.getCoucheOne(), c.getCoucheTwo(), getFrame().getSelectedSprite().getSprite(), c.getCollision()); - break; - default: - n = c; - break; - } - - map.setCase(n.getPosX(), n.getPosY(), n); - panel.repaint(); - } - } - } else if (frame.getSelectedPaintingMode() == 1) { - for (Case c : getFrame().getMap().getAllCases()) { - Map map = getFrame().getMap(); - - if (getFrame().getSelectedSprite() != null) { - if (getFrame().getSelectedSprite().getCouche() - 1 > getFrame().getSelectedLayerIndex()) - return; - - Case n; - - switch (getFrame().getSelectedSprite().getCouche()) { - case 0: - n = Case.create(c.getPosX(), c.getPosY(), getFrame().getSelectedSprite().getSprite(), c.getCoucheTwo(), c.getCoucheThree(), c.getCollision()); - break; - case 1: - n = Case.create(c.getPosX(), c.getPosY(), c.getCoucheOne(), getFrame().getSelectedSprite().getSprite(), c.getCoucheThree(), c.getCollision()); - break; - case 2: - n = Case.create(c.getPosX(), c.getPosY(), c.getCoucheOne(), c.getCoucheTwo(), getFrame().getSelectedSprite().getSprite(), c.getCollision()); - break; - default: - n = c; - break; - } - - map.setCase(n.getPosX(), n.getPosY(), n); - } - } - - panel.repaint(); - } - } - - @Override - public void mouseDragged(MouseEvent event) { - if (frame.getSelectedPaintingMode() == 0) { - mouseClicked(event); - } - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.java deleted file mode 100644 index 5976e6e..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.api.editor.EditorAPI; -import fr.ynerant.leveleditor.frame.MainFrame; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class OpenMapListener implements ActionListener { - /* !CodeTemplates.overridecomment.nonjd! - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - @Override - public void actionPerformed(ActionEvent event) { - if (EditorAPI.open() != null) - MainFrame.getInstance().dispose(); - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.java b/src/main/java/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.java deleted file mode 100644 index b9e2c03..0000000 --- a/src/main/java/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.ynerant.leveleditor.frame.listeners; - -import fr.ynerant.leveleditor.editor.EditorFrame; -import fr.ynerant.leveleditor.editor.SpriteComp; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -public class SpriteMouseListener extends MouseAdapter { - private final SpriteComp sprite; - private final EditorFrame frame; - - public SpriteMouseListener(SpriteComp sprc, EditorFrame frame) { - this.sprite = sprc; - this.frame = frame; - } - - @Override - public void mouseReleased(MouseEvent event) { - if (frame.getSelectedSprite() != null) { - frame.getSelectedSprite().setSelected(false); - frame.getSelectedSprite().repaint(); - } - frame.setSelectedSprite(sprite); - sprite.setSelected(true); - sprite.repaint(); - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/GameFrame.java b/src/main/java/fr/ynerant/leveleditor/game/GameFrame.java deleted file mode 100644 index a4ed1ee..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/GameFrame.java +++ /dev/null @@ -1,237 +0,0 @@ -package fr.ynerant.leveleditor.game; - -import fr.ynerant.leveleditor.api.editor.Collision; -import fr.ynerant.leveleditor.api.editor.RawCase; -import fr.ynerant.leveleditor.api.editor.RawMap; -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; -import fr.ynerant.leveleditor.editor.CollidPanel; -import fr.ynerant.leveleditor.game.mobs.Mob; -import fr.ynerant.leveleditor.game.towers.AutoTower; -import fr.ynerant.leveleditor.game.towers.BasicTower; -import fr.ynerant.leveleditor.game.towers.NullTower; -import fr.ynerant.leveleditor.game.towers.Tower; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; -import java.util.ArrayList; -import java.util.Random; - -public class GameFrame extends JFrame { - private final Random RANDOM = new Random(); - private final RawMap map; - - private int round = 0; - private int hp = 5; - private int reward = 20; - private final List mobs = new ArrayList<>(); - private final List towers = new ArrayList<>(); - - private final JRadioButton basicTower; - private final JRadioButton nullTower; - private final JRadioButton autoTower; - private final JLabel waveLabel; - private final JLabel nbMobsLabel; - private final JLabel hpLabel; - private final JLabel rewardLabel; - private final JLabel winLabel; - - public GameFrame(RawMap map) { - super("Jeu"); - - this.map = map; - this.setSize(600, 600); - this.setPreferredSize(getSize()); - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - this.setLocationRelativeTo(null); - - JPanel root = new JPanel(); - root.setLayout(new BorderLayout()); - this.setContentPane(root); - - JPanel pane = new JPanel(); - pane.setLayout(new GridLayout(8, 1)); - root.add(pane, BorderLayout.SOUTH); - - Grid grid = new Grid(); - grid.setSize(map.getWidth(), map.getHeight()); - grid.setPreferredSize(grid.getSize()); - grid.setMinimumSize(grid.getSize()); - grid.setMaximumSize(grid.getSize()); - root.add(grid, BorderLayout.CENTER); - - ButtonGroup towerSelect = new ButtonGroup(); - - basicTower = new JRadioButton("Tour basique (" + new BasicTower(0, 0).getPrice() + " pièces)"); - basicTower.setSelected(true); - towerSelect.add(basicTower); - pane.add(basicTower); - - nullTower = new JRadioButton("Tour nulle (" + new NullTower(0, 0).getPrice() + " pièces)"); - towerSelect.add(nullTower); - pane.add(nullTower); - - autoTower = new JRadioButton("Tour automatique (" + new AutoTower(0, 0).getPrice() + " pièces)"); - towerSelect.add(autoTower); - pane.add(autoTower); - - waveLabel = new JLabel(); - pane.add(waveLabel); - - nbMobsLabel = new JLabel(); - pane.add(nbMobsLabel); - - hpLabel = new JLabel(); - pane.add(hpLabel); - - rewardLabel = new JLabel(); - pane.add(rewardLabel); - - winLabel = new JLabel(); - pane.add(winLabel); - - setVisible(true); - - new Thread(() -> { - while (hp > 0 && (round < 4 || !mobs.isEmpty())) { - tick(); - - try { - Thread.sleep(50L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }).start(); - - repaint(); - } - - public RawMap getMap() { - return map; - } - - public void tick() { - if (mobs.isEmpty() && round < 4) { - ++round; - int nb_mobs = round * (RANDOM.nextInt(16) + 1); - for (int i = 1; i <= nb_mobs; ++i) { - Mob mob = Mob.getRandomMob(); - do - mob.move(RANDOM.nextInt(getMap().getWidth() / 16), RANDOM.nextInt(getMap().getHeight() / 16)); - while (getMap().getCase(mob.getX(), mob.getY()).getCollision() != Collision.ANY); - getMap().getCase(mob.getX(), mob.getY()).setCollision(Collision.PARTIAL); - mobs.add(mob); - } - } - - for (Tower tower : towers) { - for (Mob mob : tower.filterDetectedMobs(mobs)) - mob.hit(tower.getDamagePerShot()); - } - - for (Mob mob : new ArrayList<>(mobs)) { - getMap().getCase(mob.getX(), mob.getY()).setCollision(Collision.ANY); - mob.tick(this); - if (mob.getX() < 0 || mob.isDead()) { - mobs.remove(mob); - if (mob.getX() < 0) { - --hp; - if (hp == 0) { - winLabel.setForeground(Color.red); - winLabel.setText("Vous avez perdu !"); - return; - } - } - else - reward += mob.getReward(); - } - else - getMap().getCase(mob.getX(), mob.getY()).setCollision(Collision.PARTIAL); - } - - waveLabel.setText("Vague " + round); - nbMobsLabel.setText(mobs.size() + " mob" + (mobs.size() > 1 ? "s" : "") + " restant" + (mobs.size() > 1 ? "s" : "")); - hpLabel.setText("Points de vie : " + hp); - rewardLabel.setText("Butin : " + reward); - - if (round == 4 && mobs.isEmpty()) { - winLabel.setForeground(Color.green.darker()); - winLabel.setText("Vous avez gagné !"); - } - } - - private class Grid extends JComponent implements MouseListener { - public Grid() { - addMouseListener(this); - } - - @Override - protected void paintComponent(Graphics _g) { - Graphics2D g = (Graphics2D) _g; - - if (getMap().getFont() != null) - g.drawImage(getMap().getFont(), null, null); - - SpriteRegister.refreshAllSprites(); - int SPRITE_SIZE = 32; - for (RawCase c : getMap().getCases()) { - Sprite s1 = SpriteRegister.getCategory(c.getCoucheOne().getCategory()).getSprites().get(c.getCoucheOne().getIndex()); - Sprite s2 = SpriteRegister.getCategory(c.getCoucheTwo().getCategory()).getSprites().get(c.getCoucheTwo().getIndex()); - Sprite s3 = SpriteRegister.getCategory(c.getCoucheThree().getCategory()).getSprites().get(c.getCoucheThree().getIndex()); - g.drawImage(s1.getImage(), SPRITE_SIZE * c.getPosX(), SPRITE_SIZE * c.getPosY(), SPRITE_SIZE, SPRITE_SIZE, Color.white, null); - if (!CollidPanel.isEmpty(s2.getImage())) - g.drawImage(s2.getImage(), SPRITE_SIZE * c.getPosX(), SPRITE_SIZE * c.getPosY(), SPRITE_SIZE, SPRITE_SIZE, null, null); - if (!CollidPanel.isEmpty(s3.getImage())) - g.drawImage(s3.getImage(), SPRITE_SIZE * c.getPosX(), SPRITE_SIZE * c.getPosY(), SPRITE_SIZE, SPRITE_SIZE, null, null); - } - - for (Mob mob : new ArrayList<>(mobs)) { - Sprite s = mob.getSprite(); - g.drawImage(s.getImage(), SPRITE_SIZE * mob.getX(), SPRITE_SIZE * mob.getY(), SPRITE_SIZE, SPRITE_SIZE, null, null); - } - - for (Tower tower : towers) { - Sprite s = tower.getSprite(); - g.drawImage(s.getImage(), SPRITE_SIZE * tower.getX(), SPRITE_SIZE * tower.getY(), SPRITE_SIZE, SPRITE_SIZE, null, null); - } - - repaint(); - } - - @Override - public void mouseClicked(MouseEvent event) {} - - @Override - public void mousePressed(MouseEvent event) {} - - @Override - public void mouseReleased(MouseEvent event) { - int x = event.getX() / 32, y = event.getY() / 32; - Tower tower = basicTower.isSelected() ? new BasicTower(x, y) : - nullTower.isSelected() ? new NullTower(x, y) : - autoTower.isSelected() ? new AutoTower(x, y) : - null; - if (tower == null || tower.getPrice() > reward) - return; - - RawCase c = getMap().getCase(x, y); - if (c == null || c.getCollision() != Collision.ANY) - return; - c.setCollision(Collision.FULL); - - reward -= tower.getPrice(); - towers.add(tower); - } - - @Override - public void mouseEntered(MouseEvent event) {} - - @Override - public void mouseExited(MouseEvent event) {} - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob.java b/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob.java deleted file mode 100644 index 724d6aa..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob.java +++ /dev/null @@ -1,133 +0,0 @@ -package fr.ynerant.leveleditor.game.mobs; - -import fr.ynerant.leveleditor.api.editor.RawCase; -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; -import fr.ynerant.leveleditor.game.GameFrame; - -import java.util.*; - -public abstract class Mob { - private static final Random RANDOM = new Random(); - private Sprite sprite; - private int x; - private int y; - private int hp; - private long tickRemains; - - public Mob() { - this.hp = getMaxHP(); - this.tickRemains = getSlowness(); - } - - public abstract int getMaxHP(); - - public abstract long getSlowness(); - - public abstract int getReward(); - - public abstract String getName(); - - public Sprite getSprite() { - if (sprite == null) - sprite = SpriteRegister.getCategory(getName()).getSprites().get(0); - return sprite; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public void move(int x, int y) { - this.x = x; - this.y = y; - } - - public int getHP() { - return hp; - } - - public boolean isDead() { - return hp <= 0; - } - - public void setHP(int hp) { - this.hp = hp; - } - - public boolean hit(int damage) { - if (!isDead()) { - this.hp -= damage; - return true; - } - - return false; - } - - public void tick(GameFrame game) { - if (tickRemains > 0) - --tickRemains; - else { - tickRemains = getSlowness(); - RawCase current = game.getMap().getCase(getX(), getY()); - - if (current.getPosX() == 0) { - move(-1, getY()); - return; - } - - List visited = new ArrayList<>(); - Queue queue = new ArrayDeque<>(); - Map pred = new HashMap<>(); - RawCase last = null; - queue.add(current); - while (!queue.isEmpty()) { - RawCase visiting = queue.poll(); - visited.add(visiting); - for (RawCase neighbour : game.getMap().getNeighbours(visiting)) { - if (visited.contains(neighbour)) - continue; - - pred.put(neighbour, visiting); - queue.add(neighbour); - - if (neighbour.getPosX() == 0) { - last = neighbour; - queue.clear(); - break; - } - } - - if (last != null) { - while (pred.get(last) != current) - last = pred.get(last); - move(last.getPosX(), last.getPosY()); - } - } - } - } - - @Override - public String toString() { - return "Mob{" + - "sprite=" + sprite + - ", x=" + x + - ", y=" + y + - '}'; - } - - public static Mob getRandomMob() { - switch (RANDOM.nextInt(3)) { - case 1: - return new Mob1(); - case 2: - return new Mob2(); - default: - return new MobCancer(); - } - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob1.java b/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob1.java deleted file mode 100644 index 611fcad..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob1.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.ynerant.leveleditor.game.mobs; - -public class Mob1 extends Mob { - @Override - public int getMaxHP() { - return 2; - } - - @Override - public long getSlowness() { - return 60; - } - - @Override - public int getReward() { - return 10; - } - - @Override - public String getName() { - return "mob1"; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob2.java b/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob2.java deleted file mode 100644 index 750999f..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/mobs/Mob2.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.ynerant.leveleditor.game.mobs; - -public class Mob2 extends Mob { - @Override - public int getMaxHP() { - return 6; - } - - @Override - public long getSlowness() { - return 20; - } - - @Override - public int getReward() { - return 20; - } - - @Override - public String getName() { - return "mob2"; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/mobs/MobCancer.java b/src/main/java/fr/ynerant/leveleditor/game/mobs/MobCancer.java deleted file mode 100644 index d7571b0..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/mobs/MobCancer.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.ynerant.leveleditor.game.mobs; - -public class MobCancer extends Mob { - @Override - public int getMaxHP() { - return 50; - } - - @Override - public long getSlowness() { - return 100; - } - - @Override - public int getReward() { - return 100; - } - - @Override - public String getName() { - return "mobcancer"; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/towers/AutoTower.java b/src/main/java/fr/ynerant/leveleditor/game/towers/AutoTower.java deleted file mode 100644 index 28dc7c8..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/towers/AutoTower.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.ynerant.leveleditor.game.towers; - -import fr.ynerant.leveleditor.game.mobs.Mob; - -import java.util.Collection; - -public class AutoTower extends Tower { - public AutoTower(int x, int y) { - super(x, y); - } - - @Override - public String getName() { - return "autotower"; - } - - @Override - public int getDamagePerShot() { - return 20; - } - - @Override - public long getPeriod() { - return 10; - } - - @Override - public int getPrice() { - return 142; - } - - @Override - Collection _filterDetectedMobs(Collection mobs) { - return mobs; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/towers/BasicTower.java b/src/main/java/fr/ynerant/leveleditor/game/towers/BasicTower.java deleted file mode 100644 index 4099109..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/towers/BasicTower.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.ynerant.leveleditor.game.towers; - -import fr.ynerant.leveleditor.game.mobs.Mob; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class BasicTower extends Tower { - public BasicTower(int x, int y) { - super(x, y); - } - - @Override - public String getName() { - return "basictower"; - } - - @Override - public int getDamagePerShot() { - return 1; - } - - @Override - public long getPeriod() { - return 5; - } - - @Override - public int getPrice() { - return 10; - } - - @Override - Collection _filterDetectedMobs(Collection mobs) { - List filtered = new ArrayList<>(); - - for (Mob mob : mobs) { - if ((mob.getX() == getX() || mob.getY() == getY()) - && Math.abs(mob.getX() - getX()) <= 3 && Math.abs(mob.getY() - getY()) <= 3) - filtered.add(mob); - } - - return filtered; - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/towers/NullTower.java b/src/main/java/fr/ynerant/leveleditor/game/towers/NullTower.java deleted file mode 100644 index 7f08fbd..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/towers/NullTower.java +++ /dev/null @@ -1,37 +0,0 @@ -package fr.ynerant.leveleditor.game.towers; - -import fr.ynerant.leveleditor.game.mobs.Mob; - -import java.util.ArrayList; -import java.util.Collection; - -public class NullTower extends Tower { - public NullTower(int x, int y) { - super(x, y); - } - - @Override - public String getName() { - return "nulltower"; - } - - @Override - public int getDamagePerShot() { - return Integer.MAX_VALUE; - } - - @Override - public long getPeriod() { - return 1; - } - - @Override - public int getPrice() { - return 5; - } - - @Override - Collection _filterDetectedMobs(Collection mobs) { - return new ArrayList<>(); - } -} diff --git a/src/main/java/fr/ynerant/leveleditor/game/towers/Tower.java b/src/main/java/fr/ynerant/leveleditor/game/towers/Tower.java deleted file mode 100644 index 619bf5d..0000000 --- a/src/main/java/fr/ynerant/leveleditor/game/towers/Tower.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.ynerant.leveleditor.game.towers; - -import fr.ynerant.leveleditor.api.editor.sprites.Sprite; -import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister; -import fr.ynerant.leveleditor.game.mobs.Mob; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; - -public abstract class Tower { - private final Sprite sprite; - private final int x; - private final int y; - private long remainingTicks; - - public Tower(int x, int y) { - this.sprite = SpriteRegister.getCategory(getName()).getSprites().get(0); - this.x = x; - this.y = y; - } - - private static final Random RANDOM = new Random(); - - public Sprite getSprite() { - return sprite; - } - - public abstract String getName(); - - public abstract int getDamagePerShot(); - - public abstract long getPeriod(); - - public abstract int getPrice(); - - abstract Collection _filterDetectedMobs(Collection mobs); - - public Collection filterDetectedMobs(Collection mobs) { - if (remainingTicks > 0) { - --remainingTicks; - return new ArrayList<>(); - } - else { - remainingTicks = getPeriod(); - return _filterDetectedMobs(mobs); - } - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } -} diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 09456ce..0000000 --- a/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: fr.ynerant.leveleditor.client.main.Main - diff --git a/src/main/resources/assets/leveleditor/textures/sprites/basictower.png b/src/main/resources/assets/leveleditor/textures/sprites/basictower.png index 89f32ad..84b1271 100644 Binary files a/src/main/resources/assets/leveleditor/textures/sprites/basictower.png and b/src/main/resources/assets/leveleditor/textures/sprites/basictower.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/explodertower.png b/src/main/resources/assets/leveleditor/textures/sprites/explodertower.png new file mode 100644 index 0000000..dc70397 Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/explodertower.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/nulltower.png b/src/main/resources/assets/leveleditor/textures/sprites/freezertower.png similarity index 100% rename from src/main/resources/assets/leveleditor/textures/sprites/nulltower.png rename to src/main/resources/assets/leveleditor/textures/sprites/freezertower.png diff --git a/src/main/resources/assets/leveleditor/textures/sprites/autotower.png b/src/main/resources/assets/leveleditor/textures/sprites/lasertower.png similarity index 100% rename from src/main/resources/assets/leveleditor/textures/sprites/autotower.png rename to src/main/resources/assets/leveleditor/textures/sprites/lasertower.png diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mob1.png b/src/main/resources/assets/leveleditor/textures/sprites/mob1.png index 3874744..67b1c67 100644 Binary files a/src/main/resources/assets/leveleditor/textures/sprites/mob1.png and b/src/main/resources/assets/leveleditor/textures/sprites/mob1.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mob2.png b/src/main/resources/assets/leveleditor/textures/sprites/mob2.png index 1f0471f..a91a8f2 100644 Binary files a/src/main/resources/assets/leveleditor/textures/sprites/mob2.png and b/src/main/resources/assets/leveleditor/textures/sprites/mob2.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mobbreaker.png b/src/main/resources/assets/leveleditor/textures/sprites/mobbreaker.png new file mode 100644 index 0000000..82210a9 Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/mobbreaker.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mobhealer.png b/src/main/resources/assets/leveleditor/textures/sprites/mobhealer.png new file mode 100644 index 0000000..64bc559 Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/mobhealer.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mobspeeder.png b/src/main/resources/assets/leveleditor/textures/sprites/mobspeeder.png new file mode 100644 index 0000000..ef6cba0 Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/mobspeeder.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/mobcancer.png b/src/main/resources/assets/leveleditor/textures/sprites/mobstrong.png similarity index 100% rename from src/main/resources/assets/leveleditor/textures/sprites/mobcancer.png rename to src/main/resources/assets/leveleditor/textures/sprites/mobstrong.png diff --git a/src/main/resources/assets/leveleditor/textures/sprites/sprites.json b/src/main/resources/assets/leveleditor/textures/sprites/sprites.json index 84e484b..6f928f6 100644 --- a/src/main/resources/assets/leveleditor/textures/sprites/sprites.json +++ b/src/main/resources/assets/leveleditor/textures/sprites/sprites.json @@ -325,16 +325,34 @@ "mob2": [ [0, 0] ], - "mobcancer": [ + "mobstrong": [ + [0, 0] + ], + "mobhealer": [ + [0, 0] + ], + "mobbreaker": [ + [0, 0] + ], + "mobspeeder": [ [0, 0] ], "basictower": [ [0, 0] ], - "nulltower": [ + "walltower": [ [0, 0] ], - "autotower": [ + "freezertower": [ + [0, 0] + ], + "explodertower": [ + [0, 0] + ], + "upgradetower": [ + [0, 0] + ], + "lasertower": [ [0, 0] ] } \ No newline at end of file diff --git a/src/main/resources/assets/leveleditor/textures/sprites/upgradetower.png b/src/main/resources/assets/leveleditor/textures/sprites/upgradetower.png new file mode 100644 index 0000000..8decd3f Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/upgradetower.png differ diff --git a/src/main/resources/assets/leveleditor/textures/sprites/walltower.png b/src/main/resources/assets/leveleditor/textures/sprites/walltower.png new file mode 100644 index 0000000..c44a960 Binary files /dev/null and b/src/main/resources/assets/leveleditor/textures/sprites/walltower.png differ diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml deleted file mode 100644 index 8736eb0..0000000 --- a/src/main/resources/log4j2.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/Case.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/Case.scala new file mode 100644 index 0000000..f084bd7 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/Case.scala @@ -0,0 +1,40 @@ +package fr.ynerant.leveleditor.api.editor + +import fr.ynerant.leveleditor.api.editor.sprites.Sprite + + +object Case { + def create(posX: Int, posY: Int, couche1: Sprite, couche2: Sprite, couche3: Sprite, collision: String): Case = { + val c = new Case + c.x = posX + c.y = posY + c.couche1 = couche1 + c.couche2 = couche2 + c.couche3 = couche3 + c.collision = collision + c + } +} + +class Case { + private var x = 0 + private var y = 0 + private var couche1 = null: Sprite + private var couche2 = null: Sprite + private var couche3 = null: Sprite + private var collision = null: String + + def getPosX: Int = x + + def getPosY: Int = y + + def getCoucheOne: Sprite = couche1 + + def getCoucheTwo: Sprite = couche2 + + def getCoucheThree: Sprite = couche3 + + def getCollision: String = collision + + override def toString: String = "{Case x=" + x + " y=" + y + " couche1=" + couche1 + " couche2=" + couche2 + " couche3=" + couche3 + " collision=" + collision.toString.toUpperCase + "}\n" +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/Collision.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/Collision.scala new file mode 100644 index 0000000..5de47e7 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/Collision.scala @@ -0,0 +1,9 @@ +package fr.ynerant.leveleditor.api.editor + +object Collision { + val FULL: String = "FULL" + val PARTIAL: String = "PARTIAL" + val ANY: String = "ANY" + + val values: IndexedSeq[String] = IndexedSeq(FULL, PARTIAL, ANY) +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/EditorAPI.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/EditorAPI.scala new file mode 100644 index 0000000..e107a2f --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/EditorAPI.scala @@ -0,0 +1,145 @@ +package fr.ynerant.leveleditor.api.editor + +import java.awt.Color +import java.awt.image.BufferedImage +import java.io._ +import java.nio.charset.StandardCharsets +import java.util.zip.{GZIPInputStream, GZIPOutputStream} + +import fr.ynerant.leveleditor.editor.GMap +import javax.swing.JFileChooser +import javax.swing.filechooser.FileNameExtensionFilter +import net.liftweb.json._ + +object EditorAPI { + private var LAST_FILE = null: File + + def toRawMap(width: Int, height: Int): RawMap = { + var cases = Nil: List[RawCase] + var y = 1 + while ( { + y < height + }) { + var x = 1 + while ( { + x < width + }) { + val c = RawCase.create(x / 16, y / 16, RawSprite.BLANK, RawSprite.BLANK, RawSprite.BLANK, Collision.ANY) + cases ::= c + + x += 16 + } + + y += 16 + } + RawMap.create(cases, width, height) + } + + def createJFC: JFileChooser = { + val jfc = new JFileChooser + jfc.setFileFilter(new FileNameExtensionFilter("Fichiers monde (*.gmap, *.dat)", "gmap", "dat")) + jfc.setFileHidingEnabled(true) + jfc.setFileSelectionMode(JFileChooser.FILES_ONLY) + val dir = new File("maps") + assert(dir.isDirectory || dir.mkdirs) + jfc.setCurrentDirectory(dir) + jfc + } + + def saveAs(map: RawMap): Unit = { + val jfc = createJFC + var file = null: File + jfc.showSaveDialog(null) + file = jfc.getSelectedFile + if (file == null) return + if (!file.getName.toLowerCase.endsWith(".gmap") && !file.getName.toLowerCase.endsWith(".dat")) file = new File(file.getParentFile, file.getName + ".gmap") + LAST_FILE = file + save(file, map) + } + + def save(map: RawMap): Unit = { + if (LAST_FILE != null) save(LAST_FILE, map) + else saveAs(map) + } + + def save(file: File, map: RawMap): Unit = { + implicit val formats: DefaultFormats.type = DefaultFormats + val json = Serialization.writePretty(map) + try { + assert(file.exists() || file.createNewFile) + val bos = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(file))) + bos.write(json.getBytes(StandardCharsets.UTF_8)) + bos.close() + } catch { + case ex: IOException => + ex.printStackTrace() + } + } + + def open: GMap = { + val jfc = createJFC + var file = null: File + jfc.showOpenDialog(null) + file = jfc.getSelectedFile + if (file == null) return null + LAST_FILE = file + open(file) + } + + def getRawMap(f: File): RawMap = { + var json = null: String + try { + val gis = new GZIPInputStream(new BufferedInputStream(new FileInputStream(f))) + val bytes = new Array[Byte](512 * 1024) + var count = 0 + val text = new StringBuilder + while ( { + count = gis.read(bytes) + count != -1 + }) text.append(new String(bytes, 0, count, StandardCharsets.UTF_8)) + gis.close() + json = text.toString + } catch { + case e: IOException => + e.printStackTrace() + } + implicit val formats: DefaultFormats.type = DefaultFormats + parse(json).extract[RawMap] + } + + def open(f: File): GMap = open(getRawMap(f)) + + def open(map: RawMap): GMap = { + if (map.getFont == null) { + val baseWidth = map.getWidth + val baseHeight = map.getHeight + val width = baseWidth + (baseWidth / 16) + 1 + val height = baseHeight + (baseHeight / 16) + 1 + val image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) + val g = image.createGraphics + g.setColor(Color.white) + g.fillRect(0, 0, width, height) + g.setColor(Color.black) + g.drawLine(0, 0, width, 0) + g.drawLine(0, 0, 0, height) + var x = 17 + while ( { + x <= width + }) { + g.drawLine(x, 0, x, height) + + x += 17 + } + var y = 17 + while ( { + y <= height + }) { + g.drawLine(0, y, width, y) + + y += 17 + } + map.setFont(image) + } + new GMap(map) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/RawCase.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawCase.scala new file mode 100644 index 0000000..88b038c --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawCase.scala @@ -0,0 +1,29 @@ +package fr.ynerant.leveleditor.api.editor + +object RawCase { + def create(posX: Int, posY: Int, couche1: RawSprite, couche2: RawSprite, couche3: RawSprite, collision: String): RawCase = { + new RawCase(posX, posY, couche1, couche2, couche3, collision) + } + + def create(c: Case): RawCase = { + new RawCase(c.getPosX, c.getPosY, RawSprite.create(c.getCoucheOne), RawSprite.create(c.getCoucheTwo), RawSprite.create(c.getCoucheThree), c.getCollision) + } +} + +case class RawCase(var x: Int, var y: Int, var couche1: RawSprite, var couche2: RawSprite, var couche3: RawSprite, var collision: String) { + def getPosX: Int = x + + def getPosY: Int = y + + def getCoucheOne: RawSprite = couche1 + + def getCoucheTwo: RawSprite = couche2 + + def getCoucheThree: RawSprite = couche3 + + def getCollision: String = collision // FULL, PARTIAL or ANY + + def setCollision(collision: String): Unit = { + this.collision = collision + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/RawMap.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawMap.scala new file mode 100644 index 0000000..810cdb4 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawMap.scala @@ -0,0 +1,58 @@ +package fr.ynerant.leveleditor.api.editor + +import java.awt.image.BufferedImage + +import fr.ynerant.leveleditor.editor.GMap +import net.liftweb.json._ + + +object RawMap { + def create(cases: List[RawCase], width: Int, height: Int): RawMap = { + new RawMap(cases, width, height) + } + + def create(map: GMap): RawMap = { + val raw = new RawMap(Nil, map.getWidth, map.getHeight) + map.getAllCases.foreach(c => raw.cases ::= RawCase.create(c)) + raw + } +} + +case class RawMap(var cases: List[RawCase], var width: Int, var height: Int) { + private var cases_map = null: Map[Integer, RawCase] + private var font = null: BufferedImage + + def getNeighbours(c: RawCase): Iterable[RawCase] = { + var list = Nil: List[RawCase] + list ::= getCase(c.getPosX, c.getPosY - 1) + list ::= getCase(c.getPosX + 1, c.getPosY) + list ::= getCase(c.getPosX, c.getPosY + 1) + list ::= getCase(c.getPosX - 1, c.getPosY) + list.filter((_c: RawCase) => _c != null) + } + + def getCase(x: Int, y: Int): RawCase = { + if (cases_map == null) { + cases_map = Map() + getCases.foreach(c => cases_map = cases_map.updated(c.getPosY * width + c.getPosX, c)) + } + cases_map.getOrElse(y * getWidth + x, null) + } + + def getCases: List[RawCase] = cases + + def getWidth: Int = width + + def getHeight: Int = height + + def getFont: BufferedImage = font + + def setFont(font: BufferedImage): Unit = { + this.font = font + } + + override def toString: String = { + implicit val formats: DefaultFormats.type = DefaultFormats + Serialization.writePretty(this) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/RawSprite.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawSprite.scala new file mode 100644 index 0000000..b85f34f --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/RawSprite.scala @@ -0,0 +1,20 @@ +package fr.ynerant.leveleditor.api.editor + +import fr.ynerant.leveleditor.api.editor.sprites.Sprite + + +object RawSprite { + val BLANK = new RawSprite("blank", 0) + + def create(spr: Sprite): RawSprite = { + new RawSprite(spr.getCategory.getName, spr.getIndex) + } +} + +case class RawSprite(var category: String, protected var index: Int) { + if (category == null) category = "blank" + + def getCategory: String = category + + def getIndex: Int = index +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Category.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Category.scala new file mode 100644 index 0000000..8b32892 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Category.scala @@ -0,0 +1,27 @@ +package fr.ynerant.leveleditor.api.editor.sprites + +import scala.collection.mutable.ListBuffer + +object Category { + def create(name: String, sprites: ListBuffer[Sprite]): Category = { + val c = new Category + c.name = name + c.sprites = sprites + c + } +} + +class Category private() { + private var sprites = null: ListBuffer[Sprite] + private var name = null: String + + def getName: String = name + + def getSprites: ListBuffer[Sprite] = sprites + + def addSprite(s: Sprite): Unit = { + this.sprites += s + } + + override def toString: String = name +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Sprite.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Sprite.scala new file mode 100644 index 0000000..07ad085 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/Sprite.scala @@ -0,0 +1,36 @@ +package fr.ynerant.leveleditor.api.editor.sprites + +import java.awt._ +import java.awt.image.BufferedImage + +import scala.collection.mutable.ListBuffer + +object Sprite { + val BLANK = new Sprite(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB), Category.create("blank", ListBuffer()), 0) + + val g: Graphics2D = BLANK.getImage.createGraphics + g.setComposite(AlphaComposite.Clear) + g.setColor(new Color(0, true)) + g.fillRect(0, 0, 16, 16) + +} + +class Sprite(val img: BufferedImage, val cat: Category, val index: Int) { + if (!this.cat.getSprites.contains(this)) this.cat.addSprite(this) + + def getImage: BufferedImage = this.img + + def getCategory: Category = cat + + def getIndex: Int = index + + override def hashCode: Int = cat.hashCode ^ getIndex + + override def equals(o: Any): Boolean = { + if (!o.isInstanceOf[Sprite]) return false + val other = o.asInstanceOf[Sprite] + hashCode == other.hashCode + } + + override def toString: String = "{Sprite img=" + img + " cat=" + cat.getName + "}" +} diff --git a/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.scala b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.scala new file mode 100644 index 0000000..9dc343f --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/api/editor/sprites/SpriteRegister.scala @@ -0,0 +1,111 @@ +package fr.ynerant.leveleditor.api.editor.sprites + +import java.io.{BufferedInputStream, File, FileInputStream, IOException} +import java.net.{URISyntaxException, URLDecoder} +import java.nio.file.{Files, Paths} +import java.util.Objects +import java.util.jar.JarFile + +import fr.ynerant.leveleditor.client.main.Main +import javax.imageio.ImageIO +import net.liftweb.json._ + +import scala.collection.mutable.ListBuffer + +object SpriteRegister { + private var nameToCoords = Map(): Map[String, List[List[Int]]] + private var sprites = Map(): Map[String, Category] + + @throws[IOException] + def unpack(): Unit = { + if (Main.isInDevelopmentMode) try { + val dir = new File(getClass.getResource("/assets").toURI) + unpackDir(dir) + } catch { + case e: URISyntaxException => + e.printStackTrace() + } + else { + @SuppressWarnings(Array("deprecation")) val path = URLDecoder.decode(getClass.getProtectionDomain.getCodeSource.getLocation.getPath, "UTF-8") + val jarFile = new File(path) + if (jarFile.isFile) { + val jar = new JarFile(jarFile) + val entries = jar.entries + while ( { + entries.hasMoreElements + }) { + val je = entries.nextElement + val name = je.getName + if (name.startsWith("assets/")) { + val f = new File(name) + if (name.endsWith("/")) { + if (!f.mkdirs && !f.isDirectory) throw new IOException("Unable to make dir: " + f) + } + else if (!f.isFile) Files.copy(jar.getInputStream(je), Paths.get(f.toURI)) + } + } + jar.close() + } + } + } + + @throws[IOException] + private def unpackDir(dir: File): Unit = { + for (f <- Objects.requireNonNull(dir.listFiles)) { + if (f.isDirectory) { + unpackDir(f) + } + else { + val path = f.getAbsolutePath.substring(f.getAbsolutePath.indexOf(File.separatorChar + "assets") + 1) + val local = new File(path) + assert(local.getParentFile.isDirectory || local.getParentFile.mkdirs) + assert(!local.exists || local.delete) + Files.copy(Paths.get(f.toURI), Paths.get(local.toURI)) + } + } + } + + @SuppressWarnings(Array("unchecked")) def refreshAllSprites(): Unit = { + if (nameToCoords != null && nameToCoords.nonEmpty && sprites.nonEmpty) return + val assetsDir = new File("assets") + var assets = Nil: List[String] + for (dir <- Objects.requireNonNull(assetsDir.listFiles)) { + assets ::= dir.getName + } + + assets.foreach(asset => { + try { + val f = new File(assetsDir.getAbsolutePath + "/" + asset + "/textures/sprites") + assert(f.isDirectory || f.mkdirs) + val json = Files.readString(new File(f, "sprites.json").toPath) + implicit val formats: DefaultFormats.type = DefaultFormats + nameToCoords = parse(json).extract[Map[String, List[List[Int]]]] + nameToCoords.keySet.foreach(key => { + try { + val is = new BufferedInputStream(new FileInputStream(new File(f, key + ".png"))) + val img = ImageIO.read(is) + val cat = Category.create(key, ListBuffer()) + nameToCoords(key).foreach(list => { + val x = list.head.intValue + val y = list(1).intValue + val child = img.getSubimage(x, y, 16, 16) + new Sprite(child, cat, nameToCoords(key).toIndexedSeq.indexOf(list)) + }) + sprites += (key -> cat) + } catch { + case t: Throwable => + System.err.println("Erreur lors de la lecture du sprite '" + key + "'") + t.printStackTrace() + } + }) + } catch { + case e: IOException => + e.printStackTrace() + } + }) + } + + def getCategory(name: String): Category = sprites(name) + + def getAllCategories: List[Category] = sprites.values.toList +} diff --git a/src/main/scala/fr/ynerant/leveleditor/client/main/Main.scala b/src/main/scala/fr/ynerant/leveleditor/client/main/Main.scala new file mode 100644 index 0000000..e1a0df0 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/client/main/Main.scala @@ -0,0 +1,182 @@ +package fr.ynerant.leveleditor.client.main + +import java.awt._ +import java.awt.image.BufferedImage +import java.io.{File, IOException} +import java.net.{URISyntaxException, URL} +import java.util.Locale + +import fr.ynerant.leveleditor.api.editor.EditorAPI +import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister +import fr.ynerant.leveleditor.frame.MainFrame +import fr.ynerant.leveleditor.game.GameFrame +import javax.swing._ + + +/** + * Class principale qui lance le jeu + * + * @author ÿnérant + * @see #main(String...) + */ +object Main { + /** + * Variable disant si le jeu est lancé en développement ou non. + * + * @see #isInDevelopmentMode() + * @see #main(String...) + * @since 0.1-aplha + */ + private var DEV = false + + /** + * Accesseur disant si le jeu est lancé en développement ou non. + * + * @see #DEV + * @since 0.1-alpha + */ + def isInDevelopmentMode: Boolean = DEV + + /** + * @param args arguments du jeu. Possibilités :
    --edit lancera un éditeur
    --help lance l'aide affichant toutes les options possibles + * @see #launchEditMode() + * @since 0.1-alpha + */ + def main(args: Array[String]): Unit = { + System.setProperty("sun.java2d.noddraw", "true") + Locale.setDefault(Locale.FRANCE) + try UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName) + catch { + case e: Exception => + new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace() + System.err.print("Caused by ") + e.printStackTrace() + } + try { + new File(getClass.getResource("/assets").toURI) + DEV = true + } catch { + case t: Throwable => + DEV = false + } + + try SpriteRegister.unpack() + catch { + case e: IOException => + e.printStackTrace() + } + SpriteRegister.refreshAllSprites() + + launchFrame() + } + + private def checkJava(): Unit = { + if (GraphicsEnvironment.isHeadless) { + val ex = new HeadlessException("Impossible de lancer un jeu sans \u00e9cran !") + System.err.println("Cette application est un jeu, sans écran, elle aura du mal \u00e0 tourner ...") + ex.printStackTrace() + System.exit(1) + } + try classOf[Map[_, _]].getDeclaredMethod("getOrDefault", classOf[Any], classOf[Any]) + catch { + case ex: NoSuchMethodException => + ex.printStackTrace() + JOptionPane.showMessageDialog(null, "Cette application requiert Java 8.
La page de t\u00e9l\u00e9chargement va maintenant s'ouvrir.") + JOptionPane.showMessageDialog(null, "Si vous êtes certain que Java 8 est installé sur votre machine, assurez-vous qu'il n'y a pas de versions obsolètes de Java,
ou si vous êtes plus expérimentés si le path vers Java est bien défini vers la bonne version.") + try if (Desktop.isDesktopSupported) Desktop.getDesktop.browse(new URL("http://java.com/download").toURI) + else JOptionPane.showMessageDialog(null, "Votre machine ne supporte pas la classe Desktop, impossible d'ouvrir la page.
Rendez-vous y manuellement sur http://java.com/download pour installer Java.") + catch { + case e@(_: IOException | _: URISyntaxException) => + e.printStackTrace() + } + System.exit(1) + } + } + + /** + * Lance la fenêtre principale + * + * @see #main(String...) + * @see #launchEditMode() + */ + private def launchFrame(): Unit = { + MainFrame.getInstance.setVisible(true) + } + + /** + * Permet de lancer l'éditeur de carte + * + * @see #main(String...) + * @see #launchFrame() + * @since 0.1-aplha + */ + def launchEditMode: Boolean = { + System.out.println("Lancement de l'\u00e9diteur de monde ...") + var baseWidth = 0 + var baseHeight = 0 + var width = 0 + var height = 0 + while (baseWidth <= 0) { + try { + val baseWidthStr = JOptionPane.showInputDialog(null, "Veuillez entrez le nombre de cases longueur de votre carte (0 pour annuler) :") + if (baseWidthStr == null) return false + baseWidth = baseWidthStr.toInt * 16 + if (baseWidth < 0) throw new NumberFormatException + if (baseWidth == 0) return false + } catch { + case ignored: NumberFormatException => + + } + } + while (baseHeight <= 0) { + try { + val baseHeightStr = JOptionPane.showInputDialog("Veuillez entrez le nombre de cases hauteur de votre carte (0 pour annuler) :") + if (baseHeightStr == null) return false + baseHeight = baseHeightStr.toInt * 16 + if (baseHeight < 0) throw new NumberFormatException + if (baseHeight == 0) return false + } catch { + case ignored: NumberFormatException => + } + } + width = baseWidth + (baseWidth / 16) + 1 + height = baseHeight + (baseHeight / 16) + 1 + val image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) + val g = image.createGraphics + g.setColor(Color.white) + g.fillRect(0, 0, width, height) + g.setColor(Color.black) + g.drawLine(0, 0, width, 0) + g.drawLine(0, 0, 0, height) + var x = 17 + while ( { + x <= width + }) { + g.drawLine(x, 0, x, height) + + x += 17 + } + var y = 17 + while ( { + y <= height + }) { + g.drawLine(0, y, width, y) + + y += 17 + } + val rm = EditorAPI.toRawMap(baseWidth, baseHeight) + rm.setFont(image) + EditorAPI.open(rm) + true + } + + def launchGameMode: Boolean = { + println("Lancement du jeu ...") + val jfc = EditorAPI.createJFC + jfc.showOpenDialog(MainFrame.getInstance) + if (jfc.getSelectedFile == null) return false + val map = EditorAPI.getRawMap(jfc.getSelectedFile) + new GameFrame(map) + true + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/CollidPanel.scala b/src/main/scala/fr/ynerant/leveleditor/editor/CollidPanel.scala new file mode 100644 index 0000000..502b5fc --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/CollidPanel.scala @@ -0,0 +1,60 @@ +package fr.ynerant.leveleditor.editor + +import java.awt._ +import java.awt.image.BufferedImage + +import fr.ynerant.leveleditor.api.editor.Collision +import javax.swing._ + + +@SerialVersionUID(-138754019431984881L) +object CollidPanel { + def isEmpty(image: BufferedImage): Boolean = { + var allrgba = 0 + for (x <- 0 until image.getWidth) { + for (y <- 0 until image.getHeight) { + allrgba += image.getRGB(x, y) + 1 + } + } + allrgba == 0 + } +} + +@SerialVersionUID(-138754019431984881L) +class CollidPanel(val frame: EditorFrame) extends JPanel { + override def paintComponent(g: Graphics): Unit = { + g.fillRect(0, 0, getWidth, getHeight) + val img = getMap.getFont + val x = getWidth / 2 - img.getWidth + val y = getHeight / 2 - img.getHeight + val width = img.getWidth * 2 + val height = img.getHeight * 2 + g.drawImage(getMap.getFont, x, y, width, height, null) + getMap.getAllCases.foreach(c => { + if (!CollidPanel.isEmpty(c.getCoucheOne.getImage)) g.drawImage(c.getCoucheOne.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + if (!CollidPanel.isEmpty(c.getCoucheTwo.getImage)) g.drawImage(c.getCoucheTwo.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + if (!CollidPanel.isEmpty(c.getCoucheThree.getImage)) g.drawImage(c.getCoucheThree.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + }) + + getMap.getAllCases.foreach(c => { + if (!c.getCollision.equals(Collision.ANY)) { + val alpha = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB) + if (c.getCollision.equals(Collision.FULL)) { + val grap = alpha.createGraphics + grap.setColor(new Color(0, 0, 0, 100)) + grap.fillRect(0, 0, 16, 16) + grap.dispose() + } + else if (c.getCollision.equals(Collision.PARTIAL)) { + val grap = alpha.createGraphics + grap.setColor(new Color(255, 0, 255, 70)) + grap.fillRect(0, 0, 16, 16) + grap.dispose() + } + g.drawImage(alpha, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + } + }) + } + + def getMap: GMap = frame.getMap +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/EditorFrame.scala b/src/main/scala/fr/ynerant/leveleditor/editor/EditorFrame.scala new file mode 100644 index 0000000..fa7afa2 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/EditorFrame.scala @@ -0,0 +1,247 @@ +package fr.ynerant.leveleditor.editor + +import java.awt._ +import java.awt.event._ +import java.io.File + +import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister +import fr.ynerant.leveleditor.api.editor.{EditorAPI, RawMap} +import fr.ynerant.leveleditor.frame.listeners._ +import javax.swing._ +import javax.swing.event.{ChangeEvent, ChangeListener} + + +@SerialVersionUID(-2705122356101556462L) +class EditorFrame(val map: GMap) extends JFrame("Level Editor") with ChangeListener with ActionListener with WindowListener { + final private val save = new JMenuItem("Sauvegarder") + final private val saveAs = new JMenuItem("Sauvegarder sous ...") + final private val exit = new JMenuItem("Quitter") + final private val pen = new JRadioButtonMenuItem("Pinceau") + final private val pot = new JRadioButtonMenuItem("Pot de peinture") + final private val tabs = new JTabbedPane + final private var tabColl = null: CollidPanel + final private var mapPanel = null: MapPanel + final private val resources = new JTabbedPane + final private val couche1 = new JPanel + final private val couche2 = new JPanel + final private val couche3 = new JPanel + final private[editor] val group = new ButtonGroup + private var selectedSprite = null: SpriteComp + + this.setSize(1000, 1000) + this.setPreferredSize(getSize) + this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE) + this.setExtendedState(Frame.MAXIMIZED_BOTH) + this.setLocationRelativeTo(null) + this.addWindowListener(this) + val content = new JPanel + content.setLayout(new BorderLayout) + this.setContentPane(content) + this.setVisible(true) + this.setVisible(false) + val fichier = new JMenu("Fichier") + fichier.setMnemonic(KeyEvent.VK_F + KeyEvent.VK_ALT) + val nouveau = new JMenuItem("Nouveau") + nouveau.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.VK_CONTROL, true)) + nouveau.addActionListener(new CreateMapListener) + fichier.add(nouveau) + val open = new JMenuItem("Ouvrir") + open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.VK_CONTROL, true)) + open.addActionListener(new OpenMapListener) + fichier.add(open) + fichier.addSeparator() + save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.VK_CONTROL, true)) + save.addActionListener(this) + fichier.add(save) + saveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.VK_CONTROL + KeyEvent.VK_SHIFT, true)) + saveAs.addActionListener(this) + fichier.add(saveAs) + fichier.addSeparator() + exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.VK_CONTROL, true)) + exit.addActionListener(this) + fichier.add(exit) + val bar: JMenuBar = new JMenuBar + bar.add(fichier) + pen.setSelected(true) + pen.addActionListener(this) + pot.addActionListener(this) + group.add(pen) + group.add(pot) + val selectionMode = new JMenu("Mode de s\u00e9lection") + selectionMode.add(pen) + selectionMode.add(pot) + val tools = new JMenu("Outils") + tools.setMnemonic(KeyEvent.VK_O + KeyEvent.VK_ALT) + tools.add(selectionMode) + bar.add(tools) + this.setJMenuBar(bar) + mapPanel = new MapPanel(this) + mapPanel.addMouseListener(new MapMouseListener(mapPanel, this)) + mapPanel.addMouseMotionListener(new MapMouseListener(mapPanel, this)) + tabColl = new CollidPanel(this) + tabColl.addMouseListener(new CollidMapMouseListener(tabColl, this)) + tabColl.addMouseMotionListener(new CollidMapMouseListener(tabColl, this)) + val scrollMap = new JScrollPane(mapPanel) + scrollMap.getHorizontalScrollBar.setUnitIncrement(34) + scrollMap.getVerticalScrollBar.setUnitIncrement(34) + val scrollCollidMap = new JScrollPane(tabColl) + scrollCollidMap.getHorizontalScrollBar.setUnitIncrement(34) + scrollCollidMap.getVerticalScrollBar.setUnitIncrement(34) + tabs.addTab("Carte", scrollMap) + val tabEvents = new JPanel + tabs.addTab("\u00c9vennments", new JScrollPane(tabEvents)) + tabs.addTab("Collisions", scrollCollidMap) + tabs.addChangeListener(this) + content.add(tabs, BorderLayout.CENTER) + couche1.setLayout(new WrapLayout(FlowLayout.LEFT)) + couche2.setLayout(new WrapLayout(FlowLayout.LEFT)) + couche3.setLayout(new WrapLayout(FlowLayout.LEFT)) + val scroll1 = new JScrollPane(couche1, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) + val scroll2 = new JScrollPane(couche2, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) + val scroll3 = new JScrollPane(couche3, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) + scroll1.getHorizontalScrollBar.setMaximum(0) + scroll2.getHorizontalScrollBar.setMaximum(0) + scroll3.getHorizontalScrollBar.setMaximum(0) + resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 1.png").getAbsolutePath), scroll1) + resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 2.png").getAbsolutePath), scroll2) + resources.addTab("", new ImageIcon(new File("assets/leveleditor/textures/layer 3.png").getAbsolutePath), scroll3) + resources.addChangeListener(this) + resources.setBackgroundAt(0, Color.white) + resources.setBackgroundAt(1, Color.white) + resources.setBackgroundAt(2, Color.white) + content.add(resources, BorderLayout.EAST) + resize() + drawResources() + revalidate() + repaint() + + private def drawResources(): Unit = { + couche1.removeAll() + couche2.removeAll() + couche3.removeAll() + if (couche1.getComponents.length > 0) return + if (couche1.getWidth == 0 || couche2.getWidth == 0 || couche3.getWidth == 0) { + couche1.repaint() + couche2.repaint() + couche3.repaint() + } + SpriteRegister.getAllCategories.foreach(cat => { + cat.getSprites.foreach(spr => { + val sprc1 = new SpriteComp(spr, 0) + val sprc2 = new SpriteComp(spr, 1) + val sprc3 = new SpriteComp(spr, 2) + sprc1.addMouseListener(new SpriteMouseListener(sprc1, this)) + sprc2.addMouseListener(new SpriteMouseListener(sprc2, this)) + sprc3.addMouseListener(new SpriteMouseListener(sprc3, this)) + couche1.add(sprc1) + couche2.add(sprc2) + couche3.add(sprc3) + }) + }) + couche1.revalidate() + couche2.revalidate() + couche3.revalidate() + couche1.repaint() + couche2.repaint() + couche3.repaint() + } + + def resize(): Unit = { + val cursorPos = resources.getSelectedComponent.asInstanceOf[JScrollPane].getVerticalScrollBar.getValue + tabs.setPreferredSize(new Dimension(getWidth, getHeight / 5)) + tabs.setLocation(0, 0) + val img = getMap.getFont + val width = img.getWidth * 2 + val height = img.getHeight * 2 + mapPanel.setPreferredSize(new Dimension(width, height)) + mapPanel.setLocation(0, getHeight / 5) + tabColl.setPreferredSize(new Dimension(width, height)) + tabColl.setLocation(0, getHeight / 5) + resources.setPreferredSize(new Dimension(getWidth / 4 - 15, getHeight / 5 * 4 - 40)) + resources.setLocation(getWidth / 4 * 3, getHeight / 5) + val scroll1 = resources.getComponent(0).asInstanceOf[JScrollPane] + val scroll2 = resources.getComponent(1).asInstanceOf[JScrollPane] + val scroll3 = resources.getComponent(2).asInstanceOf[JScrollPane] + scroll1.getHorizontalScrollBar.setMaximum(0) + scroll2.getHorizontalScrollBar.setMaximum(0) + scroll3.getHorizontalScrollBar.setMaximum(0) + drawResources() + resources.getSelectedComponent.asInstanceOf[JScrollPane].getVerticalScrollBar.setValue(cursorPos) + } + + def getMap: GMap = map + + def getSelectedSprite: SpriteComp = selectedSprite + + def setSelectedSprite(sprite: SpriteComp): Unit = { + this.selectedSprite = sprite + } + + override def stateChanged(event: ChangeEvent): Unit = { + if (event.getSource eq resources) { + if (getSelectedLayerIndex == 0) { + resources.setBackgroundAt(0, Color.white) + resources.setBackgroundAt(1, Color.white) + resources.setBackgroundAt(2, Color.white) + } + else if (getSelectedLayerIndex == 1) { + resources.setBackgroundAt(0, Color.black) + resources.setBackgroundAt(1, Color.white) + resources.setBackgroundAt(2, Color.white) + } + else if (getSelectedLayerIndex == 2) { + resources.setBackgroundAt(0, Color.black) + resources.setBackgroundAt(1, Color.black) + resources.setBackgroundAt(2, Color.white) + } + repaint() + } + else if (event.getSource eq tabs) { + resources.setEnabled(tabs.getSelectedIndex == 0) + couche1.setEnabled(resources.isEnabled) + couche2.setEnabled(resources.isEnabled) + couche3.setEnabled(resources.isEnabled) + repaint() + } + } + + def getSelectedLayerIndex: Int = resources.getSelectedIndex + + override def actionPerformed(event: ActionEvent): Unit = { + if (event.getSource eq save) EditorAPI.save(RawMap.create(map)) + else if (event.getSource eq saveAs) EditorAPI.saveAs(RawMap.create(map)) + else if (event.getSource eq exit) { + val result = JOptionPane.showConfirmDialog(null, "Voulez-vous sauvegarder votre carte avant de quitter ? Toute modification sera perdue", "Confirmation", JOptionPane.YES_NO_CANCEL_OPTION) + if (result == 0) save.doClick() + if (result != 2) dispose() + } + } + + def getSelectedPaintingMode: Int = if (pen.isSelected) 0 + else if (pot.isSelected) 1 + else -1 + + override def windowActivated(event: WindowEvent): Unit = { + } + + override def windowClosed(event: WindowEvent): Unit = { + } + + override def windowClosing(event: WindowEvent): Unit = { + val result = JOptionPane.showConfirmDialog(null, "Voulez-vous sauvegarder avant de quitter ?", "Confirmation", JOptionPane.YES_NO_CANCEL_OPTION) + if (result == 0) EditorAPI.save(RawMap.create(map)) + if (result != 2) dispose() + } + + override def windowDeactivated(event: WindowEvent): Unit = { + } + + override def windowDeiconified(event: WindowEvent): Unit = { + } + + override def windowIconified(event: WindowEvent): Unit = { + } + + override def windowOpened(event: WindowEvent): Unit = { + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/GMap.scala b/src/main/scala/fr/ynerant/leveleditor/editor/GMap.scala new file mode 100644 index 0000000..9a438c5 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/GMap.scala @@ -0,0 +1,61 @@ +package fr.ynerant.leveleditor.editor + +import java.awt.image.BufferedImage + +import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister +import fr.ynerant.leveleditor.api.editor.{Case, RawMap} + + +object GMap { + private var cases = Nil: List[Case] +} + +class GMap(val raw: RawMap) { + final private var frame = null: EditorFrame + final private var width = 0 + final private var height = 0 + private var casesMap = Map(): Map[Int, Map[Int, Case]] + final private var font = null: BufferedImage + + GMap.cases = Nil + this.width = raw.getWidth + this.height = raw.getHeight + this.font = raw.getFont + + raw.getCases.foreach(rc => + GMap.cases = Case.create(rc.getPosX, rc.getPosY, SpriteRegister.getCategory(rc.getCoucheOne.getCategory).getSprites(rc.getCoucheOne.getIndex), SpriteRegister.getCategory(rc.getCoucheTwo.getCategory).getSprites(rc.getCoucheTwo.getIndex), SpriteRegister.getCategory(rc.getCoucheThree.getCategory).getSprites(rc.getCoucheThree.getIndex), rc.getCollision) :: GMap.cases + ) + + reorganizeMap() + frame = new EditorFrame(this) + getFrame.setVisible(true) + + def getFrame: EditorFrame = frame + + def getWidth: Int = width + + def getHeight: Int = height + + def getCase(x: Int, y: Int): Case = casesMap.getOrElse(x, Map()).getOrElse(y, null) + + def getAllCases: List[Case] = { + var list = Nil: List[Case] + casesMap.values.foreach(l => list = list.appendedAll(l.values)) + list + } + + def getFont: BufferedImage = font + + private def reorganizeMap(): Unit = { + for (i <- 0 until width) { + casesMap += (i -> Map()) + } + GMap.cases.foreach(c => setCase(c.getPosX, c.getPosY, c)) + } + + def setCase(x: Int, y: Int, c: Case): Unit = { + var map = casesMap(x) + map = map + (y -> c) + casesMap = casesMap.updated(x, map) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/MapPanel.scala b/src/main/scala/fr/ynerant/leveleditor/editor/MapPanel.scala new file mode 100644 index 0000000..732dcaa --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/MapPanel.scala @@ -0,0 +1,37 @@ +package fr.ynerant.leveleditor.editor + +import java.awt._ +import java.awt.image.BufferedImage + +import javax.swing._ + + +@SerialVersionUID(2629019576253690557L) +class MapPanel(val frame: EditorFrame) extends JPanel { + override def paintComponent(g: Graphics): Unit = { + g.fillRect(0, 0, getWidth, getHeight) + val img = getMap.getFont + val x = getWidth / 2 - img.getWidth + val y = getHeight / 2 - img.getHeight + val width = img.getWidth * 2 + val height = img.getHeight * 2 + g.drawImage(getMap.getFont, x, y, width, height, null) + getMap.getAllCases.foreach(c => { // BufferedImage image; + if (!isEmpty(c.getCoucheOne.getImage)) g.drawImage(c.getCoucheOne.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + if (!isEmpty(c.getCoucheTwo.getImage) && frame.getSelectedLayerIndex >= 1) g.drawImage(c.getCoucheTwo.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + if (!isEmpty(c.getCoucheThree.getImage) && frame.getSelectedLayerIndex == 2) g.drawImage(c.getCoucheThree.getImage, x + c.getPosX * 34 + 2, y + c.getPosY * 34 + 2, 32, 32, null) + }) + } + + def getMap: GMap = frame.getMap + + @SuppressWarnings(Array("BooleanMethodIsAlwaysInverted")) private def isEmpty(image: BufferedImage) = { + var allrgba = 0 + for (x <- 0 until image.getWidth) { + for (y <- 0 until image.getHeight) { + allrgba += image.getRGB(x, y) + 1 + } + } + allrgba == 0 + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/SpriteComp.scala b/src/main/scala/fr/ynerant/leveleditor/editor/SpriteComp.scala new file mode 100644 index 0000000..1fb0e15 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/SpriteComp.scala @@ -0,0 +1,40 @@ +package fr.ynerant.leveleditor.editor + +import fr.ynerant.leveleditor.api.editor.sprites.Sprite +import javax.swing._ +import java.awt._ + + +@SerialVersionUID(-6512257366877053285L) +class SpriteComp(val sprite: Sprite, val couche: Int) extends JComponent { + this.setMinimumSize(new Dimension(32, 32)) + this.setMaximumSize(new Dimension(32, 32)) + this.setPreferredSize(new Dimension(32, 32)) + this.setSize(new Dimension(32, 32)) + repaint() + private var selected = false + + def getSprite: Sprite = sprite + + def getCouche: Int = couche + + def isSelected: Boolean = selected + + def setSelected(selected: Boolean): Unit = { + this.selected = selected + } + + override def paintComponent(g: Graphics): Unit = { + super.paintComponent(g) + g.setColor(Color.white) + g.fillRect(0, 0, getWidth, getHeight) + g.drawImage(sprite.getImage, 0, 0, 32, 32, Color.white, null) + if (isSelected) { + g.setColor(Color.black) + g.drawLine(0, 0, getWidth - 1, 0) + g.drawLine(0, 0, 0, getHeight - 1) + g.drawLine(0, getHeight - 1, getWidth - 1, getHeight - 1) + g.drawLine(getWidth - 1, 0, getWidth - 1, getHeight - 1) + } + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/editor/WrapLayout.scala b/src/main/scala/fr/ynerant/leveleditor/editor/WrapLayout.scala new file mode 100644 index 0000000..5cf84ea --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/editor/WrapLayout.scala @@ -0,0 +1,58 @@ +package fr.ynerant.leveleditor.editor + +import javax.swing._ +import java.awt._ + + +@SerialVersionUID(8777237960365591646L) +class WrapLayout(val alignment: Int) extends FlowLayout(alignment) { + override def preferredLayoutSize(target: Container): Dimension = layoutSize(target, preferred = true) + + override def minimumLayoutSize(target: Container): Dimension = { + val minimum = layoutSize(target, preferred = false) + minimum.width -= (getHgap + 1) + minimum + } + + private def layoutSize(target: Container, preferred: Boolean) = { + var targetWidth = target.getSize.width + if (targetWidth == 0) targetWidth = Integer.MAX_VALUE + val hgap = getHgap + val vgap = getVgap + val insets = target.getInsets + val horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2) + val maxWidth = targetWidth - horizontalInsetsAndGap + val dim = new Dimension(0, 0) + var rowWidth = 0 + var rowHeight = 0 + val nmembers = target.getComponentCount + for (i <- 0 until nmembers) { + val m = target.getComponent(i) + if (m.isVisible) { + val d = if (preferred) m.getPreferredSize + else m.getMinimumSize + if (rowWidth + d.width > maxWidth) { + addRow(dim, rowWidth, rowHeight) + rowWidth = 0 + rowHeight = 0 + } + if (rowWidth != 0) rowWidth += hgap + rowWidth += d.width + rowHeight = Math.max(rowHeight, d.height) + } + } + addRow(dim, rowWidth, rowHeight) + dim.width += horizontalInsetsAndGap + dim.height += insets.top + insets.bottom + vgap * 2 + val scrollPane = SwingUtilities.getAncestorOfClass(classOf[JScrollPane], target) + if (scrollPane != null) dim.width -= (hgap + 1) + dim + + } + + private def addRow(dim: Dimension, rowWidth: Int, rowHeight: Int): Unit = { + dim.width = Math.max(dim.width, rowWidth) + if (dim.height > 0) dim.height += getVgap + dim.height += rowHeight + } +} \ No newline at end of file diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/MainFrame.scala b/src/main/scala/fr/ynerant/leveleditor/frame/MainFrame.scala new file mode 100644 index 0000000..4a28a79 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/MainFrame.scala @@ -0,0 +1,89 @@ +package fr.ynerant.leveleditor.frame + +import fr.ynerant.leveleditor.frame.listeners.ChangeLAFListener +import fr.ynerant.leveleditor.frame.listeners.CreateMapListener +import fr.ynerant.leveleditor.frame.listeners.OpenMapListener +import javax.swing._ +import java.awt._ +import java.awt.event.{ActionEvent, KeyEvent} + +import fr.ynerant.leveleditor.client.main.Main + + +/** + * Fenêtre principale du jeu + * + * @author ÿnérant + */ +@SerialVersionUID(-3168760121879418534L) +object MainFrame { + /** + * Instance unique principale + * + * @see #MainFrame() + * @see #getInstance() + */ + private var INSTANCE = null: MainFrame + + /** + * Cet accesseur renvoie l'accesseur unique de la classe + * + * @return l'instance unique de la classe + * @see #INSTANCE + * @see #MainFrame() + */ + def getInstance: MainFrame = { + if (INSTANCE == null) INSTANCE = new MainFrame + INSTANCE + } +} + +@SerialVersionUID(-3168760121879418534L) +class MainFrame @SuppressWarnings(Array("JavadocReference")) private() + +/** + * Constructeur + * + * @see Main#launchFrame() + */ + extends JFrame { + println("Initialisation de la fen\u00eatre") + this.setTitle("Level Editor") + this.setPreferredSize(new Dimension(1000, 800)) + this.setSize(800, 700) + this.setLocationRelativeTo(null) + this.setExtendedState(Frame.MAXIMIZED_BOTH) + this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) + val fichier = new JMenu("Fichier") + fichier.setMnemonic(KeyEvent.VK_F + KeyEvent.VK_ALT) + val display = new JMenu("Affichage") + display.setMnemonic(KeyEvent.VK_A + KeyEvent.VK_ALT) + val createMap = new JMenuItem("Cr\u00e9er") + createMap.addActionListener(new CreateMapListener) + val editMaps = new JMenu("Cartes") + editMaps.add(createMap) + val openMap = new JMenuItem("Ouvrir") + openMap.addActionListener(new OpenMapListener) + editMaps.add(openMap) + fichier.add(editMaps) + val systemLAF = new JMenuItem("Apparence syst\u00e8me") + systemLAF.addActionListener(new ChangeLAFListener(systemLAF, this)) + val changeLAF = new JMenu("Modfier l'apparence") + changeLAF.add(systemLAF) + val javaLAF = new JMenuItem("Apparence Java") + javaLAF.addActionListener(new ChangeLAFListener(javaLAF, this)) + changeLAF.add(javaLAF) + val darkLAF = new JMenuItem("Apparence sombre") + darkLAF.addActionListener(new ChangeLAFListener(darkLAF, this)) + changeLAF.add(darkLAF) + display.add(changeLAF) + val bar = new JMenuBar + bar.add(fichier) + bar.add(display) + this.setJMenuBar(bar) + val start = new JButton("Commencer la partie !") + start.addActionListener((actionEvent: ActionEvent) => { + if (Main.launchGameMode) MainFrame.getInstance.dispose() + }) + this.setContentPane(start) +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.scala new file mode 100644 index 0000000..d11391d --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/ChangeLAFListener.scala @@ -0,0 +1,41 @@ +package fr.ynerant.leveleditor.frame.listeners + +import javax.swing._ +import java.awt.event.ActionEvent +import java.awt.event.ActionListener + + +class ChangeLAFListener(val item: JMenuItem, val frame: JFrame) extends ActionListener { + override def actionPerformed(event: ActionEvent): Unit = { + if (item.getText.toLowerCase.contains("sys")) { + try UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName) + catch { + case e: Exception => + new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace() + System.err.print("Caused by ") + e.printStackTrace() + } + SwingUtilities.updateComponentTreeUI(frame) + } + else if (item.getText.toLowerCase.contains("java")) { + try UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName) + catch { + case e: Exception => + new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace() + System.err.print("Caused by ") + e.printStackTrace() + } + SwingUtilities.updateComponentTreeUI(frame) + } + else if (item.getText.toLowerCase.contains("sombre")) { + try UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel") + catch { + case e: Exception => + new ExceptionInInitializerError("Erreur lors du changement de 'look and feel'").printStackTrace() + System.err.print("Caused by ") + e.printStackTrace() + } + SwingUtilities.updateComponentTreeUI(frame) + } + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.scala new file mode 100644 index 0000000..1082122 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CollidMapMouseListener.scala @@ -0,0 +1,28 @@ +package fr.ynerant.leveleditor.frame.listeners + +import java.awt.event.{MouseAdapter, MouseEvent} + +import fr.ynerant.leveleditor.api.editor.{Case, Collision} +import fr.ynerant.leveleditor.editor.{CollidPanel, EditorFrame} + + +class CollidMapMouseListener(val panel: CollidPanel, val frame: EditorFrame) extends MouseAdapter { + def getFrame: EditorFrame = frame + + override def mouseReleased(event: MouseEvent): Unit = { + val map = getFrame.getMap + val x = panel.getWidth / 2 - map.getFont.getWidth + val y = panel.getHeight / 2 - map.getFont.getHeight + val c = map.getCase((event.getX - x + 2) / 34, (event.getY - y + 2) / 34) + if (c != null && event.getX - x >= 2 && event.getY - y >= 2) { + val col = c.getCollision match { + case Collision.ANY => Collision.PARTIAL + case Collision.PARTIAL => Collision.FULL + case Collision.FULL => Collision.ANY + } + val n = Case.create(c.getPosX, c.getPosY, c.getCoucheOne, c.getCoucheTwo, c.getCoucheThree, col) + map.setCase((event.getX - x + 2) / 34, (event.getY - y + 2) / 34, n) + panel.repaint() + } + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.scala new file mode 100644 index 0000000..b4f251c --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/CreateMapListener.scala @@ -0,0 +1,19 @@ +package fr.ynerant.leveleditor.frame.listeners + +import java.awt.event.ActionEvent +import java.awt.event.ActionListener + +import fr.ynerant.leveleditor.client.main.Main +import fr.ynerant.leveleditor.frame.MainFrame + + +/** + * @author ÿnérant + */ +class CreateMapListener extends ActionListener { + /* !CodeTemplates.overridecomment.nonjd! + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ override def actionPerformed(event: ActionEvent): Unit = { + if (Main.launchEditMode) MainFrame.getInstance.dispose() + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.scala new file mode 100644 index 0000000..aff973d --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/MapMouseListener.scala @@ -0,0 +1,67 @@ +package fr.ynerant.leveleditor.frame.listeners + +import java.awt.event.{MouseAdapter, MouseEvent} + +import fr.ynerant.leveleditor.api.editor.Case +import fr.ynerant.leveleditor.editor.{EditorFrame, MapPanel} + + +class MapMouseListener(val panel: MapPanel, val frame: EditorFrame) extends MouseAdapter { + def getFrame: EditorFrame = frame + + override def mouseClicked(event: MouseEvent): Unit = { + if (frame.getSelectedPaintingMode == 0) { + val map = getFrame.getMap + val x = panel.getWidth / 2 - map.getFont.getWidth + val y = panel.getHeight / 2 - map.getFont.getHeight + val c = map.getCase((event.getX - x + 2) / 34, (event.getY - y + 2) / 34): Case + if (c != null && event.getX - x >= 2 && event.getY - y >= 2) if (getFrame.getSelectedSprite != null) { + var n = null: Case + getFrame.getSelectedSprite.getCouche match { + case 0 => + n = Case.create(c.getPosX, c.getPosY, getFrame.getSelectedSprite.getSprite, c.getCoucheTwo, c.getCoucheThree, c.getCollision) + + case 1 => + n = Case.create(c.getPosX, c.getPosY, c.getCoucheOne, getFrame.getSelectedSprite.getSprite, c.getCoucheThree, c.getCollision) + + case 2 => + n = Case.create(c.getPosX, c.getPosY, c.getCoucheOne, c.getCoucheTwo, getFrame.getSelectedSprite.getSprite, c.getCollision) + + case _ => + n = c + } + map.setCase(n.getPosX, n.getPosY, n) + panel.repaint() + } + } + else if (frame.getSelectedPaintingMode == 1) { + getFrame.getMap.getAllCases.foreach(c => { + val map = getFrame.getMap + if (getFrame.getSelectedSprite != null) { + if (getFrame.getSelectedSprite.getCouche - 1 > getFrame.getSelectedLayerIndex) return + var n = null: Case + getFrame.getSelectedSprite.getCouche match { + case 0 => + n = Case.create(c.getPosX, c.getPosY, getFrame.getSelectedSprite.getSprite, c.getCoucheTwo, c.getCoucheThree, c.getCollision) + + case 1 => + n = Case.create(c.getPosX, c.getPosY, c.getCoucheOne, getFrame.getSelectedSprite.getSprite, c.getCoucheThree, c.getCollision) + + case 2 => + n = Case.create(c.getPosX, c.getPosY, c.getCoucheOne, c.getCoucheTwo, getFrame.getSelectedSprite.getSprite, c.getCollision) + + case _ => + n = c + + } + map.setCase(n.getPosX, n.getPosY, n) + } + }) + panel.repaint() + } + } + + override def mouseDragged(event: MouseEvent): Unit = { + if (frame.getSelectedPaintingMode == 0) mouseClicked(event) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.scala new file mode 100644 index 0000000..f5ef165 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/OpenMapListener.scala @@ -0,0 +1,16 @@ +package fr.ynerant.leveleditor.frame.listeners + +import java.awt.event.ActionEvent +import java.awt.event.ActionListener + +import fr.ynerant.leveleditor.api.editor.EditorAPI +import fr.ynerant.leveleditor.frame.MainFrame + + +class OpenMapListener extends ActionListener { + /* !CodeTemplates.overridecomment.nonjd! + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ override def actionPerformed(event: ActionEvent): Unit = { + if (EditorAPI.open != null) MainFrame.getInstance.dispose() + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.scala b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.scala new file mode 100644 index 0000000..344d113 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/frame/listeners/SpriteMouseListener.scala @@ -0,0 +1,19 @@ +package fr.ynerant.leveleditor.frame.listeners + +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent + +import fr.ynerant.leveleditor.editor.{EditorFrame, SpriteComp} + + +class SpriteMouseListener(val sprite: SpriteComp, val frame: EditorFrame) extends MouseAdapter { + override def mouseReleased(event: MouseEvent): Unit = { + if (frame.getSelectedSprite != null) { + frame.getSelectedSprite.setSelected(false) + frame.getSelectedSprite.repaint() + } + frame.setSelectedSprite(sprite) + sprite.setSelected(true) + sprite.repaint() + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/GameFrame.scala b/src/main/scala/fr/ynerant/leveleditor/game/GameFrame.scala new file mode 100644 index 0000000..60f0328 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/GameFrame.scala @@ -0,0 +1,226 @@ +package fr.ynerant.leveleditor.game + +import java.awt._ +import java.awt.event.{MouseEvent, MouseListener} + +import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister +import fr.ynerant.leveleditor.api.editor.{Collision, RawMap} +import fr.ynerant.leveleditor.editor.CollidPanel +import fr.ynerant.leveleditor.game.mobs.Mob +import fr.ynerant.leveleditor.game.towers._ +import javax.swing._ + +import scala.collection.mutable.ListBuffer +import scala.util.Random + + +class GameFrame(val map: RawMap) extends JFrame("Jeu") { + private var round = 0 + private var hp = 5 + private var reward = 20 + private var mobs = ListBuffer[Mob]() + private var towers = ListBuffer[Tower]() + private val pathFinder = PathFinder(this) + final private var basicTower = null: JRadioButton + final private var wallTower = null: JRadioButton + final private var freezerTower = null: JRadioButton + final private var explodeTower = null: JRadioButton + final private var upgradeTower = null: JRadioButton + final private var laserTower = null: JRadioButton + final private var waveLabel = null: JLabel + final private var nbMobsLabel = null: JLabel + final private var hpLabel = null: JLabel + final private var rewardLabel = null: JLabel + final private var winLabel = null: JLabel + + this.setSize(1000, 1000) + this.setPreferredSize(getSize) + this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) + this.setExtendedState(Frame.MAXIMIZED_BOTH) + this.setLocationRelativeTo(null) + val root = new JPanel + root.setLayout(new BorderLayout) + this.setContentPane(root) + val pane = new JPanel + pane.setLayout(new GridLayout(8, 1)) + root.add(pane, BorderLayout.SOUTH) + val grid = new Grid() + grid.setSize(map.getWidth, map.getHeight) + grid.setPreferredSize(grid.getSize) + grid.setMinimumSize(grid.getSize) + grid.setMaximumSize(grid.getSize) + root.add(grid, BorderLayout.CENTER) + val towerSelect = new ButtonGroup + basicTower = new JRadioButton("Tour basique (" + new BasicTower(0, 0).getPrice + " pièces)") + basicTower.setSelected(true) + towerSelect.add(basicTower) + pane.add(basicTower) + wallTower = new JRadioButton("Tour-mur (" + new WallTower(0, 0).getPrice + " pièces)") + towerSelect.add(wallTower) + pane.add(wallTower) + freezerTower = new JRadioButton("Tour froide (" + new FreezerTower(0, 0).getPrice + " pièces)") + towerSelect.add(freezerTower) + pane.add(freezerTower) + explodeTower = new JRadioButton("Tour explosive (" + new ExploderTower(0, 0).getPrice + " pièces)") + towerSelect.add(explodeTower) + pane.add(explodeTower) + upgradeTower = new JRadioButton("Tour d'amélioration (" + new UpgradeTower(0, 0).getPrice + " pièces)") + towerSelect.add(upgradeTower) + pane.add(upgradeTower) + laserTower = new JRadioButton("Tour laser (" + new LaserTower(0, 0).getPrice + " pièces)") + towerSelect.add(laserTower) + pane.add(laserTower) + waveLabel = new JLabel + pane.add(waveLabel) + nbMobsLabel = new JLabel + pane.add(nbMobsLabel) + hpLabel = new JLabel + pane.add(hpLabel) + rewardLabel = new JLabel + pane.add(rewardLabel) + winLabel = new JLabel + pane.add(winLabel) + setVisible(true) + new Thread(() => { + pathFinder.calculatePath() + + while (hp > 0 && (round < 4 || mobs.nonEmpty)) { + try + tick() + catch { + case e: Throwable => + e.printStackTrace() + } + + try Thread.sleep(50L) + catch { + case e: InterruptedException => + e.printStackTrace() + } + } + }).start() + repaint() + + def getMap: RawMap = map + + def getMobs: ListBuffer[Mob] = mobs + + def getTowers: ListBuffer[Tower] = towers + + def breakTower(tower: Tower): Unit = towers -= tower + + def getPathFinder: PathFinder = pathFinder + + def tick(): Unit = { + if (mobs.isEmpty && round < 4) { + round += 1 + val nb_mobs = round * (Random.nextInt(8) + 1) + for (_ <- 1 to nb_mobs) { + val mob = Mob.getRandomMob + do mob.move(Random.nextInt(getMap.getWidth / 16), Random.nextInt(getMap.getHeight / 16)) while ( { + !getMap.getCase(mob.getX, mob.getY).getCollision.equals(Collision.ANY) + }) + getMap.getCase(mob.getX, mob.getY).setCollision(Collision.PARTIAL) + mobs += mob + } + } + towers.foreach(tower => tower.shot(this)) + mobs.foreach(mob => { + getMap.getCase(mob.getX, mob.getY).setCollision(Collision.ANY) + mob.tick(this) + if (mob.getX < 0 || mob.isDead) { + mobs -= mob + if (mob.getX < 0) { + hp -= 1 + if (hp == 0) { + winLabel.setForeground(Color.red) + winLabel.setText("Vous avez perdu !") + return + } + } + else reward += mob.getReward + } + else getMap.getCase(mob.getX, mob.getY).setCollision(Collision.PARTIAL) + }) + waveLabel.setText("Vague " + round) + nbMobsLabel.setText(mobs.size + " mob" + (if (mobs.size > 1) "s" + else "") + " restant" + (if (mobs.size > 1) "s" + else "")) + hpLabel.setText("Points de vie : " + hp) + rewardLabel.setText("Butin : " + reward) + if (round == 4 && mobs.isEmpty) { + winLabel.setForeground(Color.green.darker) + winLabel.setText("Vous avez gagné !") + } + } + + class Grid() extends JComponent with MouseListener { + addMouseListener(this) + + override def mouseReleased(event: MouseEvent): Unit = { + val x = event.getX / 32 + val y = event.getY / 32 + val tower = if (basicTower.isSelected) new BasicTower(x, y) + else if (wallTower.isSelected) new WallTower(x, y) + else if (freezerTower.isSelected) new FreezerTower(x, y) + else if (explodeTower.isSelected) new ExploderTower(x, y) + else if (upgradeTower.isSelected) new UpgradeTower(x, y) + else if (laserTower.isSelected) new LaserTower(x, y) + else null + if (tower == null || tower.getPrice > reward) return + val c = getMap.getCase(x, y) + if (c == null || !c.getCollision.equals(Collision.ANY)) return + c.setCollision(Collision.FULL) + + pathFinder.invalidate() + + val accessible = getMap.getCases.filter(c => !Collision.FULL.equals(c.getCollision)) + if (accessible.exists(c => c.getPosX > 0 && pathFinder.nextPos(c.getPosX, c.getPosY) == null) || !accessible.exists(c => c.getPosX == 0 && !c.getCollision.equals(Collision.FULL))) { + // We ensure that the end of the game is accessible from everywhere, the tower should not block the game + c.setCollision(Collision.ANY) + pathFinder.invalidate() + } + else { + reward -= tower.getPrice + towers += tower + } + } + + override def mouseClicked(event: MouseEvent): Unit = { + } + + override def mousePressed(event: MouseEvent): Unit = { + } + + override protected def paintComponent(_g: Graphics): Unit = { + val g = _g.asInstanceOf[Graphics2D] + if (getMap.getFont != null) g.drawImage(getMap.getFont, null, null) + SpriteRegister.refreshAllSprites() + val SPRITE_SIZE = 32 + getMap.getCases.foreach(c => { + val s1 = SpriteRegister.getCategory(c.getCoucheOne.getCategory).getSprites(c.getCoucheOne.getIndex) + val s2 = SpriteRegister.getCategory(c.getCoucheTwo.getCategory).getSprites(c.getCoucheTwo.getIndex) + val s3 = SpriteRegister.getCategory(c.getCoucheThree.getCategory).getSprites(c.getCoucheThree.getIndex) + g.drawImage(s1.getImage, SPRITE_SIZE * c.getPosX, SPRITE_SIZE * c.getPosY, SPRITE_SIZE, SPRITE_SIZE, Color.white, null) + if (!CollidPanel.isEmpty(s2.getImage)) g.drawImage(s2.getImage, SPRITE_SIZE * c.getPosX, SPRITE_SIZE * c.getPosY, SPRITE_SIZE, SPRITE_SIZE, null, null) + if (!CollidPanel.isEmpty(s3.getImage)) g.drawImage(s3.getImage, SPRITE_SIZE * c.getPosX, SPRITE_SIZE * c.getPosY, SPRITE_SIZE, SPRITE_SIZE, null, null) + }) + mobs.foreach(mob => { + val s = mob.getSprite + g.drawImage(s.getImage, SPRITE_SIZE * mob.getX, SPRITE_SIZE * mob.getY, SPRITE_SIZE, SPRITE_SIZE, null, null) + }) + towers.foreach(tower => { + val s = tower.getSprite + g.drawImage(s.getImage, SPRITE_SIZE * tower.getX, SPRITE_SIZE * tower.getY, SPRITE_SIZE, SPRITE_SIZE, null, null) + }) + repaint() + } + + override def mouseEntered(event: MouseEvent): Unit = { + } + + override def mouseExited(event: MouseEvent): Unit = { + } + } + +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/PathFinder.scala b/src/main/scala/fr/ynerant/leveleditor/game/PathFinder.scala new file mode 100644 index 0000000..64d9e60 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/PathFinder.scala @@ -0,0 +1,40 @@ +package fr.ynerant.leveleditor.game + +import java.util + +import fr.ynerant.leveleditor.api.editor.{Collision, RawCase} + +case class PathFinder(game: GameFrame) { + var pred: Map[Int, RawCase] = Map(): Map[Int, RawCase] + + def invalidate(): Unit = calculatePath() + + def calculatePath(): Unit = { + pred = Map() + val queue = new util.ArrayDeque[RawCase] + + for (i <- 0 until game.getMap.getHeight / 16) { + val start = game.getMap.getCase(0, i) + if (!start.getCollision.equals(Collision.FULL)) { + pred += (coords(start) -> null) + queue.add(start) + } + } + + while (!queue.isEmpty) { + val visiting = queue.poll + game.getMap.getNeighbours(visiting).foreach(neighbour => { + if (neighbour != null && !neighbour.collision.equals(Collision.FULL) && !pred.contains(coords(neighbour))) { + pred += (coords(neighbour) -> visiting) + queue.add(neighbour) + } + }) + } + } + + def coords(rawCase: RawCase): Int = rawCase.getPosY * game.getMap.getWidth / 16 + rawCase.getPosX + + def nextPos(x: Int, y: Int): RawCase = { + pred.getOrElse(y * game.getMap.getWidth / 16 + x, null) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob.scala new file mode 100644 index 0000000..ab36000 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob.scala @@ -0,0 +1,122 @@ +package fr.ynerant.leveleditor.game.mobs + +import fr.ynerant.leveleditor.api.editor.RawCase +import fr.ynerant.leveleditor.api.editor.sprites.{Sprite, SpriteRegister} +import fr.ynerant.leveleditor.game.GameFrame + +import scala.util.Random + +object Mob { + private val RANDOM = new Random + + def getRandomMob: Mob = RANDOM.nextInt(6) match { + case 0 => + new Mob1 + case 1 => + new Mob2 + case 2 => + new MobStrong + case 3 => + new MobHealer + case 4 => + new MobBreaker + case 5 => + new MobSpeeder + } +} + +abstract class Mob() { + private var hp = getMaxHP + private var tickRemains = 0L + private var sprite = null: Sprite + private var x = 0 + private var y = 0 + private var freezeTime = 0 + private var speedMultiplier = 1 + + tickRemains = getSlowness + + def getMaxHP: Int + + def _getSlowness: Long + + def getSlowness: Long = { + (_getSlowness * Random.between(0.95, 1.05) * (if (freezeTime > 0) 2 else 1) / speedMultiplier).toLong + } + + def getReward: Int + + def getName: String + + def getSprite: Sprite = { + if (sprite == null) sprite = SpriteRegister.getCategory(getName).getSprites.head + sprite + } + + def getX: Int = x + + def getY: Int = y + + def move(x: Int, y: Int): Unit = { + this.x = x + this.y = y + } + + def freeze(time: Int): Unit = { + if (freezeTime == 0) + tickRemains *= 2 + freezeTime = time + } + + def speedup(multiplier: Int): Unit = speedMultiplier = multiplier + + def heal(hp: Int): Unit = { + this.hp = Math.min(hp + 1, getMaxHP) + } + + def getHP: Int = hp + + def isDead: Boolean = hp <= 0 + + def setHP(hp: Int): Unit = { + this.hp = hp + } + + def hit(damage: Int): Boolean = { + if (!isDead) { + this.hp -= damage + return true + } + false + } + + /** + * Called each game tick + */ + def tick(game: GameFrame): Unit = { + if (freezeTime > 0) + freezeTime -= 1 + + if (tickRemains > 0) tickRemains -= 1 + else { + tickRemains = getSlowness + val current = game.getMap.getCase(getX, getY) + if (current.getPosX == 0) { + move(-1, getY) + return + } + + _tick(game) + + val newCase: RawCase = game.getPathFinder.nextPos(getX, getY) + move(newCase.getPosX, newCase.getPosY) + } + } + + /** + * Custom mobs override this function to do some custom stuff + */ + def _tick(game: GameFrame): Unit = () + + override def toString: String = "Mob{" + "sprite=" + sprite + ", x=" + x + ", y=" + y + '}' +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob1.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob1.scala new file mode 100644 index 0000000..5218785 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob1.scala @@ -0,0 +1,11 @@ +package fr.ynerant.leveleditor.game.mobs + +class Mob1 extends Mob { + override def getMaxHP = 2 + + override def _getSlowness = 50 + + override def getReward = 10 + + override def getName = "mob1" +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob2.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob2.scala new file mode 100644 index 0000000..28f17c6 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/Mob2.scala @@ -0,0 +1,11 @@ +package fr.ynerant.leveleditor.game.mobs + +class Mob2 extends Mob { + override def getMaxHP = 6 + + override def _getSlowness = 20 + + override def getReward = 20 + + override def getName = "mob2" +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobBreaker.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobBreaker.scala new file mode 100644 index 0000000..c533556 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobBreaker.scala @@ -0,0 +1,18 @@ +package fr.ynerant.leveleditor.game.mobs + +import fr.ynerant.leveleditor.game.GameFrame + +class MobBreaker extends Mob { + override def getMaxHP = 110 + + override def _getSlowness = 120 + + override def getReward = 70 + + override def getName = "mobhealer" + + override def _tick(game: GameFrame): Unit = { + game.getTowers.filter(tower => Math.abs(tower.getX - getX) + Math.abs(tower.getY - getY) <= 1).foreach(tower => game.breakTower(tower)) + game.getPathFinder.invalidate + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobHealer.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobHealer.scala new file mode 100644 index 0000000..c8a6ef5 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobHealer.scala @@ -0,0 +1,17 @@ +package fr.ynerant.leveleditor.game.mobs + +import fr.ynerant.leveleditor.game.GameFrame + +class MobHealer extends Mob { + override def getMaxHP = 20 + + override def _getSlowness = 60 + + override def getReward = 20 + + override def getName = "mobhealer" + + override def _tick(game: GameFrame): Unit = { + game.getMobs.filter(mob => Math.pow(mob.getX - getX, 2) + Math.pow(mob.getY - getY, 2) <= 9).foreach(mob => mob.heal(2)) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobSpeeder.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobSpeeder.scala new file mode 100644 index 0000000..2ef1261 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobSpeeder.scala @@ -0,0 +1,17 @@ +package fr.ynerant.leveleditor.game.mobs + +import fr.ynerant.leveleditor.game.GameFrame + +class MobSpeeder extends Mob { + override def getMaxHP = 25 + + override def _getSlowness = 60 + + override def getReward = 30 + + override def getName = "mobspeeder" + + override def _tick(game: GameFrame): Unit = { + game.getMobs.filter(mob => Math.pow(mob.getX - getX, 2) + Math.pow(mob.getY - getY, 2) <= 9 && mob != this).foreach(mob => mob.speedup(3)) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobStrong.scala b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobStrong.scala new file mode 100644 index 0000000..2150246 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/mobs/MobStrong.scala @@ -0,0 +1,11 @@ +package fr.ynerant.leveleditor.game.mobs + +class MobStrong extends Mob { + override def getMaxHP = 50 + + override def _getSlowness = 100 + + override def getReward = 100 + + override def getName = "mobstrong" +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/BasicTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/BasicTower.scala new file mode 100644 index 0000000..0f07191 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/BasicTower.scala @@ -0,0 +1,22 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.game.GameFrame + +import scala.util.Random + +class BasicTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "basictower" + + override def getDamagePerShot = if (isUpgraded) 3 else 1 + + override def getPeriod = 5 + + override def getPrice = 10 + + override private[towers] def _shot(game: GameFrame): Unit = { + var l = game.getMobs.filter(mob => Math.pow(mob.getX - getX, 2) + Math.pow(mob.getY - getY, 2) <= 9).toList + l = Random.shuffle(l) + if (l.nonEmpty) + l.head.hit(getDamagePerShot) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/ExploderTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/ExploderTower.scala new file mode 100644 index 0000000..442c6c8 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/ExploderTower.scala @@ -0,0 +1,26 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.game.GameFrame + +import scala.util.Random + +class ExploderTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "explodertower" + + override def getDamagePerShot = if (isUpgraded) 7 else 3 + + override def getPeriod = 20 + + override def getPrice = 70 + + override private[towers] def _shot(game: GameFrame): Unit = { + var l = game.getMobs.filter(mob => Math.pow(mob.getX - getX, 2) + Math.pow(mob.getY - getY, 2) <= 25).toList + l = Random.shuffle(l) + if (l.nonEmpty) { + val target = l.head + target.hit(getDamagePerShot) + game.getMobs.filter(mob => Math.pow(mob.getX - target.getX, 2) + Math.pow(mob.getX - target.getX, 2) <= 9) + .foreach(mob => mob.hit(getDamagePerShot)) + } + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/FreezerTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/FreezerTower.scala new file mode 100644 index 0000000..ad59c62 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/FreezerTower.scala @@ -0,0 +1,20 @@ +package fr.ynerant.leveleditor.game.towers; + +import fr.ynerant.leveleditor.game.GameFrame + +class FreezerTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "freezertower" + + override def getDamagePerShot = if (isUpgraded) 1 else 0 + + override def getPeriod = 10 + + override def getPrice = 40 + + override private[towers] def _shot(game: GameFrame): Unit = { + game.getMobs.filter(mob => Math.abs(mob.getX - getX) <= 3 && Math.abs(mob.getY - getY) <= 3).foreach(mob => { + mob.freeze(if (isUpgraded) 100 else 40) + mob.hit(getDamagePerShot) + }) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/LaserTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/LaserTower.scala new file mode 100644 index 0000000..50912d0 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/LaserTower.scala @@ -0,0 +1,17 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.game.GameFrame + +class LaserTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "lasertower" + + override def getDamagePerShot = if (isUpgraded) 8 else 3 + + override def getPeriod = 40 + + override def getPrice = 80 + + override private[towers] def _shot(game: GameFrame): Unit = { + game.getMobs.filter(mob => mob.getX == getX || mob.getY == getY).foreach(mob => mob.hit(getDamagePerShot)) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/Tower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/Tower.scala new file mode 100644 index 0000000..e1cde90 --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/Tower.scala @@ -0,0 +1,37 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.api.editor.sprites.{Sprite, SpriteRegister} +import fr.ynerant.leveleditor.game.GameFrame + +abstract class Tower(val x: Int, val y: Int) { + final private val sprite = SpriteRegister.getCategory(getName).getSprites.head + private var remainingTicks = 0L + private var upgraded = false + + def getSprite: Sprite = sprite + + def getName: String + + def getDamagePerShot: Int + + def getPeriod: Long + + def getPrice: Int + + def upgrade: Unit = upgraded = true + + def isUpgraded: Boolean = upgraded + + def shot(game: GameFrame): Unit = if (remainingTicks > 0) + remainingTicks -= 1 + else { + remainingTicks = getPeriod + _shot(game) + } + + private[towers] def _shot(game: GameFrame): Unit + + def getX: Int = x + + def getY: Int = y +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/UpgradeTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/UpgradeTower.scala new file mode 100644 index 0000000..a72c76a --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/UpgradeTower.scala @@ -0,0 +1,19 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.game.GameFrame + +class UpgradeTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "upgradetower" + + override def getDamagePerShot = if (isUpgraded) 1 else 0 + + override def getPeriod = 60 + + override def getPrice = 65 + + override private[towers] def _shot(game: GameFrame): Unit = { + game.getTowers.filter(tower => Math.pow(tower.getX - getX, 2) + Math.pow(tower.getY - getY, 2) <= 25 && tower != this).foreach(tower => tower.upgrade) + if (isUpgraded) + game.getMobs.filter(mob => Math.pow(mob.getX - getX, 2) + Math.pow(mob.getY - getY, 2) <= 9).foreach(mob => mob.hit(getDamagePerShot)) + } +} diff --git a/src/main/scala/fr/ynerant/leveleditor/game/towers/WallTower.scala b/src/main/scala/fr/ynerant/leveleditor/game/towers/WallTower.scala new file mode 100644 index 0000000..2e62cef --- /dev/null +++ b/src/main/scala/fr/ynerant/leveleditor/game/towers/WallTower.scala @@ -0,0 +1,15 @@ +package fr.ynerant.leveleditor.game.towers + +import fr.ynerant.leveleditor.game.GameFrame + +class WallTower(override val x: Int, override val y: Int) extends Tower(x, y) { + override def getName = "walltower" + + override def getDamagePerShot: Int = Integer.MAX_VALUE + + override def getPeriod = 1 + + override def getPrice = 5 + + override private[towers] def _shot(game: GameFrame): Unit = () +}