Translated project in Scala (but the path finder seems to be broken)

This commit is contained in:
Yohann D'ANELLO 2020-04-04 04:33:11 +02:00
parent 40e0a92f9e
commit 58509e0d5b
67 changed files with 1905 additions and 2543 deletions

View File

@ -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\"".

View File

@ -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";
}
}

View File

@ -1,5 +0,0 @@
package fr.ynerant.leveleditor.api.editor;
public enum Collision {
FULL, PARTIAL, ANY
}

View File

@ -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<RawCase> 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);
}
}

View File

@ -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;
}
}

View File

@ -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<RawCase> cases;
private java.util.Map<Integer, RawCase> cases_map;
private int width;
private int height;
private transient BufferedImage font;
public static RawMap create(List<RawCase> 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<RawCase> 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<RawCase> getNeighbours(RawCase c) {
List<RawCase> 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;
}
}

View File

@ -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;
}
}

View File

@ -1,4 +0,0 @@
/**
* @author ÿnérant
*/
package fr.ynerant.leveleditor.api.editor;

View File

@ -1,33 +0,0 @@
package fr.ynerant.leveleditor.api.editor.sprites;
import java.util.List;
public class Category {
private List<Sprite> sprites;
private String name;
private Category() {
}
public static Category create(String name, List<Sprite> sprites) {
Category c = new Category();
c.name = name;
c.sprites = sprites;
return c;
}
public String getName() {
return name;
}
public List<Sprite> getSprites() {
return sprites;
}
@Override
public String toString() {
return name;
}
}

View File

@ -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() + "}";
}
}

View File

@ -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<String, List<List<Double>>> nameToCoords;
private static final Map<String, Category> 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<JarEntry> 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<String> 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<Double> 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<Category> getAllCategories() {
return new ArrayList<>(sprites.values());
}
}

View File

@ -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&eacute; en d&eacute;veloppement ou non.
*
* @see #isInDevelopmentMode()
* @see #main(String...)
* @since 0.1-aplha
*/
private static boolean DEV;
/**
* @param args arguments du jeu. Possibilit&eacute;s :<br>&nbsp;&nbsp;&nbsp;&nbsp;<strong>--edit</strong> lancera un &eacute;diteur<br>&nbsp;&nbsp;&nbsp;&nbsp;<strong>--help</strong> 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<String> edit = parser.accepts("edit", "Lancer l'\u00e9diteur de monde").withOptionalArg();
OptionSpec<String> 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, "<html>Cette application requiert <strong>Java 8</strong>.<br />La page de t\u00e9l\u00e9chargement va maintenant s'ouvrir.</html>");
JOptionPane.showMessageDialog(null, "<html>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,<br />ou si vous êtes plus expérimentés si le path vers Java est bien défini vers la bonne version.</html>");
try {
if (Desktop.isDesktopSupported())
Desktop.getDesktop().browse(new URL("http://java.com/download").toURI());
else
JOptionPane.showMessageDialog(null, "<html>Votre machine ne supporte pas la classe Desktop, impossible d'ouvrir la page.<br />Rendez-vous y manuellement sur <a href=\"http://java.com/download\">http://java.com/download</a> pour installer Java.</html>");
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
System.exit(1);
}
}
/**
* Lance la fen&ecirc;tre principale
*
* @see #main(String...)
* @see #launchEditMode()
*/
private static void launchFrame() {
MainFrame.getInstance().setVisible(true);
}
/**
* Permet de lancer l'&eacute;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&eacute; en d&eacute;veloppement ou non.
*
* @see #DEV
* @since 0.1-alpha
*/
public static boolean isInDevelopmentMode() {
return DEV;
}
}

View File

@ -1,6 +0,0 @@
/**
* Ce package comprend uniquement la classe Main, qui lance l'application.
*
* @author ÿnérant
*/
package fr.ynerant.leveleditor.client.main;

View File

@ -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;
}
}

View File

@ -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) {
}
}

View File

@ -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<Case> cases;
private final EditorFrame frame;
private final int width;
private final int height;
private final java.util.Map<Integer, java.util.Map<Integer, Case>> 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<Case> getAllCases() {
List<Case> list = new ArrayList<>();
for (java.util.Map<Integer, Case> l : casesMap.values()) {
list.addAll(l.values());
}
return list;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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&ecirc;tre principale du jeu
*
* @author ÿnérant
*/
public class MainFrame extends JFrame {
/**
* ID de s&eacute;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;
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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<Mob> mobs = new ArrayList<>();
private final List<Tower> 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) {}
}
}

View File

@ -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<RawCase> visited = new ArrayList<>();
Queue<RawCase> queue = new ArrayDeque<>();
Map<RawCase, RawCase> 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();
}
}
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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<Mob> _filterDetectedMobs(Collection<Mob> mobs) {
return mobs;
}
}

View File

@ -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<Mob> _filterDetectedMobs(Collection<Mob> mobs) {
List<Mob> 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;
}
}

View File

@ -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<Mob> _filterDetectedMobs(Collection<Mob> mobs) {
return new ArrayList<>();
}
}

View File

@ -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<Mob> _filterDetectedMobs(Collection<Mob> mobs);
public Collection<Mob> filterDetectedMobs(Collection<Mob> mobs) {
if (remainingTicks > 0) {
--remainingTicks;
return new ArrayList<>();
}
else {
remainingTicks = getPeriod();
return _filterDetectedMobs(mobs);
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}

View File

@ -0,0 +1,41 @@
package fr.ynerant.leveleditor.api.editor
import fr.ynerant.leveleditor.api.editor.Collision.Collision
import fr.ynerant.leveleditor.api.editor.sprites.Sprite
object Case {
def create(posX: Int, posY: Int, couche1: Sprite, couche2: Sprite, couche3: Sprite, collision: Collision): 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: Collision
def getPosX: Int = x
def getPosY: Int = y
def getCoucheOne: Sprite = couche1
def getCoucheTwo: Sprite = couche2
def getCoucheThree: Sprite = couche3
def getCollision: Collision = collision
override def toString: String = "{Case x=" + x + " y=" + y + " couche1=" + couche1 + " couche2=" + couche2 + " couche3=" + couche3 + " collision=" + collision.toString.toUpperCase + "}\n"
}

View File

@ -0,0 +1,6 @@
package fr.ynerant.leveleditor.api.editor
object Collision extends Enumeration {
type Collision = Value
val FULL, PARTIAL, ANY = Value
}

View File

@ -0,0 +1,160 @@
package fr.ynerant.leveleditor.api.editor
import java.awt.Color
import java.awt.image.BufferedImage
import java.io._
import java.lang.reflect.Type
import java.nio.charset.StandardCharsets
import java.util
import java.util.zip.{GZIPInputStream, GZIPOutputStream}
import com.google.gson.{Gson, GsonBuilder, JsonDeserializationContext, JsonDeserializer, JsonElement, JsonPrimitive, JsonSerializationContext, JsonSerializer}
import fr.ynerant.leveleditor.api.editor.Collision.Collision
import fr.ynerant.leveleditor.editor.Map
import javax.swing.JFileChooser
import javax.swing.filechooser.FileNameExtensionFilter
object EditorAPI {
private var LAST_FILE = null: File
def toRawMap(width: Int, height: Int): RawMap = {
val cases = new util.ArrayList[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.add(c)
x += 16
}
y += 16
}
RawMap.create(cases, width, height)
}
def createGson: Gson = {
val builder = new GsonBuilder
builder.registerTypeAdapter(classOf[Collision.Collision], new JsonDeserializer[Collision.Collision] {
override def deserialize(jsonElement: JsonElement, `type`: Type, jsonDeserializationContext: JsonDeserializationContext): Collision = Collision.withName(jsonElement.getAsString)
})
builder.registerTypeAdapter(classOf[Collision.Collision], new JsonSerializer[Collision.Collision] {
override def serialize(t: Collision, `type`: Type, jsonSerializationContext: JsonSerializationContext): JsonElement = new JsonPrimitive(t.toString)
})
builder.enableComplexMapKeySerialization
builder.serializeNulls
builder.setPrettyPrinting()
builder.create
}
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 = {
val json = createGson.toJson(map)
try {
assert(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: Map = {
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()
}
createGson.fromJson(json, classOf[RawMap])
}
def open(f: File): Map = open(getRawMap(f))
def open(map: RawMap): Map = {
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 Map(map)
}
}

View File

@ -0,0 +1,31 @@
package fr.ynerant.leveleditor.api.editor
import fr.ynerant.leveleditor.api.editor.Collision.Collision
object RawCase {
def create(posX: Int, posY: Int, couche1: RawSprite, couche2: RawSprite, couche3: RawSprite, collision: Collision): 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: Collision) {
def getPosX: Int = x
def getPosY: Int = y
def getCoucheOne: RawSprite = couche1
def getCoucheTwo: RawSprite = couche2
def getCoucheThree: RawSprite = couche3
def getCollision: Collision = collision
def setCollision(collision: Collision): Unit = {
this.collision = collision
}
}

View File

@ -0,0 +1,60 @@
package fr.ynerant.leveleditor.api.editor
import fr.ynerant.leveleditor.editor.Map
import java.awt.image.BufferedImage
import java.util
import java.util.stream.Collectors
import com.google.gson.Gson
object RawMap {
def create(cases: util.List[RawCase], width: Int, height: Int): RawMap = {
new RawMap(cases, width, height)
}
def create(map: Map): RawMap = {
val raw = new RawMap(new util.ArrayList[RawCase], 0, 0)
raw.width = map.getWidth
raw.height = map.getHeight
raw.cases = new util.ArrayList[RawCase]
map.getAllCases.forEach(c => raw.cases.add(RawCase.create(c)))
raw
}
}
case class RawMap(var cases: util.List[RawCase], var width: Int, var height: Int) {
private var cases_map = null: util.HashMap[Integer, RawCase]
private var font = null: BufferedImage
def getCases: util.List[RawCase] = cases
def getCase(x: Int, y: Int): RawCase = {
if (cases_map == null) {
cases_map = new util.HashMap[Integer, RawCase]
getCases.forEach(c => cases_map.put(c.getPosY * width + c.getPosX, c))
}
cases_map.get(y * getWidth + x)
}
def getNeighbours(c: RawCase): util.Collection[RawCase] = {
val list = new util.ArrayList[RawCase]
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))
list.stream.filter((_c: RawCase) => _c != null && (_c.getCollision == Collision.ANY)).collect(Collectors.toList())
}
def getWidth: Int = width
def getHeight: Int = height
def getFont: BufferedImage = font
def setFont(font: BufferedImage): Unit = {
this.font = font
}
override def toString: String = new Gson().toJson(this)
}

View File

@ -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
}

View File

@ -0,0 +1,23 @@
package fr.ynerant.leveleditor.api.editor.sprites
import java.util
object Category {
def create(name: String, sprites: util.List[Sprite]): Category = {
val c = new Category
c.name = name
c.sprites = sprites
c
}
}
class Category private() {
private var sprites = null: util.List[Sprite]
private var name = null: String
def getName: String = name
def getSprites: util.List[Sprite] = sprites
override def toString: String = name
}

View File

@ -0,0 +1,38 @@
package fr.ynerant.leveleditor.api.editor.sprites
import java.awt._
import java.awt.image.BufferedImage
import java.util
import java.util.ArrayList
object Sprite {
val BLANK = new Sprite(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB), Category.create("blank", new util.ArrayList[Sprite]), 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.getSprites.add(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 + "}"
}

View File

@ -0,0 +1,108 @@
package fr.ynerant.leveleditor.api.editor.sprites
import java.io.{BufferedInputStream, BufferedReader, File, FileInputStream, IOException, InputStreamReader}
import java.net.{URISyntaxException, URLDecoder}
import java.nio.file.{Files, Paths}
import java.util
import java.util.Objects
import java.util.jar.JarFile
import com.google.gson.Gson
import javax.imageio.ImageIO
import fr.ynerant.leveleditor.client.main.Main
object SpriteRegister {
private var nameToCoords = null: util.Map[String, util.List[util.List[Double]]]
private val sprites = new util.HashMap[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.isEmpty && !sprites.isEmpty) return
val assetsDir = new File("assets")
val assets = new util.ArrayList[String]
for (dir <- Objects.requireNonNull(assetsDir.listFiles)) {
assets.add(dir.getName)
}
assets.forEach(asset => {
try {
val f = new File(assetsDir.getAbsolutePath + "/" + asset + "/textures/sprites")
assert(f.isDirectory || f.mkdirs)
val br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(f, "sprites.json"))))
nameToCoords = new Gson().fromJson(br, classOf[util.Map[_, _]])
br.close()
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, new util.ArrayList[Sprite])
nameToCoords.get(key).forEach(list => {
val x = list.get(0).intValue
val y = list.get(1).intValue
val child = img.getSubimage(x, y, 16, 16)
new Sprite(child, cat, nameToCoords.get(key).indexOf(list))
})
sprites.put(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.get(name)
def getAllCategories = new util.ArrayList[Category](sprites.values)
}

View File

@ -0,0 +1,185 @@
package fr.ynerant.leveleditor.client.main
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._
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 fr.ynerant.leveleditor.client.main.Main.DEV
/**
* Class principale qui lance le jeu
*
* @author ÿnérant
* @see #main(String...)
*/
object Main {
/**
* Variable disant si le jeu est lanc&eacute; en d&eacute;veloppement ou non.
*
* @see #isInDevelopmentMode()
* @see #main(String...)
* @since 0.1-aplha
*/
private var DEV = false
/**
* Accesseur disant si le jeu est lanc&eacute; en d&eacute;veloppement ou non.
*
* @see #DEV
* @since 0.1-alpha
*/
def isInDevelopmentMode: Boolean = DEV
/**
* @param args arguments du jeu. Possibilit&eacute;s :<br>&nbsp;&nbsp;&nbsp;&nbsp;<strong>--edit</strong> lancera un &eacute;diteur<br>&nbsp;&nbsp;&nbsp;&nbsp;<strong>--help</strong> 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, "<html>Cette application requiert <strong>Java 8</strong>.<br />La page de t\u00e9l\u00e9chargement va maintenant s'ouvrir.</html>")
JOptionPane.showMessageDialog(null, "<html>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,<br />ou si vous êtes plus expérimentés si le path vers Java est bien défini vers la bonne version.</html>")
try if (Desktop.isDesktopSupported) Desktop.getDesktop.browse(new URL("http://java.com/download").toURI)
else JOptionPane.showMessageDialog(null, "<html>Votre machine ne supporte pas la classe Desktop, impossible d'ouvrir la page.<br />Rendez-vous y manuellement sur <a href=\"http://java.com/download\">http://java.com/download</a> pour installer Java.</html>")
catch {
case e@(_: IOException | _: URISyntaxException) =>
e.printStackTrace()
}
System.exit(1)
}
}
/**
* Lance la fen&ecirc;tre principale
*
* @see #main(String...)
* @see #launchEditMode()
*/
private def launchFrame(): Unit = {
MainFrame.getInstance.setVisible(true)
}
/**
* Permet de lancer l'&eacute;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
}
}

View File

@ -0,0 +1,64 @@
package fr.ynerant.leveleditor.editor
import fr.ynerant.leveleditor.api.editor.Collision
import javax.swing._
import java.awt._
import java.awt.image.BufferedImage
@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 {
def getMap: Map = frame.getMap
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 ne Collision.ANY) {
val alpha = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB)
if (c.getCollision eq 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 eq 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)
}
})
}
}

View File

@ -0,0 +1,248 @@
package fr.ynerant.leveleditor.editor
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.io.File
import fr.ynerant.leveleditor.api.editor.{EditorAPI, RawMap}
@SerialVersionUID(-2705122356101556462L)
class EditorFrame(val map: Map) 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(600, 600)
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: Map = 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 = {
}
}

View File

@ -0,0 +1,60 @@
package fr.ynerant.leveleditor.editor
import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister
import java.awt.image.BufferedImage
import java.util
import fr.ynerant.leveleditor.api.editor.{Case, RawMap}
object Map {
private var cases = null: util.ArrayList[Case]
}
class Map(val raw: RawMap) {
final private var frame = null: EditorFrame
final private var width = 0
final private var height = 0
final private val casesMap = new util.HashMap[Integer, util.Map[Integer, Case]]
final private var font = null: BufferedImage
Map.cases = new util.ArrayList[Case]
this.width = raw.getWidth
this.height = raw.getHeight
this.font = raw.getFont
raw.getCases.forEach(rc =>
Map.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)
def getFrame: EditorFrame = frame
def getWidth: Int = width
def getHeight: Int = height
def getCase(x: Int, y: Int): Case = casesMap.getOrDefault(x, new util.HashMap[Integer, Case]).get(y)
def setCase(x: Int, y: Int, c: Case): Unit = {
casesMap.get(x).put(y, c)
}
def getFont: BufferedImage = font
private def reorganizeMap(): Unit = {
for (i <- 0 until width) {
casesMap.put(i, new util.HashMap[Integer, Case])
}
Map.cases.forEach(c => setCase(c.getPosX, c.getPosY, c))
}
def getAllCases: util.List[Case] = {
val list = new util.ArrayList[Case]
casesMap.values.forEach(l => list.addAll(l.values()))
list
}
}

View File

@ -0,0 +1,49 @@
package fr.ynerant.leveleditor.editor
import javax.swing._
import java.awt._
import java.awt.image.BufferedImage
@SerialVersionUID(2629019576253690557L)
class MapPanel(val frame: EditorFrame) extends JPanel {
def getMap: Map = frame.getMap
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 (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(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
}
}

View File

@ -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)
}
}
}

View File

@ -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
}
}

View File

@ -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&ecirc;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)
}

View File

@ -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)
}
}
}

View File

@ -0,0 +1,28 @@
package fr.ynerant.leveleditor.frame.listeners
import fr.ynerant.leveleditor.api.editor.{Case, Collision}
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
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 colIndex = c.getCollision.id
var newColIndex = colIndex + 1
if (newColIndex >= Collision.values.size) newColIndex = 0
val col = Collision.apply(newColIndex)
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()
}
}
}

View File

@ -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()
}
}

View File

@ -0,0 +1,69 @@
package fr.ynerant.leveleditor.frame.listeners
import java.awt.event.MouseAdapter
import java.awt.event.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)
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -0,0 +1,193 @@
package fr.ynerant.leveleditor.game
import fr.ynerant.leveleditor.api.editor.{Collision, RawMap}
import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister
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
import java.util.Random
import fr.ynerant.leveleditor.editor.CollidPanel
class GameFrame(val map: RawMap) extends JFrame("Jeu") {
final private val RANDOM = new Random
private var round = 0
private var hp = 5
private var reward = 20
final private val mobs = new util.ArrayList[Mob]
final private val towers = new util.ArrayList[Tower]
final private var basicTower = null: JRadioButton
final private var nullTower = null: JRadioButton
final private var autoTower = 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(600, 600)
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)
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 {
case e: InterruptedException =>
e.printStackTrace()
}
}
}).start()
repaint()
def getMap: RawMap = map
def tick(): Unit = {
if (mobs.isEmpty && round < 4) {
round += 1
val nb_mobs = round * (RANDOM.nextInt(16) + 1)
for (i <- 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 != Collision.ANY
})
getMap.getCase(mob.getX, mob.getY).setCollision(Collision.PARTIAL)
mobs.add(mob)
}
}
towers.forEach(tower => {
tower.filterDetectedMobs(mobs).forEach(mob => {
mob.hit(tower.getDamagePerShot)
})
})
new util.ArrayList[Mob](mobs).forEach(mob => {
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 -= 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 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.get(c.getCoucheOne.getIndex)
val s2 = SpriteRegister.getCategory(c.getCoucheTwo.getCategory).getSprites.get(c.getCoucheTwo.getIndex)
val 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)
})
new util.ArrayList[Mob](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 mouseClicked(event: MouseEvent): Unit = {
}
override def mousePressed(event: MouseEvent): Unit = {
}
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 (nullTower.isSelected) new NullTower(x, y)
else if (autoTower.isSelected) new AutoTower(x, y)
else null
if (tower == null || tower.getPrice > reward) return
val c = getMap.getCase(x, y)
if (c == null || (c.getCollision ne Collision.ANY)) return
c.setCollision(Collision.FULL)
reward -= tower.getPrice
towers.add(tower)
}
override def mouseEntered(event: MouseEvent): Unit = {
}
override def mouseExited(event: MouseEvent): Unit = {
}
}
}

View File

@ -0,0 +1,108 @@
package fr.ynerant.leveleditor.game.mobs
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
import java.util.Random
import fr.ynerant.leveleditor.api.editor.RawCase
object Mob {
private val RANDOM = new Random
def getRandomMob: Mob = RANDOM.nextInt(3) match {
case 1 =>
new Mob1
case 2 =>
new Mob2
case _ =>
new MobCancer
}
}
abstract class Mob() {
private var hp = getMaxHP
private var tickRemains = getSlowness
private var sprite = null: Sprite
private var x = 0
private var y = 0
def getMaxHP: Int
def getSlowness: Long
def getReward: Int
def getName: String
def getSprite: Sprite = {
if (sprite == null) sprite = SpriteRegister.getCategory(getName).getSprites.get(0)
sprite
}
def getX: Int = x
def getY: Int = y
def move(x: Int, y: Int): Unit = {
this.x = x
this.y = y
}
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
}
def tick(game: GameFrame): Unit = {
if (tickRemains > 0) tickRemains -= 1
else {
tickRemains = getSlowness
val current = game.getMap.getCase(getX, getY)
if (current.getPosX == 0) {
move(-1, getY)
return
}
val visited = new util.ArrayList[RawCase]
val queue = new util.ArrayDeque[RawCase]
val pred = new util.HashMap[RawCase, RawCase]
var last = null: RawCase
queue.add(current)
while (!queue.isEmpty) {
val visiting = queue.poll
visited.add(visiting)
game.getMap.getNeighbours(visiting).forEach(neighbour => {
if (neighbour != null && !visited.contains(neighbour)) {
pred.put(neighbour, visiting)
queue.add(neighbour)
if (neighbour.getPosX == 0) {
last = neighbour
queue.clear()
return
}
}
})
if (last != null) {
while (pred.get(last) != current) last = pred.get(last)
move(last.getPosX, last.getPosY)
}
}
}
}
override def toString: String = "Mob{" + "sprite=" + sprite + ", x=" + x + ", y=" + y + '}'
}

View File

@ -0,0 +1,11 @@
package fr.ynerant.leveleditor.game.mobs
class Mob1 extends Mob {
override def getMaxHP = 2
override def getSlowness = 60
override def getReward = 10
override def getName = "mob1"
}

View File

@ -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"
}

View File

@ -0,0 +1,11 @@
package fr.ynerant.leveleditor.game.mobs
class MobCancer extends Mob {
override def getMaxHP = 50
override def getSlowness = 100
override def getReward = 100
override def getName = "mobcancer"
}

View File

@ -0,0 +1,17 @@
package fr.ynerant.leveleditor.game.towers
import fr.ynerant.leveleditor.game.mobs.Mob
import java.util
class AutoTower(override val x: Int, override val y: Int) extends Tower(x, y) {
override def getName = "autotower"
override def getDamagePerShot = 20
override def getPeriod = 10
override def getPrice = 142
override private[towers] def _filterDetectedMobs(mobs: util.Collection[Mob]) = mobs
}

View File

@ -0,0 +1,23 @@
package fr.ynerant.leveleditor.game.towers
import fr.ynerant.leveleditor.game.mobs.Mob
import java.util
class BasicTower(override val x: Int, override val y: Int) extends Tower(x, y) {
override def getName = "basictower"
override def getDamagePerShot = 1
override def getPeriod = 5
override def getPrice = 10
override private[towers] def _filterDetectedMobs(mobs: util.Collection[Mob]) = {
val filtered = new util.ArrayList[Mob]
mobs.forEach(mob => {
if ((mob.getX == getX || mob.getY == getY) && Math.abs(mob.getX - getX) <= 3 && Math.abs(mob.getY - getY) <= 3) filtered.add(mob)
})
filtered
}
}

View File

@ -0,0 +1,17 @@
package fr.ynerant.leveleditor.game.towers
import fr.ynerant.leveleditor.game.mobs.Mob
import java.util
class NullTower(override val x: Int, override val y: Int) extends Tower(x, y) {
override def getName = "nulltower"
override def getDamagePerShot: Int = Integer.MAX_VALUE
override def getPeriod = 1
override def getPrice = 5
override private[towers] def _filterDetectedMobs(mobs: util.Collection[Mob]) = new util.ArrayList[Mob]
}

View File

@ -0,0 +1,42 @@
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
import java.util.Random
object Tower {
private val RANDOM = new Random
}
abstract class Tower(val x: Int, val y: Int) {
final private val sprite = SpriteRegister.getCategory(getName).getSprites.get(0)
private var remainingTicks = 0L
def getSprite: Sprite = sprite
def getName: String
def getDamagePerShot: Int
def getPeriod: Long
def getPrice: Int
private[towers] def _filterDetectedMobs(mobs: util.Collection[Mob]): util.Collection[Mob]
def filterDetectedMobs(mobs: util.Collection[Mob]): util.Collection[Mob] = if (remainingTicks > 0) {
remainingTicks -= 1
new util.ArrayList[Mob]
}
else {
remainingTicks = getPeriod
_filterDetectedMobs(mobs)
}
def getX: Int = x
def getY: Int = y
}