From 2c176589c24093ae93ec45e8d208dce81c27a515 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 19 Nov 2018 13:11:43 +0100 Subject: Create java package for the project --- Makefile | 34 ++- src/Actor.java | 94 -------- src/BattleScene.java | 323 ------------------------- src/GameWindow.java | 132 ----------- src/Map.java | 167 ------------- src/MapEditorScene.java | 235 ------------------ src/MapLoader.java | 69 ------ src/MapScene.java | 239 ------------------- src/Palette.java | 15 -- src/Scene.java | 164 ------------- src/Subconscious.java | 6 - src/Tile.java | 116 --------- src/Weapon.java | 44 ---- src/subconscious/Actor.java | 96 ++++++++ src/subconscious/Map.java | 169 +++++++++++++ src/subconscious/MapLoader.java | 71 ++++++ src/subconscious/Subconscious.java | 9 + src/subconscious/Tile.java | 118 +++++++++ src/subconscious/Weapon.java | 46 ++++ src/subconscious/graphics/BattleScene.java | 330 ++++++++++++++++++++++++++ src/subconscious/graphics/GameWindow.java | 132 +++++++++++ src/subconscious/graphics/MapEditorScene.java | 242 +++++++++++++++++++ src/subconscious/graphics/MapScene.java | 241 +++++++++++++++++++ src/subconscious/graphics/Scene.java | 166 +++++++++++++ src/subconscious/util/Palette.java | 17 ++ 25 files changed, 1658 insertions(+), 1617 deletions(-) delete mode 100644 src/Actor.java delete mode 100644 src/BattleScene.java delete mode 100644 src/GameWindow.java delete mode 100644 src/Map.java delete mode 100644 src/MapEditorScene.java delete mode 100644 src/MapLoader.java delete mode 100644 src/MapScene.java delete mode 100644 src/Palette.java delete mode 100644 src/Scene.java delete mode 100644 src/Subconscious.java delete mode 100644 src/Tile.java delete mode 100644 src/Weapon.java create mode 100644 src/subconscious/Actor.java create mode 100644 src/subconscious/Map.java create mode 100644 src/subconscious/MapLoader.java create mode 100644 src/subconscious/Subconscious.java create mode 100644 src/subconscious/Tile.java create mode 100644 src/subconscious/Weapon.java create mode 100644 src/subconscious/graphics/BattleScene.java create mode 100644 src/subconscious/graphics/GameWindow.java create mode 100644 src/subconscious/graphics/MapEditorScene.java create mode 100644 src/subconscious/graphics/MapScene.java create mode 100644 src/subconscious/graphics/Scene.java create mode 100644 src/subconscious/util/Palette.java diff --git a/Makefile b/Makefile index 3955d69..bdb14d3 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,25 @@ -MAINCLASS := Subconscious -JAVAC_ARGS := -Xlint:all +MAINCLASS := subconscious.Subconscious -.PHONY: all run pack build dirs clean -all: build +JAVAC := javac +JAVAC_ARGS := -Xlint:all \ + -classpath lib/gson-2.6.2.jar:. \ + -sourcepath src -run: build - cd bin && java -Dawt.useSystemAAFontSettings=on -cp ../lib/gson-2.6.2.jar:. $(MAINCLASS) +SOURCES := $(shell find src -iname '*.java') + +.PHONY: all run pack classes dirs clean +all: classes + +classes: + $(JAVAC) $(JAVAC_ARGS) -d build $(SOURCES) .ONESHELL: -pack: build +run: classes + cd build + java -Dawt.useSystemAAFontSettings=on -cp ../lib/gson-2.6.2.jar:. $(MAINCLASS) + +.ONESHELL: +pack: classes echo "Main-Class: $(MAINCLASS)" > jar/manifest.txt jar cvfm jar/$(MAINCLASS).jar jar/manifest.txt -C bin/ . rm jar/manifest.txt @@ -22,13 +33,10 @@ pack: build zip -r Subconcious.jar ./* find . ! -name 'Subconcious.jar' -type f -exec rm -f {} + rm -R com META-INF - -build: dirs - javac $(JAVAC_ARGS) -cp lib/gson-2.6.2.jar:. -d bin/ src/*.java + dirs: - mkdir -p src bin jar + mkdir -p build clean: - rm -R jar/* - rm bin/* + rm -rd build \ No newline at end of file diff --git a/src/Actor.java b/src/Actor.java deleted file mode 100644 index 7b4635f..0000000 --- a/src/Actor.java +++ /dev/null @@ -1,94 +0,0 @@ -public class Actor { - private final String name; - - // TODO: enemy should not be binary (ex clans / groups / factions) - private boolean isEnemy; - private int hp; - - private int x; - private int y; - - public class SkillSet { - public int agility = 0; - // public int strenght; - // public int defense; - } - - public SkillSet skills; - - private Weapon weapon; - private int actionsLeft; - // TODO: make final - private int actions = 2; - // TODO: make bonus / power-ups structure - - public Actor(String name, int hp, boolean isEnemy, int agility) { - this.name = name; - this.hp = hp; - this.isEnemy = isEnemy; - - this.skills = new SkillSet(); - this.skills.agility = agility; - - // TODO: puch should have infinite durability - this.weapon = new Weapon("fist", 1, 1, 10000000); - - this.resetActions(); - } - - public String getName() { return this.name; } - - public int getX() { return this.x; } - public int getY() { return this.y; } - - public Weapon getWeapon() { return this.weapon; } - public void equipWeapon(Weapon weapon) { this.weapon = weapon; } - - public void setHP(int hp) { this.hp = hp; } - public int getHP() { return this.hp; } - - public final SkillSet getSkills() { return this.skills; } - - public int getActionsLeft() { return this.actionsLeft; } - - public void resetActions() { - this.actionsLeft = this.actions; - } - - public boolean hit(Actor actor, Map map) { - if (this.actionsLeft > 0) { - if (this.weapon.damage(this, actor, map)) { - this.actionsLeft--; - return true; - } - } - return false; - } - - public boolean isAlive() { - return this.hp > 0; - } - - - public boolean isEnemy() { - return this.isEnemy; - } - - public void damage(int dmg) { - this.hp -= dmg; - } - - public void move(int x, int y) { - if (this.actionsLeft > 0) { - this.x = x; - this.y = y; - this.actionsLeft--; - } - } - - public void place(int x, int y) { - this.x = x; - this.y = y; - - } -} diff --git a/src/BattleScene.java b/src/BattleScene.java deleted file mode 100644 index 443d452..0000000 --- a/src/BattleScene.java +++ /dev/null @@ -1,323 +0,0 @@ -import java.util.ArrayList; -import java.util.Collections; - -import java.awt.Canvas; -import java.awt.Graphics2D; -import java.awt.Dimension; -import java.awt.BorderLayout; -import java.awt.GridLayout; - -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import java.awt.image.BufferStrategy; - -import java.awt.geom.Point2D; -import java.awt.geom.NoninvertibleTransformException; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JButton; - -public class BattleScene extends MapScene { - - private enum Mode { - NONE, ATTACK, MOVE - }; - - // TODO: refractor, make Points() - private int previousX = -1; - private int previousY = -1; - // TODO: what the fuck is the difference between these two? - private Actor selectedActor; - private Actor lastActor; - - private Mode mode; - - private boolean actorClicked = false; - - // TODO: these are the coordinates of the mouse => refractor names - private int realX = 0; - private int realY = 0; - - public BattleScene() { - super(); - - // TODO: this should be handled in MapScene - MapLoader mapLoader = new MapLoader("../testmap.json"); - this.map = mapLoader.getMap(); - - this.selectedActor = this.map.getNextActor(); - - this.setLayout(new BorderLayout()); - - // TODO: make a method buildUi() ? - JPanel bottomPanel = new JPanel(); - bottomPanel.setLayout(new GridLayout(1,4)); - - JButton moveButton = new JButton("Move"); - moveButton.setActionCommand("move"); - JButton attackButton = new JButton("Attack"); - attackButton.setActionCommand("attack"); - JButton nextButton = new JButton("Next"); - nextButton.setActionCommand("next"); - JButton passButton = new JButton("Pass"); - passButton.setActionCommand("pass"); - - moveButton.addActionListener(this); - attackButton.addActionListener(this); - nextButton.addActionListener(this); - passButton.addActionListener(this); - - bottomPanel.add(moveButton); - bottomPanel.add(attackButton); - bottomPanel.add(nextButton); - bottomPanel.add(passButton); - - this.add(bottomPanel, BorderLayout.PAGE_END); - this.add(this.canvas, BorderLayout.CENTER); - } - - @Override - protected void absoluteRender(Graphics2D g) { - //draw cursor - //g.setColor(Palette.BLUE); - //g.fillOval(this.realX-10*this.guiSize, this.realY-10*this.guiSize, 20*this.guiSize, 20*this.guiSize); - //g.setColor(Palette.ORANGE); - //g.drawOval(this.realX-10*this.guiSize, this.realY-10*this.guiSize, 20*this.guiSize, 20*this.guiSize); - - //draw panels - g.setColor(Palette.WHITE_T); - g.fillRect(this.canvasSize.width-100*this.guiSize, this.canvasSize.height-100*this.guiSize, - 100*this.guiSize, 100*this.guiSize); - g.fillRect(0, this.canvasSize.height-100*this.guiSize, 150*this.guiSize, 100*this.guiSize); - - g.setColor(Palette.BLACK); - g.setFont(g.getFont().deriveFont(12.0F*this.guiSize)); - Tile tile = null; - - try{ - tile = this.map.getTile(this.previousX, this.previousY); - switch (tile.getType()) { - case CLEAR: - break; - case GRASS: - g.drawString("Grass", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); - break; - case WATER: - g.drawString("Water", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); - break; - case MOUNTAIN: - g.drawString("Mountain", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); - break; - } - - g.setFont(g.getFont().deriveFont(8.0F*this.guiSize)); - if (this.actorClicked && this.lastActor != null) { - g.setColor(Palette.WHITE_T); - g.fillRect(0, 0, 100*this.guiSize, 150*this.guiSize); - g.fillRect(this.canvasSize.width-100*this.guiSize, 0, 100*this.guiSize, 100*this.guiSize); - - g.setColor(Palette.BLACK); - g.drawString(this.lastActor.getName(), 5*this.guiSize, 15*this.guiSize); - - g.drawString("HP", 5*this.guiSize, 30*this.guiSize); - g.setColor(Palette.RED); - g.fillRect(20*this.guiSize, 22*this.guiSize, 70*this.guiSize, 10*this.guiSize); - g.setColor(Palette.DARKGREEN); - g.fillRect(20*this.guiSize, 22*this.guiSize, 70*this.guiSize*this.lastActor.getHP()/10, 10*this.guiSize); - - g.setColor(Palette.BLACK); - g.drawString("Agility: " + Integer.toString(this.lastActor.getSkills().agility), - 5*this.guiSize, 45*this.guiSize); - } else if (this.actorClicked) { - g.setColor(Palette.WHITE_T); - g.fillRect(0, 0, 100*this.guiSize, 150*this.guiSize); - g.fillRect(this.canvasSize.width-100*this.guiSize, 0, 100*this.guiSize, 100*this.guiSize); - - g.setColor(Palette.BLACK); - g.drawString("None left", 5*this.guiSize, 15*this.guiSize); - } - } catch (ArrayIndexOutOfBoundsException ex) { - } catch (NullPointerException ext) { - System.out.println("map non existent"); - ext.printStackTrace(); - } - } - - @Override - protected void update(long deltaNanoTime) { - ArrayList actorsToRemove = new ArrayList<>(); - int enemyCounter = 0; - - for (Actor actor : this.map.getActors()) { - if (!actor.isAlive()) { - actorsToRemove.add(actor); - } - if (actor.isEnemy()) { - enemyCounter++; - } - } - - for (Actor actor : actorsToRemove) { - this.map.removeActor(actor); - } - - if (selectedActor != null) { - this.map.setCursor(selectedActor.getX(), selectedActor.getY()); - } else { - this.map.setCursor(-1, -1); - } - - if (enemyCounter == 0) { - // win - // TODO: reimplement on upper level - // this.main.backToMenu(); - } - } - - private void aiPlay() { - // TODO: write AI code - // give back control back to the player - this.map.resetActors(); - this.selectedActor = this.map.getNextActor(); - this.lastActor = this.selectedActor; - this.actorClicked = true; - } - - @Override - public void mouseClicked(MouseEvent e) { - - int tileSize = this.maxSize/10; - Point2D p = new Point2D.Double(e.getX(), e.getY()); - - try { - p = this.tx.inverseTransform(p, null); - } catch (NoninvertibleTransformException ex) {} - - try { - // find actor under cursor - int x = (int) (p.getX()/tileSize); - int y = (int) (p.getY()/tileSize); - Tile tile = this.map.getTile(x, y); - Actor actor = null; - - for (Actor i : this.map.getActors()) { - if (x == i.getX() && y == i.getY()) { - actor = i; - break; - } - } - - if (actor != null) { - this.actorClicked = true; - this.lastActor = actor; - } else { - this.actorClicked = false; - } - - if (this.mode == Mode.MOVE) { - if (tile.isSelected()) { - this.selectedActor.move(x, y); - this.mode = Mode.NONE; - this.map.clearSelected(); - if (this.selectedActor.getActionsLeft() <= 0) { - this.selectedActor = this.map.getNextActor(); - this.lastActor = this.selectedActor; - this.actorClicked = true; - } - } - } else if (this.mode == Mode.ATTACK) { - if (actor != null) { - this.selectedActor.hit(actor, this.map); - if (this.selectedActor.getActionsLeft() <= 0) { - this.selectedActor = this.map.getNextActor(); - this.lastActor = this.selectedActor; - this.actorClicked = true; - } - } - this.mode = Mode.NONE; - this.map.clearSelected(); - } - } catch (ArrayIndexOutOfBoundsException ex) { - System.out.println("no tile clicked"); - } catch (NullPointerException ext) { - //ext.printStackTrace(); - System.out.println("map non existent"); - } - } - - @Override - public void mouseMoved(MouseEvent e) { - this.realX = e.getX(); - this.realY = e.getY(); - int tileSize = this.maxSize/10; - Point2D p = new Point2D.Double(e.getX(), e.getY()); - try { - p = this.tx.inverseTransform(p, null); - } catch (NoninvertibleTransformException ex) {} - int x = (int) (p.getX()/tileSize); - int y = (int) (p.getY()/tileSize); - try { - Tile tile = this.map.getTile(x, y); - if (x != this.previousX || y != this.previousY) { - if (this.mode == Mode.MOVE) { - this.map.clearSelected(); - ArrayList path = this.map.getPath(this.selectedActor, x, y); - Collections.reverse(path); - for (int i=0; i=0 && - x+r < this.map.getSize() && - y+c >= 0 && - y+c < this.map.getSize()) { - this.map.getTile(x+r, y+c).setSelected(true); - } - } - } - this.mode = Mode.ATTACK; - } else if ("next".equals(e.getActionCommand())) { - this.map.clearSelected(); - this.selectedActor = this.map.getNextActor(); - this.lastActor = this.selectedActor; - this.actorClicked = true; - } - - } -} diff --git a/src/GameWindow.java b/src/GameWindow.java deleted file mode 100644 index a908a0a..0000000 --- a/src/GameWindow.java +++ /dev/null @@ -1,132 +0,0 @@ -// TODO: package - -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.CardLayout; -import java.awt.BorderLayout; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JButton; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - - -public class GameWindow extends JFrame implements ActionListener { - public static final Dimension WINDOW_SIZE = new Dimension(600, 400); - - public final String MENU_CARD = "menu"; - public final String SCENE_CARD = "scene"; - - private JPanel root; - - private Scene scene = null; - private Thread sceneThread = null; - - // TODO: remove map editor, start directly on Battle mode - public GameWindow() { - super("Subconscious"); - - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.setSize(WINDOW_SIZE); - this.setPreferredSize(WINDOW_SIZE); - this.setLocationRelativeTo(null); - - this.initComponents(); - - this.add(this.root, BorderLayout.CENTER); - this.pack(); - this.setVisible(true); - } - - private void initComponents() { - // set up a cardlayout - this.root = new JPanel(new CardLayout()); - - // build Menu card - JPanel menu = new JPanel(); - menu.setLayout(new GridLayout(3, 1)); - - JButton editor = new JButton("Editor"); - editor.setActionCommand("btn-editor"); - editor.addActionListener(this); - - JButton battle = new JButton("Battle"); - battle.setActionCommand("btn-battle"); - battle.addActionListener(this); - - JButton exit = new JButton("Exit"); - exit.setActionCommand("btn-exit"); - exit.addActionListener(this); - - menu.add(editor); - menu.add(battle); - menu.add(exit); - - // add cards - this.root.add(menu, MENU_CARD); - } - - public void showScene(Scene scene) { - // the current scene is already open - if (scene == this.scene) { - ((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD); - scene.updateCanvasSize(); - scene.resume(); - - return; - } - - // if there is an old scene - if (this.scene != null) { - // close old scene - this.scene.stop(); - try { - this.sceneThread.join(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - } - - // build new thread - this.scene = scene; - this.sceneThread = new Thread(this.scene); - - // add to layout - this.root.add(scene, SCENE_CARD); - ((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD); - - this.sceneThread.start(); - scene.updateCanvasSize(); - scene.resume(); - } - - public void showMenu() { - this.scene.pause(); - ((CardLayout)this.root.getLayout()).show(this, MENU_CARD); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().startsWith("btn")) { - if (e.getActionCommand().equals("btn-exit")) { - this.setVisible(false); - this.dispose(); - return; - } - - Scene scene = null; - - if (e.getActionCommand().equals("btn-editor")) { - scene = new MapEditorScene(); - } else if (e.getActionCommand().equals("btn-battle")) { - scene = new BattleScene(); - } - - if (scene != null) { - showScene(scene); - } - } - } -} diff --git a/src/Map.java b/src/Map.java deleted file mode 100644 index 0e0d1e3..0000000 --- a/src/Map.java +++ /dev/null @@ -1,167 +0,0 @@ -import java.awt.Dimension; -import java.util.ArrayList; - -public class Map { - private final Dimension size; - // TODO: is there a particular reason to not use a 2D array? - private final Tile grid[]; - private ArrayList actors = new ArrayList(); - // TODO: rename to selectedActor? - private int actorIndex = -1; - // TODO: make selectedTile? Tile contains x and y members - private int selectedX; - private int selectedY; - - public Map(Dimension size) { - this.size = size; - - // Populate grid with GRASS tiles - this.grid = new Tile[this.size.width * this.size.height]; - for (int x = 0; x < this.size.width; x++) { - for (int y = 0; y < this.size.height; y++) { - this.grid[x * this.size.width + y] = new Tile(Tile.Type.GRASS, x, y); - } - } - } - - // pathfinding algorithm - public ArrayList getPath(Actor actor, int x, int y) { - ArrayList unsettled = new ArrayList(); - ArrayList settled = new ArrayList(); - Tile startTile = this.getTile(actor.getX(), actor.getY()); - - for (Tile i : this.getGrid()) { - i.setDistance(10000000); - } - - startTile.setDistance(0); - unsettled.add(startTile); - settled.add(startTile); - - boolean stop = false; - while (unsettled.size() != 0) { - Tile workingTile = unsettled.get(0); - unsettled.remove(workingTile); - for (Tile i : workingTile.getAdjacent(this)) { - if (settled.contains(i)) { - continue; - } - i.setDistance(i.getCost(actor) + workingTile.getDistance()); - unsettled.add(i); - settled.add(i); - } - } - - ArrayList out = new ArrayList(); - Tile workingTile = this.getTile(x, y); - double bestDistance = 1000000000; - Tile bestTile = workingTile; - - while (true) { - for (Tile i : workingTile.getAdjacent(this)) { - if (i.getDistance() < bestDistance) { - bestDistance = i.getDistance(); - bestTile = i; - } - } - out.add(workingTile); - if (workingTile.getX() == startTile.getX() && workingTile.getY() == startTile.getY()) { - break; - } - workingTile = bestTile; - bestDistance = 1000000000; - } - - return out; - } - - public void update(ArrayList actorsList, Tile[] tileGrid) { - // TODO: if this is needed for something, implement copy constructors for Actor and Tile - // and delete this code - for (Actor actor : actorsList) { - Actor newActor = new Actor(actor.getName(), actor.getHP(), actor.isEnemy(), actor.getSkills().agility); - newActor.place(actor.getX(), actor.getY()); - this.actors.add(newActor); - } - - for (int x = 0; x < this.size.width; x++) { - for (int y = 0; y < this.size.height; y++) { - Tile.Type oldTileType = tileGrid[x * this.size.width + y].getType(); - this.grid[x * this.size.width + y] = new Tile(oldTileType, x, y); - } - } - } - - // TODO: refractor to resetActorActions(); - public void resetActors() { - for (Actor actor : this.actors) { - if (!actor.isEnemy()) { - actor.resetActions(); - } - } - } - - public Actor getNextActor() { - int counter = 0; - this.actorIndex++; - if (this.actorIndex >= this.actors.size()) { - this.actorIndex = 0; - } - Actor actor = this.actors.get(this.actorIndex); - while (actor.isEnemy() || actor.getActionsLeft() <= 0) { - this.actorIndex++; - if (this.actorIndex >= this.actors.size()) { - this.actorIndex = 0; - } - actor = this.actors.get(this.actorIndex); - if (counter > this.actors.size()*2) { - return null; - } - counter++; - } - return actor; - } - - // TODO: there is the Map cursor and the Mouse cursor, - // a solution to the naming shall be found - public void setCursor(int x, int y) { - this.getTile(this.selectedX, this.selectedY).setCursor(false); - if (x == -1 && y == -1) { - return; - } - this.getTile(x, y).setCursor(true); - this.selectedX = x; - this.selectedY = y; - } - - public Tile[] getGrid() { - return this.grid; - } - - public Tile getTile(int x, int y) { - return this.grid[x * this.size.width + y]; - } - - public int getSize() { - return this.size.width; - } - - public ArrayList getActors() { - return this.actors; - } - - public void removeActor(Actor actor) { - this.actors.remove(actor); - } - - public void addActor(Actor actor) { - this.actors.add(actor); - } - - // TODO: remove by introducing selectedTile member - public void clearSelected() { - for (Tile tile : this.grid) { - tile.setSelected(false); - } - } -} diff --git a/src/MapEditorScene.java b/src/MapEditorScene.java deleted file mode 100644 index 5f6bda5..0000000 --- a/src/MapEditorScene.java +++ /dev/null @@ -1,235 +0,0 @@ -import java.util.ArrayList; - -import java.awt.Canvas; -import java.awt.Graphics2D; -import java.awt.Dimension; -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferStrategy; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.NoninvertibleTransformException; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.JLabel; -import javax.swing.JTextField; -import javax.swing.JFileChooser; -import javax.swing.JCheckBox; - -import java.lang.Integer; - -public class MapEditorScene extends MapScene { - private Tile.Type placingTile = Tile.Type.CLEAR; - private Actor placingActor = new Actor("", 0, false, 0); - private ArrayList actorFields = new ArrayList<>(); - private JFrame actorFrame; - private boolean nukeActor = false; - - public MapEditorScene() { - super(); - this.setLayout(new BorderLayout()); - - JPanel bottomPanel = new JPanel(); - bottomPanel.setLayout(new GridLayout(1,5)); - - JButton newButton = new JButton("New"); - newButton.setActionCommand("new"); - JButton tileButton = new JButton("Placing selector"); - tileButton.setActionCommand("tile"); - JButton exportButton = new JButton("Export"); - exportButton.setActionCommand("export"); - JButton importButton = new JButton("Import"); - importButton.setActionCommand("import"); - JButton actorButton = new JButton("Actors"); - actorButton.setActionCommand("actors"); - - newButton.addActionListener(this); - tileButton.addActionListener(this); - actorButton.addActionListener(this); - exportButton.addActionListener(this); - importButton.addActionListener(this); - - bottomPanel.add(newButton); - bottomPanel.add(tileButton); - bottomPanel.add(actorButton); - bottomPanel.add(exportButton); - bottomPanel.add(importButton); - - this.add(bottomPanel, BorderLayout.PAGE_END); - this.add(this.canvas, BorderLayout.CENTER); - } - - @Override - protected void update(long deltaNanoTime) {} - - @Override - protected void absoluteRender(Graphics2D g2d) {} - - @Override - public void mouseClicked(MouseEvent e) { - int tileSize = this.maxSize/10; - Point2D p = new Point2D.Double(e.getX(), e.getY()); - try { - p = this.tx.inverseTransform(p, null); - } catch (NoninvertibleTransformException ex) {} - try { - int x = (int) p.getX()/tileSize; - int y = (int) p.getY()/tileSize; - this.map.getTile(x, y); - if (this.placingTile != Tile.Type.NONE) { - this.map.getTile(x, y).setType(this.placingTile); - } else { - if (!this.nukeActor) { - Actor actor = this.placingActor; - actor.place(x, y); - this.map.addActor(actor); - } else { - Actor toNuke = this.placingActor; - for (Actor actor : this.map.getActors()) { - if (x == actor.getX() && y == actor.getY()) { - toNuke = actor; - } - } - this.map.removeActor(toNuke); - } - } - } catch (ArrayIndexOutOfBoundsException ex) { - System.out.println("no tile clicked"); - } catch (NullPointerException ext) { - System.out.println("map non existent"); - } - } - - @Override - public void actionPerformed(ActionEvent e) { - if ("new".equals(e.getActionCommand())) { - JTextField size = new JTextField(); - - JComponent[] inputs = new JComponent[] { - new JLabel("Size"), - size, - }; - - int result = JOptionPane.showConfirmDialog(null, inputs, "New map", JOptionPane.DEFAULT_OPTION); - if (result == JOptionPane.OK_OPTION) { - int sizeN = Integer.parseInt(size.getText()); - this.map = new Map(new Dimension(sizeN, sizeN)); - } - } else if ("tile".equals(e.getActionCommand())) { - String[] values = {"Clear", "Grass", "Water", "Mountain", "Actor", "Remove Actor"}; - - Object result = JOptionPane.showInputDialog(null, "Tile Type", "Tile Type Selector", JOptionPane.DEFAULT_OPTION, null, values, "0"); - if (result != null) { - String selected = result.toString(); - switch (selected) { - case "Clear": - this.placingTile = Tile.Type.CLEAR; - break; - case "Grass": - this.placingTile = Tile.Type.GRASS; - break; - case "Water": - this.placingTile = Tile.Type.WATER; - break; - case "Mountain": - this.placingTile = Tile.Type.MOUNTAIN; - break; - case "Actor": - this.placingTile = Tile.Type.NONE; - this.nukeActor = false; - break; - case "Remove Actor": - this.placingTile = Tile.Type.NONE; - this.nukeActor = true; - break; - - } - } - } else if ("export".equals(e.getActionCommand())) { - JFileChooser fc = new JFileChooser(); - fc.showSaveDialog(null); - - MapLoader mapLoader = new MapLoader(fc.getSelectedFile()); - mapLoader.saveMap(this.map); - } else if ("import".equals(e.getActionCommand())) { - JFileChooser fc = new JFileChooser(); - fc.showOpenDialog(null); - - MapLoader mapLoader = new MapLoader(fc.getSelectedFile()); - this.map = mapLoader.getMap(); - } else if ("actors".equals(e.getActionCommand())) { - JFrame actorFrame = new JFrame("Actors"); - actorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - actorFrame.setSize(new Dimension(300, 400)); - actorFrame.setLocationRelativeTo(null); - - JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(5,2)); - - JLabel lName = new JLabel("Name"); - JTextField name = new JTextField(); - JLabel lAgility = new JLabel("Agility"); - JTextField agility = new JTextField(); - JLabel lHp = new JLabel("max HP"); - JTextField hp = new JTextField(); - JCheckBox enemy = new JCheckBox("Enemy"); - JLabel empty = new JLabel(); - JButton ok = new JButton("Confirm"); - ok.setActionCommand("actOk"); - JButton cancel = new JButton("Cancel"); - cancel.setActionCommand("actCancel"); - - ArrayList actorFields = new ArrayList<>(); - actorFields.add(name); - actorFields.add(hp); - actorFields.add(agility); - actorFields.add(enemy); - this.actorFields = actorFields; - - ok.addActionListener(this); - cancel.addActionListener(this); - - panel.add(lName); - panel.add(name); - panel.add(lAgility); - panel.add(agility); - panel.add(lHp); - panel.add(hp); - panel.add(enemy); - panel.add(empty); - panel.add(ok); - panel.add(cancel); - - actorFrame.add(panel); - actorFrame.pack(); - actorFrame.setVisible(true); - - this.actorFrame = actorFrame; - } else if ("actOk".equals(e.getActionCommand())) { - JTextField nameField = (JTextField) this.actorFields.get(0); - String name = nameField.getText(); - JTextField hpField = (JTextField) this.actorFields.get(1); - int hp = Integer.parseInt(hpField.getText()); - JTextField agilityField = (JTextField) this.actorFields.get(2); - int agility = Integer.parseInt(agilityField.getText()); - JCheckBox enemyBox = (JCheckBox) this.actorFields.get(3); - Actor actor = new Actor(name, hp, enemyBox.isSelected(), agility); - this.placingActor = actor; - this.actorFrame.setVisible(false); - this.actorFrame.dispose(); - } else if ("actCancel".equals(e.getActionCommand())) { - this.actorFrame.setVisible(false); - this.actorFrame.dispose(); - } - - } -} diff --git a/src/MapLoader.java b/src/MapLoader.java deleted file mode 100644 index 4bd4e02..0000000 --- a/src/MapLoader.java +++ /dev/null @@ -1,69 +0,0 @@ -import java.lang.String; - -// TODO: use java.nio? http://tutorials.jenkov.com/java-nio/nio-vs-io.html -import java.io.File; -import java.io.PrintWriter; -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; - -import java.awt.Dimension; - -import com.google.gson.Gson; - -// TODO: this class loads AND saves classes, refractor name -class MapLoader { - File path; - - public MapLoader(Object path) { - if (path instanceof java.io.File) { - this.path = (File) path; - } else { - this.path = new File((String) path); - } - } - - public Map getMap() { - String mapText = ""; - String line = null; - FileReader fr = null; - BufferedReader bf = null; - - try { - fr = new FileReader(this.path); - bf = new BufferedReader(fr); - // TODO: read all at once - while ((line = bf.readLine()) != null) { - mapText = mapText + line; - } - bf.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - - Gson gson = new Gson(); - Map importMap = gson.fromJson(mapText, Map.class); - - // TODO: ask @mafaldo why is there a copy? - // update map with new classes - // Map map = new Map(new Dimension(importMap.getSize(), importMap.getSize())); - // map.update(importMap.getActors(), importMap.getGrid()); - // return map; - - return importMap; - } - - public void saveMap(Map map) { - Gson gson = new Gson(); - String mapText = gson.toJson(map); - PrintWriter out = null; - try { - out = new PrintWriter(this.path + ".json"); - } catch (FileNotFoundException ex) { - ex.printStackTrace(); - } - out.println(mapText); - out.close(); - } -} diff --git a/src/MapScene.java b/src/MapScene.java deleted file mode 100644 index 7ed8e3b..0000000 --- a/src/MapScene.java +++ /dev/null @@ -1,239 +0,0 @@ -import java.awt.Canvas; -import java.awt.Graphics2D; -import java.awt.BasicStroke; -import java.awt.Dimension; -import java.awt.BorderLayout; -import java.awt.GridLayout; - -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import java.awt.image.BufferStrategy; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.NoninvertibleTransformException; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JButton; - -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.IOException; - -// TODO: remove unused import -import com.google.gson.Gson; - - -public abstract class MapScene extends Scene implements ActionListener { - protected Map map; - - protected int panX = 0; - protected int panY = 0; - - protected boolean panning = false; - protected double zoom = 1; - - protected int mouseX; - protected int mouseY; - - protected boolean zooming = false; - - protected int maxSize; - protected AffineTransform tx = new AffineTransform(); - - public MapScene() { - super(); - //this.map = new Map(new Dimension(10, 10)); - } - - @Override - protected void render() { - if (this.canvasSize.width < this.canvasSize.height) { - this.maxSize = WIDTH; - } else { - this.maxSize = HEIGHT; - } - - // TODO: negate if condition and return - if (this.map == null) { - return; - } - - Graphics2D g = (Graphics2D) this.buffer.getDrawGraphics(); - //clear - g.setColor(Palette.BLACK); - g.fillRect(0, 0, this.canvasSize.width, this.canvasSize.height); - - //zoom and pan - if (this.zooming) { - Point2D p1 = new Point2D.Double(this.mouseX, this.mouseY); - Point2D p2 = null; - try { - p2 = tx.inverseTransform(p1, null); - } catch (NoninvertibleTransformException ex) {} - this.tx.setToIdentity(); - this.tx.translate(p1.getX(), p1.getY()); - this.tx.scale(this.zoom, this.zoom); - this.tx.translate(-p2.getX(), -p2.getY()); - this.zooming = false; - } - if (this.panning) { - this.tx.translate(this.panX/this.zoom, this.panY/this.zoom); - this.panning = false; - this.panX = 0; - this.panY = 0; - } - - g.transform(this.tx); - - //draw tiles - int tileSize = this.maxSize / 10; - for (Tile tile : this.map.getGrid()) { - switch (tile.getType()) { - case CLEAR: - continue; - case GRASS: - g.setColor(Palette.GREEN); - break; - case WATER: - g.setColor(Palette.BLUE); - break; - case MOUNTAIN: - g.setColor(Palette.BROWN); - break; - } - - g.fillRect( - tileSize * tile.getX(), tileSize * tile.getY(), - tileSize, tileSize); - - if (tile.isSelected()) { - g.setColor(Palette.ORANGE_T); - //g.fillRect(tileSize * tile.getX() + tileSize/4, tileSize * tile.getY() + tileSize/4, - // tileSize/2, tileSize/2); - g.fillRect( - tileSize * tile.getX(), tileSize * tile.getY(), - tileSize, tileSize); - } - - //TODO: set as class variables the storkes - if (tile.cursorOnIt()) { - BasicStroke oldStroke = (BasicStroke) g.getStroke(); - g.setStroke(new BasicStroke( - 10.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL - )); - g.setColor(Palette.ORANGE); - g.drawRect( - tileSize * tile.getX(), tileSize * tile.getY(), - tileSize, tileSize); - g.setStroke(oldStroke); - } - - - g.setPaint(Palette.BLACK); - g.drawRect( - tileSize * tile.getX(), tileSize * tile.getY(), - tileSize, tileSize); - } - - g.setColor(Palette.ORANGE); - int maxBound = this.map.getSize()*tileSize; - g.drawRect(0, 0, maxBound, maxBound); - - //draw actors - g.setFont(g.getFont().deriveFont(g.getFont().getSize()*2.0F)); - for (Actor actor: this.map.getActors()) { - if (actor.isEnemy()) { - g.setColor(Palette.RED); - } else { - g.setColor(Palette.BLUE); - } - g.fillRect(tileSize * actor.getX() + tileSize/5, tileSize * actor.getY() + tileSize/5, - 3*tileSize/5, 3*tileSize/5); - g.setColor(Palette.BLACK); - g.drawString(actor.getName(), tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20); - g.setColor(Palette.RED); - g.fillRect(tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20+tileSize/30, - (tileSize*4/5), tileSize/10); - g.setColor(Palette.DARKGREEN); - g.fillRect(tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20+tileSize/30, - (tileSize*4/5)*actor.getHP()/10, tileSize/10); - } - - // Restore absolute coordinates - AffineTransform invertTx = null; - try { - invertTx = this.tx.createInverse(); - } catch (NoninvertibleTransformException ex) {} - - g.transform(invertTx); - this.absoluteRender(g); - - g.dispose(); - this.buffer.show(); - } - - protected abstract void absoluteRender(Graphics2D g); - - @Override - public void keyPressed(KeyEvent e) { - int keyCode = e.getKeyCode(); - switch (keyCode) { - case KeyEvent.VK_UP: - this.panY += 10; - break; - case KeyEvent.VK_DOWN: - this.panY -= 10; - break; - case KeyEvent.VK_LEFT: - this.panX += 10; - break; - case KeyEvent.VK_RIGHT: - this.panX -= 10; - break; - } - } - - @Override - public void mousePressed(MouseEvent e) { - this.mouseX = e.getX(); - this.mouseY = e.getY(); - } - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - this.panX += x - this.mouseX; - this.panY += y - this.mouseY; - this.mouseX = x; - this.mouseY = y; - this.panning = true; - } - - @Override - public void mouseMoved(MouseEvent e) { - } - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - this.mouseX = e.getX(); - this.mouseY = e.getY(); - if (this.zoom > 0.3 || e.getWheelRotation() < 0) { - this.zoom -= ((double) e.getWheelRotation())/5; - } - this.zooming = true; - } - - @Override - public void actionPerformed(ActionEvent e) {} -} diff --git a/src/Palette.java b/src/Palette.java deleted file mode 100644 index ee4d747..0000000 --- a/src/Palette.java +++ /dev/null @@ -1,15 +0,0 @@ -import java.awt.Color; - -public class Palette { - public final static Color BLACK = new Color(29, 31, 33); - public final static Color WHITE = new Color(197, 200, 198); - public final static Color WHITE_T = new Color(197, 200, 198, 200); - public final static Color RED = new Color(165, 66, 66); - public final static Color YELLOW = new Color(250, 198, 116); - public final static Color GREEN = new Color(181, 189, 104); - public final static Color DARKGREEN = new Color(140, 148, 64); - public final static Color BLUE = new Color(95, 129, 157); - public final static Color ORANGE = new Color(222, 147, 95); - public final static Color ORANGE_T = new Color(222, 147, 95, 100); - public final static Color BROWN = new Color(51, 41, 33); -} diff --git a/src/Scene.java b/src/Scene.java deleted file mode 100644 index 0ecf22f..0000000 --- a/src/Scene.java +++ /dev/null @@ -1,164 +0,0 @@ -import java.awt.Canvas; -import java.awt.Graphics2D; -import java.awt.Dimension; -import java.awt.BorderLayout; - -import java.awt.event.KeyListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelListener; -import java.awt.event.MouseWheelEvent; -import java.awt.image.BufferStrategy; - -import javax.swing.JFrame; -import javax.swing.JPanel; - -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; - -public abstract class Scene extends JPanel - implements Runnable, KeyListener, MouseListener, MouseMotionListener, - MouseWheelListener, ComponentListener { - - protected final long DESIRED_FPS = 60; - protected final long DESIRED_DELTA_LOOP = (1000*1000*1000)/DESIRED_FPS; - - protected boolean running; - protected boolean paused; - protected Object pauseLock; - - protected BufferStrategy buffer; - protected Dimension canvasSize; - protected Canvas canvas; - - // TODO: make accessible from user settings - protected int guiSize = 2; - - protected Scene() { - - this.canvasSize = GameWindow.WINDOW_SIZE; - this.canvas = new Canvas(); - - this.canvas.setBounds(0, 0, this.canvasSize.width, this.canvasSize.height); - this.canvas.setIgnoreRepaint(true); - - this.canvas.addKeyListener(this); - this.canvas.addMouseListener(this); - this.canvas.addMouseMotionListener(this); - this.canvas.addMouseWheelListener(this); - } - - private void initCanvasBuffer() { - this.canvas.createBufferStrategy(2); - this.buffer = this.canvas.getBufferStrategy(); - - this.canvas.requestFocus(); - } - - public void run() { - long beginLoopTime; - long endLoopTime; - long currentUpdateTime = System.nanoTime(); - long lastUpdateTime; - long deltaLoop; - - this.initCanvasBuffer(); - - this.running = true; - this.paused = false; - pauseLock = new Object(); - - while (running) { - beginLoopTime = System.nanoTime(); - - synchronized (this.pauseLock) { - if (this.paused) { - try { - this.pauseLock.wait(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - break; - } - } - } - - this.render(); - - lastUpdateTime = currentUpdateTime; - currentUpdateTime = System.nanoTime(); - - this.update(currentUpdateTime - lastUpdateTime); - - endLoopTime = System.nanoTime(); - deltaLoop = endLoopTime - beginLoopTime; - - if (deltaLoop > this.DESIRED_DELTA_LOOP) { - // TODO: late => skip frame - } else { - try { - Thread.sleep((this.DESIRED_DELTA_LOOP - deltaLoop)/(1000*1000)); - } catch (InterruptedException e ) { - - } - } - } - } - - public synchronized void stop() { - this.running = false; - - // stop thread even if paused - this.resume(); - } - - public synchronized void pause() { - this.paused = true; - } - - public synchronized void resume() { - if (!paused) - return; - - this.paused = false; - this.pauseLock.notifyAll(); - } - - // automagically set the canvas size to the parent's size - public synchronized void updateCanvasSize() { - this.canvasSize = this.getParent().getSize(); - } - - public synchronized void setCanvasSize(Dimension newSize) { - this.canvasSize = newSize; - } - - protected abstract void render(); - protected abstract void update(long deltaNanoTime); - - @Override - public void keyTyped(KeyEvent e) {} - public void keyPressed(KeyEvent e) {} - public void keyReleased(KeyEvent e) {} - - @Override - public void mouseClicked(MouseEvent e) {} - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) {} - public void mousePressed(MouseEvent e) {} - public void mouseReleased(MouseEvent e) {} - public void mouseDragged(MouseEvent e) {} - public void mouseMoved(MouseEvent e) {} - public void mouseWheelMoved(MouseWheelEvent e) {} - - @Override - public void componentResized(ComponentEvent e) { - this.updateCanvasSize(); - } - - public void componentMoved(ComponentEvent e) {} - public void componentShown(ComponentEvent e) {} - public void componentHidden(ComponentEvent e) {} - -} diff --git a/src/Subconscious.java b/src/Subconscious.java deleted file mode 100644 index 81bc25c..0000000 --- a/src/Subconscious.java +++ /dev/null @@ -1,6 +0,0 @@ - -public class Subconscious { - public static void main(String[] args) { - GameWindow w = new GameWindow(); - } -} \ No newline at end of file diff --git a/src/Tile.java b/src/Tile.java deleted file mode 100644 index 7420a2a..0000000 --- a/src/Tile.java +++ /dev/null @@ -1,116 +0,0 @@ -import java.util.ArrayList; - -public class Tile { - public enum Type { - CLEAR, GRASS, WATER, MOUNTAIN, NONE - }; - - // TODO: make public - private final int x, y; - // TODO: make final - private Type type; - // TODO: refractor to inRange; - private boolean selected; - // TODO: it would be better if the MapScene had a member tileUnderCursor - private boolean cursorOnIt; // underCursor? - // TODO: make final, or make a table to match type to cost - private double cost; - // TODO: remove and make here a method - // double distanceFrom(Tile other); - // or a method in Map.java - // double distanceBetween(Tile firstTile, Tile secondTile); - private double distance; - - public Tile(Type type, int x, int y) { - this.setType(type); - this.x = x; - this.y = y; - } - - public ArrayList getAdjacent(Map map) { - ArrayList out = new ArrayList<>(); - - if (this.getX() > 0) { - out.add(map.getTile(this.getX()-1, this.getY())); - } - - if (this.getX() < map.getSize()-1) { - out.add(map.getTile(this.getX()+1, this.getY())); - } - - if (this.getY() > 0) { - out.add(map.getTile(this.getX(), this.getY()-1)); - } - - if (this.getY() < map.getSize()-1) { - out.add(map.getTile(this.getX(), this.getY()+1)); - } - - return out; - } - - public boolean cursorOnIt() { - return this.cursorOnIt; - } - - public void setCursor(boolean cursor) { - this.cursorOnIt = cursor; - } - - public double getDistance() { - return this.distance; - } - - public void setDistance(double distance) { - this.distance = distance; - } - - public double getCost(Actor actor) { - return this.cost; - } - - public Type getType() { - return this.type; - } - - // TODO: remove this feature and make the member final - public void setType(Type type) { - this.type = type; - switch (this.type) { - case CLEAR: - this.cost = 1000000000.0; - break; - case GRASS: - this.cost = 1.0; - break; - case WATER: - this.cost = 3.0; - break; - case MOUNTAIN: - this.cost = 8.0; - break; - } - } - - public int getX() { - return this.x; - } - - public int getY() { - return this.y; - } - - public void setSelected(boolean set) { - this.selected = set; - } - - public boolean toggleSelect() { - this.selected = !this.selected; - return this.selected; - } - - // TODO: rename to isInRange() and this.selected => inRange - public boolean isSelected() { - return this.selected; - } -} diff --git a/src/Weapon.java b/src/Weapon.java deleted file mode 100644 index f20e0ca..0000000 --- a/src/Weapon.java +++ /dev/null @@ -1,44 +0,0 @@ -// TODO: there are object such as "puch" that need infinite durability -public class Weapon { - // TODO: if possible make final - private int damage; - private int durability; - private int range; - private String name; - - // TODO: add bonus / power-ups structure - // public class PowerUps {} - - public Weapon(String name, int damage, int range, int durability) { - this.name = name; - this.damage = damage; - this.range = range; - this.durability = durability; - } - - /* accessors */ - public String getName() { return this.name; } - public int getDamage() { return this.damage; } - public int getRange() { return this.range; } - public int getDurability() { return this.durability; } - - - public boolean isBroken() { - return this.durability <= 0; - } - - public boolean damage(Actor attacker, Actor attacked, Map map) { - if (isBroken()) { - return false; - } - - if (map.getTile(attacked.getX(), attacked.getY()).isSelected()) { - attacked.damage(this.damage); - this.durability--; - return true; - } else { - return false; - } - } - -} diff --git a/src/subconscious/Actor.java b/src/subconscious/Actor.java new file mode 100644 index 0000000..6551dab --- /dev/null +++ b/src/subconscious/Actor.java @@ -0,0 +1,96 @@ +package subconscious; + +public class Actor { + private final String name; + + // TODO: enemy should not be binary (ex clans / groups / factions) + private boolean isEnemy; + private int hp; + + private int x; + private int y; + + public class SkillSet { + public int agility = 0; + // public int strenght; + // public int defense; + } + + public SkillSet skills; + + private Weapon weapon; + private int actionsLeft; + // TODO: make final + private int actions = 2; + // TODO: make bonus / power-ups structure + + public Actor(String name, int hp, boolean isEnemy, int agility) { + this.name = name; + this.hp = hp; + this.isEnemy = isEnemy; + + this.skills = new SkillSet(); + this.skills.agility = agility; + + // TODO: puch should have infinite durability + this.weapon = new Weapon("fist", 1, 1, 10000000); + + this.resetActions(); + } + + public String getName() { return this.name; } + + public int getX() { return this.x; } + public int getY() { return this.y; } + + public Weapon getWeapon() { return this.weapon; } + public void equipWeapon(Weapon weapon) { this.weapon = weapon; } + + public void setHP(int hp) { this.hp = hp; } + public int getHP() { return this.hp; } + + public final SkillSet getSkills() { return this.skills; } + + public int getActionsLeft() { return this.actionsLeft; } + + public void resetActions() { + this.actionsLeft = this.actions; + } + + public boolean hit(Actor actor, Map map) { + if (this.actionsLeft > 0) { + if (this.weapon.damage(this, actor, map)) { + this.actionsLeft--; + return true; + } + } + return false; + } + + public boolean isAlive() { + return this.hp > 0; + } + + + public boolean isEnemy() { + return this.isEnemy; + } + + public void damage(int dmg) { + this.hp -= dmg; + } + + public void move(int x, int y) { + if (this.actionsLeft > 0) { + this.x = x; + this.y = y; + this.actionsLeft--; + } + } + + public void place(int x, int y) { + this.x = x; + this.y = y; + + } +} diff --git a/src/subconscious/Map.java b/src/subconscious/Map.java new file mode 100644 index 0000000..4402790 --- /dev/null +++ b/src/subconscious/Map.java @@ -0,0 +1,169 @@ +package subconscious; + +import java.awt.Dimension; +import java.util.ArrayList; + +public class Map { + private final Dimension size; + // TODO: is there a particular reason to not use a 2D array? + private final Tile grid[]; + private ArrayList actors = new ArrayList(); + // TODO: rename to selectedActor? + private int actorIndex = -1; + // TODO: make selectedTile? Tile contains x and y members + private int selectedX; + private int selectedY; + + public Map(Dimension size) { + this.size = size; + + // Populate grid with GRASS tiles + this.grid = new Tile[this.size.width * this.size.height]; + for (int x = 0; x < this.size.width; x++) { + for (int y = 0; y < this.size.height; y++) { + this.grid[x * this.size.width + y] = new Tile(Tile.Type.GRASS, x, y); + } + } + } + + // pathfinding algorithm + public ArrayList getPath(Actor actor, int x, int y) { + ArrayList unsettled = new ArrayList(); + ArrayList settled = new ArrayList(); + Tile startTile = this.getTile(actor.getX(), actor.getY()); + + for (Tile i : this.getGrid()) { + i.setDistance(10000000); + } + + startTile.setDistance(0); + unsettled.add(startTile); + settled.add(startTile); + + boolean stop = false; + while (unsettled.size() != 0) { + Tile workingTile = unsettled.get(0); + unsettled.remove(workingTile); + for (Tile i : workingTile.getAdjacent(this)) { + if (settled.contains(i)) { + continue; + } + i.setDistance(i.getCost(actor) + workingTile.getDistance()); + unsettled.add(i); + settled.add(i); + } + } + + ArrayList out = new ArrayList(); + Tile workingTile = this.getTile(x, y); + double bestDistance = 1000000000; + Tile bestTile = workingTile; + + while (true) { + for (Tile i : workingTile.getAdjacent(this)) { + if (i.getDistance() < bestDistance) { + bestDistance = i.getDistance(); + bestTile = i; + } + } + out.add(workingTile); + if (workingTile.getX() == startTile.getX() && workingTile.getY() == startTile.getY()) { + break; + } + workingTile = bestTile; + bestDistance = 1000000000; + } + + return out; + } + + public void update(ArrayList actorsList, Tile[] tileGrid) { + // TODO: if this is needed for something, implement copy constructors for Actor and Tile + // and delete this code + for (Actor actor : actorsList) { + Actor newActor = new Actor(actor.getName(), actor.getHP(), actor.isEnemy(), actor.getSkills().agility); + newActor.place(actor.getX(), actor.getY()); + this.actors.add(newActor); + } + + for (int x = 0; x < this.size.width; x++) { + for (int y = 0; y < this.size.height; y++) { + Tile.Type oldTileType = tileGrid[x * this.size.width + y].getType(); + this.grid[x * this.size.width + y] = new Tile(oldTileType, x, y); + } + } + } + + // TODO: refractor to resetActorActions(); + public void resetActors() { + for (Actor actor : this.actors) { + if (!actor.isEnemy()) { + actor.resetActions(); + } + } + } + + public Actor getNextActor() { + int counter = 0; + this.actorIndex++; + if (this.actorIndex >= this.actors.size()) { + this.actorIndex = 0; + } + Actor actor = this.actors.get(this.actorIndex); + while (actor.isEnemy() || actor.getActionsLeft() <= 0) { + this.actorIndex++; + if (this.actorIndex >= this.actors.size()) { + this.actorIndex = 0; + } + actor = this.actors.get(this.actorIndex); + if (counter > this.actors.size()*2) { + return null; + } + counter++; + } + return actor; + } + + // TODO: there is the Map cursor and the Mouse cursor, + // a solution to the naming shall be found + public void setCursor(int x, int y) { + this.getTile(this.selectedX, this.selectedY).setCursor(false); + if (x == -1 && y == -1) { + return; + } + this.getTile(x, y).setCursor(true); + this.selectedX = x; + this.selectedY = y; + } + + public Tile[] getGrid() { + return this.grid; + } + + public Tile getTile(int x, int y) { + return this.grid[x * this.size.width + y]; + } + + public int getSize() { + return this.size.width; + } + + public ArrayList getActors() { + return this.actors; + } + + public void removeActor(Actor actor) { + this.actors.remove(actor); + } + + public void addActor(Actor actor) { + this.actors.add(actor); + } + + // TODO: remove by introducing selectedTile member + public void clearSelected() { + for (Tile tile : this.grid) { + tile.setSelected(false); + } + } +} diff --git a/src/subconscious/MapLoader.java b/src/subconscious/MapLoader.java new file mode 100644 index 0000000..2233a8d --- /dev/null +++ b/src/subconscious/MapLoader.java @@ -0,0 +1,71 @@ +package subconscious; + +import java.lang.String; + +// TODO: use java.nio? http://tutorials.jenkov.com/java-nio/nio-vs-io.html +import java.io.File; +import java.io.PrintWriter; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; + +import java.awt.Dimension; + +import com.google.gson.Gson; + +// TODO: this class loads AND saves classes, refractor name +public class MapLoader { + File path; + + public MapLoader(Object path) { + if (path instanceof java.io.File) { + this.path = (File) path; + } else { + this.path = new File((String) path); + } + } + + public Map getMap() { + String mapText = ""; + String line = null; + FileReader fr = null; + BufferedReader bf = null; + + try { + fr = new FileReader(this.path); + bf = new BufferedReader(fr); + // TODO: read all at once + while ((line = bf.readLine()) != null) { + mapText = mapText + line; + } + bf.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + + Gson gson = new Gson(); + Map importMap = gson.fromJson(mapText, Map.class); + + // TODO: ask @mafaldo why is there a copy? + // update map with new classes + // Map map = new Map(new Dimension(importMap.getSize(), importMap.getSize())); + // map.update(importMap.getActors(), importMap.getGrid()); + // return map; + + return importMap; + } + + public void saveMap(Map map) { + Gson gson = new Gson(); + String mapText = gson.toJson(map); + PrintWriter out = null; + try { + out = new PrintWriter(this.path + ".json"); + } catch (FileNotFoundException ex) { + ex.printStackTrace(); + } + out.println(mapText); + out.close(); + } +} diff --git a/src/subconscious/Subconscious.java b/src/subconscious/Subconscious.java new file mode 100644 index 0000000..384393a --- /dev/null +++ b/src/subconscious/Subconscious.java @@ -0,0 +1,9 @@ +package subconscious; + +import subconscious.graphics.GameWindow; + +public class Subconscious { + public static void main(String[] args) { + GameWindow w = new GameWindow(); + } +} \ No newline at end of file diff --git a/src/subconscious/Tile.java b/src/subconscious/Tile.java new file mode 100644 index 0000000..2678043 --- /dev/null +++ b/src/subconscious/Tile.java @@ -0,0 +1,118 @@ +package subconscious; + +import java.util.ArrayList; + +public class Tile { + public enum Type { + CLEAR, GRASS, WATER, MOUNTAIN, NONE + }; + + // TODO: make public + private final int x, y; + // TODO: make final + private Type type; + // TODO: refractor to inRange; + private boolean selected; + // TODO: it would be better if the MapScene had a member tileUnderCursor + private boolean cursorOnIt; // underCursor? + // TODO: make final, or make a table to match type to cost + private double cost; + // TODO: remove and make here a method + // double distanceFrom(Tile other); + // or a method in Map.java + // double distanceBetween(Tile firstTile, Tile secondTile); + private double distance; + + public Tile(Type type, int x, int y) { + this.setType(type); + this.x = x; + this.y = y; + } + + public ArrayList getAdjacent(Map map) { + ArrayList out = new ArrayList<>(); + + if (this.getX() > 0) { + out.add(map.getTile(this.getX()-1, this.getY())); + } + + if (this.getX() < map.getSize()-1) { + out.add(map.getTile(this.getX()+1, this.getY())); + } + + if (this.getY() > 0) { + out.add(map.getTile(this.getX(), this.getY()-1)); + } + + if (this.getY() < map.getSize()-1) { + out.add(map.getTile(this.getX(), this.getY()+1)); + } + + return out; + } + + public boolean cursorOnIt() { + return this.cursorOnIt; + } + + public void setCursor(boolean cursor) { + this.cursorOnIt = cursor; + } + + public double getDistance() { + return this.distance; + } + + public void setDistance(double distance) { + this.distance = distance; + } + + public double getCost(Actor actor) { + return this.cost; + } + + public Type getType() { + return this.type; + } + + // TODO: remove this feature and make the member final + public void setType(Type type) { + this.type = type; + switch (this.type) { + case CLEAR: + this.cost = 1000000000.0; + break; + case GRASS: + this.cost = 1.0; + break; + case WATER: + this.cost = 3.0; + break; + case MOUNTAIN: + this.cost = 8.0; + break; + } + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public void setSelected(boolean set) { + this.selected = set; + } + + public boolean toggleSelect() { + this.selected = !this.selected; + return this.selected; + } + + // TODO: rename to isInRange() and this.selected => inRange + public boolean isSelected() { + return this.selected; + } +} diff --git a/src/subconscious/Weapon.java b/src/subconscious/Weapon.java new file mode 100644 index 0000000..8533b9f --- /dev/null +++ b/src/subconscious/Weapon.java @@ -0,0 +1,46 @@ +package subconscious; + +// TODO: there are object such as "puch" that need infinite durability +public class Weapon { + // TODO: if possible make final + private int damage; + private int durability; + private int range; + private String name; + + // TODO: add bonus / power-ups structure + // public class PowerUps {} + + public Weapon(String name, int damage, int range, int durability) { + this.name = name; + this.damage = damage; + this.range = range; + this.durability = durability; + } + + /* accessors */ + public String getName() { return this.name; } + public int getDamage() { return this.damage; } + public int getRange() { return this.range; } + public int getDurability() { return this.durability; } + + + public boolean isBroken() { + return this.durability <= 0; + } + + public boolean damage(Actor attacker, Actor attacked, Map map) { + if (isBroken()) { + return false; + } + + if (map.getTile(attacked.getX(), attacked.getY()).isSelected()) { + attacked.damage(this.damage); + this.durability--; + return true; + } else { + return false; + } + } + +} diff --git a/src/subconscious/graphics/BattleScene.java b/src/subconscious/graphics/BattleScene.java new file mode 100644 index 0000000..b21be04 --- /dev/null +++ b/src/subconscious/graphics/BattleScene.java @@ -0,0 +1,330 @@ +package subconscious.graphics; + +import subconscious.util.Palette; +import subconscious.Actor; +import subconscious.MapLoader; +import subconscious.Tile; + +import java.util.ArrayList; +import java.util.Collections; + +import java.awt.Canvas; +import java.awt.Graphics2D; +import java.awt.Dimension; +import java.awt.BorderLayout; +import java.awt.GridLayout; + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import java.awt.image.BufferStrategy; + +import java.awt.geom.Point2D; +import java.awt.geom.NoninvertibleTransformException; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JButton; + +public class BattleScene extends MapScene { + + private enum Mode { + NONE, ATTACK, MOVE + }; + + // TODO: refractor, make Points() + private int previousX = -1; + private int previousY = -1; + // TODO: what the fuck is the difference between these two? + private Actor selectedActor; + private Actor lastActor; + + private Mode mode; + + private boolean actorClicked = false; + + // TODO: these are the coordinates of the mouse => refractor names + private int realX = 0; + private int realY = 0; + + public BattleScene() { + super(); + + // TODO: this should be handled in MapScene + MapLoader mapLoader = new MapLoader("../testmap.json"); + this.map = mapLoader.getMap(); + + this.selectedActor = this.map.getNextActor(); + + this.setLayout(new BorderLayout()); + + // TODO: make a method buildUi() ? + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new GridLayout(1,4)); + + JButton moveButton = new JButton("Move"); + moveButton.setActionCommand("move"); + JButton attackButton = new JButton("Attack"); + attackButton.setActionCommand("attack"); + JButton nextButton = new JButton("Next"); + nextButton.setActionCommand("next"); + JButton passButton = new JButton("Pass"); + passButton.setActionCommand("pass"); + + moveButton.addActionListener(this); + attackButton.addActionListener(this); + nextButton.addActionListener(this); + passButton.addActionListener(this); + + bottomPanel.add(moveButton); + bottomPanel.add(attackButton); + bottomPanel.add(nextButton); + bottomPanel.add(passButton); + + this.add(bottomPanel, BorderLayout.PAGE_END); + this.add(this.canvas, BorderLayout.CENTER); + } + + @Override + protected void absoluteRender(Graphics2D g) { + //draw cursor + //g.setColor(Palette.BLUE); + //g.fillOval(this.realX-10*this.guiSize, this.realY-10*this.guiSize, 20*this.guiSize, 20*this.guiSize); + //g.setColor(Palette.ORANGE); + //g.drawOval(this.realX-10*this.guiSize, this.realY-10*this.guiSize, 20*this.guiSize, 20*this.guiSize); + + //draw panels + g.setColor(Palette.WHITE_T); + g.fillRect(this.canvasSize.width-100*this.guiSize, this.canvasSize.height-100*this.guiSize, + 100*this.guiSize, 100*this.guiSize); + g.fillRect(0, this.canvasSize.height-100*this.guiSize, 150*this.guiSize, 100*this.guiSize); + + g.setColor(Palette.BLACK); + g.setFont(g.getFont().deriveFont(12.0F*this.guiSize)); + Tile tile = null; + + try{ + tile = this.map.getTile(this.previousX, this.previousY); + switch (tile.getType()) { + case CLEAR: + break; + case GRASS: + g.drawString("Grass", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); + break; + case WATER: + g.drawString("Water", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); + break; + case MOUNTAIN: + g.drawString("Mountain", this.canvasSize.width-90*this.guiSize, this.canvasSize.height-80*this.guiSize); + break; + } + + g.setFont(g.getFont().deriveFont(8.0F*this.guiSize)); + if (this.actorClicked && this.lastActor != null) { + g.setColor(Palette.WHITE_T); + g.fillRect(0, 0, 100*this.guiSize, 150*this.guiSize); + g.fillRect(this.canvasSize.width-100*this.guiSize, 0, 100*this.guiSize, 100*this.guiSize); + + g.setColor(Palette.BLACK); + g.drawString(this.lastActor.getName(), 5*this.guiSize, 15*this.guiSize); + + g.drawString("HP", 5*this.guiSize, 30*this.guiSize); + g.setColor(Palette.RED); + g.fillRect(20*this.guiSize, 22*this.guiSize, 70*this.guiSize, 10*this.guiSize); + g.setColor(Palette.DARKGREEN); + g.fillRect(20*this.guiSize, 22*this.guiSize, 70*this.guiSize*this.lastActor.getHP()/10, 10*this.guiSize); + + g.setColor(Palette.BLACK); + g.drawString("Agility: " + Integer.toString(this.lastActor.getSkills().agility), + 5*this.guiSize, 45*this.guiSize); + } else if (this.actorClicked) { + g.setColor(Palette.WHITE_T); + g.fillRect(0, 0, 100*this.guiSize, 150*this.guiSize); + g.fillRect(this.canvasSize.width-100*this.guiSize, 0, 100*this.guiSize, 100*this.guiSize); + + g.setColor(Palette.BLACK); + g.drawString("None left", 5*this.guiSize, 15*this.guiSize); + } + } catch (ArrayIndexOutOfBoundsException ex) { + } catch (NullPointerException ext) { + System.out.println("map non existent"); + ext.printStackTrace(); + } + } + + @Override + protected void update(long deltaNanoTime) { + ArrayList actorsToRemove = new ArrayList<>(); + int enemyCounter = 0; + + for (Actor actor : this.map.getActors()) { + if (!actor.isAlive()) { + actorsToRemove.add(actor); + } + if (actor.isEnemy()) { + enemyCounter++; + } + } + + for (Actor actor : actorsToRemove) { + this.map.removeActor(actor); + } + + if (selectedActor != null) { + this.map.setCursor(selectedActor.getX(), selectedActor.getY()); + } else { + this.map.setCursor(-1, -1); + } + + if (enemyCounter == 0) { + // win + // TODO: reimplement on upper level + // this.main.backToMenu(); + } + } + + private void aiPlay() { + // TODO: write AI code + // give back control back to the player + this.map.resetActors(); + this.selectedActor = this.map.getNextActor(); + this.lastActor = this.selectedActor; + this.actorClicked = true; + } + + @Override + public void mouseClicked(MouseEvent e) { + + int tileSize = this.maxSize/10; + Point2D p = new Point2D.Double(e.getX(), e.getY()); + + try { + p = this.tx.inverseTransform(p, null); + } catch (NoninvertibleTransformException ex) {} + + try { + // find actor under cursor + int x = (int) (p.getX()/tileSize); + int y = (int) (p.getY()/tileSize); + Tile tile = this.map.getTile(x, y); + Actor actor = null; + + for (Actor i : this.map.getActors()) { + if (x == i.getX() && y == i.getY()) { + actor = i; + break; + } + } + + if (actor != null) { + this.actorClicked = true; + this.lastActor = actor; + } else { + this.actorClicked = false; + } + + if (this.mode == Mode.MOVE) { + if (tile.isSelected()) { + this.selectedActor.move(x, y); + this.mode = Mode.NONE; + this.map.clearSelected(); + if (this.selectedActor.getActionsLeft() <= 0) { + this.selectedActor = this.map.getNextActor(); + this.lastActor = this.selectedActor; + this.actorClicked = true; + } + } + } else if (this.mode == Mode.ATTACK) { + if (actor != null) { + this.selectedActor.hit(actor, this.map); + if (this.selectedActor.getActionsLeft() <= 0) { + this.selectedActor = this.map.getNextActor(); + this.lastActor = this.selectedActor; + this.actorClicked = true; + } + } + this.mode = Mode.NONE; + this.map.clearSelected(); + } + } catch (ArrayIndexOutOfBoundsException ex) { + System.out.println("no tile clicked"); + } catch (NullPointerException ext) { + //ext.printStackTrace(); + System.out.println("map non existent"); + } + } + + @Override + public void mouseMoved(MouseEvent e) { + this.realX = e.getX(); + this.realY = e.getY(); + int tileSize = this.maxSize/10; + Point2D p = new Point2D.Double(e.getX(), e.getY()); + try { + p = this.tx.inverseTransform(p, null); + } catch (NoninvertibleTransformException ex) {} + int x = (int) (p.getX()/tileSize); + int y = (int) (p.getY()/tileSize); + try { + Tile tile = this.map.getTile(x, y); + if (x != this.previousX || y != this.previousY) { + if (this.mode == Mode.MOVE) { + this.map.clearSelected(); + ArrayList path = this.map.getPath(this.selectedActor, x, y); + Collections.reverse(path); + for (int i=0; i=0 && + x+r < this.map.getSize() && + y+c >= 0 && + y+c < this.map.getSize()) { + this.map.getTile(x+r, y+c).setSelected(true); + } + } + } + this.mode = Mode.ATTACK; + } else if ("next".equals(e.getActionCommand())) { + this.map.clearSelected(); + this.selectedActor = this.map.getNextActor(); + this.lastActor = this.selectedActor; + this.actorClicked = true; + } + + } +} diff --git a/src/subconscious/graphics/GameWindow.java b/src/subconscious/graphics/GameWindow.java new file mode 100644 index 0000000..4d2f91c --- /dev/null +++ b/src/subconscious/graphics/GameWindow.java @@ -0,0 +1,132 @@ +package subconscious.graphics; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.CardLayout; +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JButton; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +public class GameWindow extends JFrame implements ActionListener { + public static final Dimension WINDOW_SIZE = new Dimension(600, 400); + + public final String MENU_CARD = "menu"; + public final String SCENE_CARD = "scene"; + + private JPanel root; + + private Scene scene = null; + private Thread sceneThread = null; + + // TODO: remove map editor, start directly on Battle mode + public GameWindow() { + super("Subconscious"); + + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.setSize(WINDOW_SIZE); + this.setPreferredSize(WINDOW_SIZE); + this.setLocationRelativeTo(null); + + this.initComponents(); + + this.add(this.root, BorderLayout.CENTER); + this.pack(); + this.setVisible(true); + } + + private void initComponents() { + // set up a cardlayout + this.root = new JPanel(new CardLayout()); + + // build Menu card + JPanel menu = new JPanel(); + menu.setLayout(new GridLayout(3, 1)); + + JButton editor = new JButton("Editor"); + editor.setActionCommand("btn-editor"); + editor.addActionListener(this); + + JButton battle = new JButton("Battle"); + battle.setActionCommand("btn-battle"); + battle.addActionListener(this); + + JButton exit = new JButton("Exit"); + exit.setActionCommand("btn-exit"); + exit.addActionListener(this); + + menu.add(editor); + menu.add(battle); + menu.add(exit); + + // add cards + this.root.add(menu, MENU_CARD); + } + + public void showScene(Scene scene) { + // the current scene is already open + if (scene == this.scene) { + ((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD); + scene.updateCanvasSize(); + scene.resume(); + + return; + } + + // if there is an old scene + if (this.scene != null) { + // close old scene + this.scene.stop(); + try { + this.sceneThread.join(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + + // build new thread + this.scene = scene; + this.sceneThread = new Thread(this.scene); + + // add to layout + this.root.add(scene, SCENE_CARD); + ((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD); + + this.sceneThread.start(); + scene.updateCanvasSize(); + scene.resume(); + } + + public void showMenu() { + this.scene.pause(); + ((CardLayout)this.root.getLayout()).show(this, MENU_CARD); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().startsWith("btn")) { + if (e.getActionCommand().equals("btn-exit")) { + this.setVisible(false); + this.dispose(); + return; + } + + Scene scene = null; + + if (e.getActionCommand().equals("btn-editor")) { + scene = new MapEditorScene(); + } else if (e.getActionCommand().equals("btn-battle")) { + scene = new BattleScene(); + } + + if (scene != null) { + showScene(scene); + } + } + } +} diff --git a/src/subconscious/graphics/MapEditorScene.java b/src/subconscious/graphics/MapEditorScene.java new file mode 100644 index 0000000..d6e8be4 --- /dev/null +++ b/src/subconscious/graphics/MapEditorScene.java @@ -0,0 +1,242 @@ +package subconscious.graphics; + +import subconscious.Actor; +import subconscious.Tile; +import subconscious.Map; +import subconscious.MapLoader; + +import java.util.ArrayList; + +import java.awt.Canvas; +import java.awt.Graphics2D; +import java.awt.Dimension; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferStrategy; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.NoninvertibleTransformException; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JFileChooser; +import javax.swing.JCheckBox; + +import java.lang.Integer; + +public class MapEditorScene extends MapScene { + private Tile.Type placingTile = Tile.Type.CLEAR; + private Actor placingActor = new Actor("", 0, false, 0); + private ArrayList actorFields = new ArrayList<>(); + private JFrame actorFrame; + private boolean nukeActor = false; + + public MapEditorScene() { + super(); + this.setLayout(new BorderLayout()); + + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new GridLayout(1,5)); + + JButton newButton = new JButton("New"); + newButton.setActionCommand("new"); + JButton tileButton = new JButton("Placing selector"); + tileButton.setActionCommand("tile"); + JButton exportButton = new JButton("Export"); + exportButton.setActionCommand("export"); + JButton importButton = new JButton("Import"); + importButton.setActionCommand("import"); + JButton actorButton = new JButton("Actors"); + actorButton.setActionCommand("actors"); + + newButton.addActionListener(this); + tileButton.addActionListener(this); + actorButton.addActionListener(this); + exportButton.addActionListener(this); + importButton.addActionListener(this); + + bottomPanel.add(newButton); + bottomPanel.add(tileButton); + bottomPanel.add(actorButton); + bottomPanel.add(exportButton); + bottomPanel.add(importButton); + + this.add(bottomPanel, BorderLayout.PAGE_END); + this.add(this.canvas, BorderLayout.CENTER); + } + + @Override + protected void update(long deltaNanoTime) {} + + @Override + protected void absoluteRender(Graphics2D g2d) {} + + @Override + public void mouseClicked(MouseEvent e) { + int tileSize = this.maxSize/10; + Point2D p = new Point2D.Double(e.getX(), e.getY()); + try { + p = this.tx.inverseTransform(p, null); + } catch (NoninvertibleTransformException ex) {} + try { + int x = (int) p.getX()/tileSize; + int y = (int) p.getY()/tileSize; + this.map.getTile(x, y); + if (this.placingTile != Tile.Type.NONE) { + this.map.getTile(x, y).setType(this.placingTile); + } else { + if (!this.nukeActor) { + Actor actor = this.placingActor; + actor.place(x, y); + this.map.addActor(actor); + } else { + Actor toNuke = this.placingActor; + for (Actor actor : this.map.getActors()) { + if (x == actor.getX() && y == actor.getY()) { + toNuke = actor; + } + } + this.map.removeActor(toNuke); + } + } + } catch (ArrayIndexOutOfBoundsException ex) { + System.out.println("no tile clicked"); + } catch (NullPointerException ext) { + System.out.println("map non existent"); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if ("new".equals(e.getActionCommand())) { + JTextField size = new JTextField(); + + JComponent[] inputs = new JComponent[] { + new JLabel("Size"), + size, + }; + + int result = JOptionPane.showConfirmDialog(null, inputs, "New map", JOptionPane.DEFAULT_OPTION); + if (result == JOptionPane.OK_OPTION) { + int sizeN = Integer.parseInt(size.getText()); + this.map = new Map(new Dimension(sizeN, sizeN)); + } + } else if ("tile".equals(e.getActionCommand())) { + String[] values = {"Clear", "Grass", "Water", "Mountain", "Actor", "Remove Actor"}; + + Object result = JOptionPane.showInputDialog(null, "Tile Type", "Tile Type Selector", JOptionPane.DEFAULT_OPTION, null, values, "0"); + if (result != null) { + String selected = result.toString(); + switch (selected) { + case "Clear": + this.placingTile = Tile.Type.CLEAR; + break; + case "Grass": + this.placingTile = Tile.Type.GRASS; + break; + case "Water": + this.placingTile = Tile.Type.WATER; + break; + case "Mountain": + this.placingTile = Tile.Type.MOUNTAIN; + break; + case "Actor": + this.placingTile = Tile.Type.NONE; + this.nukeActor = false; + break; + case "Remove Actor": + this.placingTile = Tile.Type.NONE; + this.nukeActor = true; + break; + + } + } + } else if ("export".equals(e.getActionCommand())) { + JFileChooser fc = new JFileChooser(); + fc.showSaveDialog(null); + + MapLoader mapLoader = new MapLoader(fc.getSelectedFile()); + mapLoader.saveMap(this.map); + } else if ("import".equals(e.getActionCommand())) { + JFileChooser fc = new JFileChooser(); + fc.showOpenDialog(null); + + MapLoader mapLoader = new MapLoader(fc.getSelectedFile()); + this.map = mapLoader.getMap(); + } else if ("actors".equals(e.getActionCommand())) { + JFrame actorFrame = new JFrame("Actors"); + actorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + actorFrame.setSize(new Dimension(300, 400)); + actorFrame.setLocationRelativeTo(null); + + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(5,2)); + + JLabel lName = new JLabel("Name"); + JTextField name = new JTextField(); + JLabel lAgility = new JLabel("Agility"); + JTextField agility = new JTextField(); + JLabel lHp = new JLabel("max HP"); + JTextField hp = new JTextField(); + JCheckBox enemy = new JCheckBox("Enemy"); + JLabel empty = new JLabel(); + JButton ok = new JButton("Confirm"); + ok.setActionCommand("actOk"); + JButton cancel = new JButton("Cancel"); + cancel.setActionCommand("actCancel"); + + ArrayList actorFields = new ArrayList<>(); + actorFields.add(name); + actorFields.add(hp); + actorFields.add(agility); + actorFields.add(enemy); + this.actorFields = actorFields; + + ok.addActionListener(this); + cancel.addActionListener(this); + + panel.add(lName); + panel.add(name); + panel.add(lAgility); + panel.add(agility); + panel.add(lHp); + panel.add(hp); + panel.add(enemy); + panel.add(empty); + panel.add(ok); + panel.add(cancel); + + actorFrame.add(panel); + actorFrame.pack(); + actorFrame.setVisible(true); + + this.actorFrame = actorFrame; + } else if ("actOk".equals(e.getActionCommand())) { + JTextField nameField = (JTextField) this.actorFields.get(0); + String name = nameField.getText(); + JTextField hpField = (JTextField) this.actorFields.get(1); + int hp = Integer.parseInt(hpField.getText()); + JTextField agilityField = (JTextField) this.actorFields.get(2); + int agility = Integer.parseInt(agilityField.getText()); + JCheckBox enemyBox = (JCheckBox) this.actorFields.get(3); + Actor actor = new Actor(name, hp, enemyBox.isSelected(), agility); + this.placingActor = actor; + this.actorFrame.setVisible(false); + this.actorFrame.dispose(); + } else if ("actCancel".equals(e.getActionCommand())) { + this.actorFrame.setVisible(false); + this.actorFrame.dispose(); + } + + } +} diff --git a/src/subconscious/graphics/MapScene.java b/src/subconscious/graphics/MapScene.java new file mode 100644 index 0000000..933526b --- /dev/null +++ b/src/subconscious/graphics/MapScene.java @@ -0,0 +1,241 @@ +package subconscious.graphics; + +import subconscious.util.Palette; +import subconscious.Map; +import subconscious.Tile; +import subconscious.Actor; + +import java.awt.Canvas; +import java.awt.Graphics2D; +import java.awt.BasicStroke; +import java.awt.Dimension; +import java.awt.BorderLayout; +import java.awt.GridLayout; + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import java.awt.image.BufferStrategy; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.NoninvertibleTransformException; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JButton; + +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.IOException; + +public abstract class MapScene extends Scene implements ActionListener { + protected Map map; + + protected int panX = 0; + protected int panY = 0; + + protected boolean panning = false; + protected double zoom = 1; + + protected int mouseX; + protected int mouseY; + + protected boolean zooming = false; + + protected int maxSize; + protected AffineTransform tx = new AffineTransform(); + + public MapScene() { + super(); + //this.map = new Map(new Dimension(10, 10)); + } + + @Override + protected void render() { + if (this.canvasSize.width < this.canvasSize.height) { + this.maxSize = WIDTH; + } else { + this.maxSize = HEIGHT; + } + + if (this.map == null) { + return; + } + + Graphics2D g = (Graphics2D) this.buffer.getDrawGraphics(); + //clear + g.setColor(Palette.BLACK); + g.fillRect(0, 0, this.canvasSize.width, this.canvasSize.height); + + //zoom and pan + if (this.zooming) { + Point2D p1 = new Point2D.Double(this.mouseX, this.mouseY); + Point2D p2 = null; + try { + p2 = tx.inverseTransform(p1, null); + } catch (NoninvertibleTransformException ex) {} + this.tx.setToIdentity(); + this.tx.translate(p1.getX(), p1.getY()); + this.tx.scale(this.zoom, this.zoom); + this.tx.translate(-p2.getX(), -p2.getY()); + this.zooming = false; + } + if (this.panning) { + this.tx.translate(this.panX/this.zoom, this.panY/this.zoom); + this.panning = false; + this.panX = 0; + this.panY = 0; + } + + g.transform(this.tx); + + //draw tiles + int tileSize = this.maxSize / 10; + for (Tile tile : this.map.getGrid()) { + switch (tile.getType()) { + case CLEAR: + continue; + case GRASS: + g.setColor(Palette.GREEN); + break; + case WATER: + g.setColor(Palette.BLUE); + break; + case MOUNTAIN: + g.setColor(Palette.BROWN); + break; + } + + g.fillRect( + tileSize * tile.getX(), tileSize * tile.getY(), + tileSize, tileSize); + + if (tile.isSelected()) { + g.setColor(Palette.ORANGE_T); + //g.fillRect(tileSize * tile.getX() + tileSize/4, tileSize * tile.getY() + tileSize/4, + // tileSize/2, tileSize/2); + g.fillRect( + tileSize * tile.getX(), tileSize * tile.getY(), + tileSize, tileSize); + } + + //TODO: set as class variables the storkes + if (tile.cursorOnIt()) { + BasicStroke oldStroke = (BasicStroke) g.getStroke(); + g.setStroke(new BasicStroke( + 10.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL + )); + g.setColor(Palette.ORANGE); + g.drawRect( + tileSize * tile.getX(), tileSize * tile.getY(), + tileSize, tileSize); + g.setStroke(oldStroke); + } + + + g.setPaint(Palette.BLACK); + g.drawRect( + tileSize * tile.getX(), tileSize * tile.getY(), + tileSize, tileSize); + } + + g.setColor(Palette.ORANGE); + int maxBound = this.map.getSize()*tileSize; + g.drawRect(0, 0, maxBound, maxBound); + + //draw actors + g.setFont(g.getFont().deriveFont(g.getFont().getSize()*2.0F)); + for (Actor actor: this.map.getActors()) { + if (actor.isEnemy()) { + g.setColor(Palette.RED); + } else { + g.setColor(Palette.BLUE); + } + g.fillRect(tileSize * actor.getX() + tileSize/5, tileSize * actor.getY() + tileSize/5, + 3*tileSize/5, 3*tileSize/5); + g.setColor(Palette.BLACK); + g.drawString(actor.getName(), tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20); + g.setColor(Palette.RED); + g.fillRect(tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20+tileSize/30, + (tileSize*4/5), tileSize/10); + g.setColor(Palette.DARKGREEN); + g.fillRect(tileSize*actor.getX() + tileSize/5, tileSize*actor.getY()-tileSize/20+tileSize/30, + (tileSize*4/5)*actor.getHP()/10, tileSize/10); + } + + // Restore absolute coordinates + AffineTransform invertTx = null; + try { + invertTx = this.tx.createInverse(); + } catch (NoninvertibleTransformException ex) {} + + g.transform(invertTx); + this.absoluteRender(g); + + g.dispose(); + this.buffer.show(); + } + + protected abstract void absoluteRender(Graphics2D g); + + @Override + public void keyPressed(KeyEvent e) { + int keyCode = e.getKeyCode(); + switch (keyCode) { + case KeyEvent.VK_UP: + this.panY += 10; + break; + case KeyEvent.VK_DOWN: + this.panY -= 10; + break; + case KeyEvent.VK_LEFT: + this.panX += 10; + break; + case KeyEvent.VK_RIGHT: + this.panX -= 10; + break; + } + } + + @Override + public void mousePressed(MouseEvent e) { + this.mouseX = e.getX(); + this.mouseY = e.getY(); + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + this.panX += x - this.mouseX; + this.panY += y - this.mouseY; + this.mouseX = x; + this.mouseY = y; + this.panning = true; + } + + @Override + public void mouseMoved(MouseEvent e) { + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + this.mouseX = e.getX(); + this.mouseY = e.getY(); + if (this.zoom > 0.3 || e.getWheelRotation() < 0) { + this.zoom -= ((double) e.getWheelRotation())/5; + } + this.zooming = true; + } + + @Override + public void actionPerformed(ActionEvent e) {} +} diff --git a/src/subconscious/graphics/Scene.java b/src/subconscious/graphics/Scene.java new file mode 100644 index 0000000..53b936c --- /dev/null +++ b/src/subconscious/graphics/Scene.java @@ -0,0 +1,166 @@ +package subconscious.graphics; + +import java.awt.Canvas; +import java.awt.Graphics2D; +import java.awt.Dimension; +import java.awt.BorderLayout; + +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelListener; +import java.awt.event.MouseWheelEvent; +import java.awt.image.BufferStrategy; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; + +public abstract class Scene extends JPanel + implements Runnable, KeyListener, MouseListener, MouseMotionListener, + MouseWheelListener, ComponentListener { + + protected final long DESIRED_FPS = 60; + protected final long DESIRED_DELTA_LOOP = (1000*1000*1000)/DESIRED_FPS; + + protected boolean running; + protected boolean paused; + protected Object pauseLock; + + protected BufferStrategy buffer; + protected Dimension canvasSize; + protected Canvas canvas; + + // TODO: make accessible from user settings + protected int guiSize = 2; + + protected Scene() { + + this.canvasSize = GameWindow.WINDOW_SIZE; + this.canvas = new Canvas(); + + this.canvas.setBounds(0, 0, this.canvasSize.width, this.canvasSize.height); + this.canvas.setIgnoreRepaint(true); + + this.canvas.addKeyListener(this); + this.canvas.addMouseListener(this); + this.canvas.addMouseMotionListener(this); + this.canvas.addMouseWheelListener(this); + } + + private void initCanvasBuffer() { + this.canvas.createBufferStrategy(2); + this.buffer = this.canvas.getBufferStrategy(); + + this.canvas.requestFocus(); + } + + public void run() { + long beginLoopTime; + long endLoopTime; + long currentUpdateTime = System.nanoTime(); + long lastUpdateTime; + long deltaLoop; + + this.initCanvasBuffer(); + + this.running = true; + this.paused = false; + pauseLock = new Object(); + + while (running) { + beginLoopTime = System.nanoTime(); + + synchronized (this.pauseLock) { + if (this.paused) { + try { + this.pauseLock.wait(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + break; + } + } + } + + this.render(); + + lastUpdateTime = currentUpdateTime; + currentUpdateTime = System.nanoTime(); + + this.update(currentUpdateTime - lastUpdateTime); + + endLoopTime = System.nanoTime(); + deltaLoop = endLoopTime - beginLoopTime; + + if (deltaLoop > this.DESIRED_DELTA_LOOP) { + // TODO: late => skip frame + } else { + try { + Thread.sleep((this.DESIRED_DELTA_LOOP - deltaLoop)/(1000*1000)); + } catch (InterruptedException e ) { + + } + } + } + } + + public synchronized void stop() { + this.running = false; + + // stop thread even if paused + this.resume(); + } + + public synchronized void pause() { + this.paused = true; + } + + public synchronized void resume() { + if (!paused) + return; + + this.paused = false; + this.pauseLock.notifyAll(); + } + + // automagically set the canvas size to the parent's size + public synchronized void updateCanvasSize() { + this.canvasSize = this.getParent().getSize(); + } + + public synchronized void setCanvasSize(Dimension newSize) { + this.canvasSize = newSize; + } + + protected abstract void render(); + protected abstract void update(long deltaNanoTime); + + @Override + public void keyTyped(KeyEvent e) {} + public void keyPressed(KeyEvent e) {} + public void keyReleased(KeyEvent e) {} + + @Override + public void mouseClicked(MouseEvent e) {} + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mousePressed(MouseEvent e) {} + public void mouseReleased(MouseEvent e) {} + public void mouseDragged(MouseEvent e) {} + public void mouseMoved(MouseEvent e) {} + public void mouseWheelMoved(MouseWheelEvent e) {} + + @Override + public void componentResized(ComponentEvent e) { + this.updateCanvasSize(); + } + + public void componentMoved(ComponentEvent e) {} + public void componentShown(ComponentEvent e) {} + public void componentHidden(ComponentEvent e) {} + +} diff --git a/src/subconscious/util/Palette.java b/src/subconscious/util/Palette.java new file mode 100644 index 0000000..adab9ad --- /dev/null +++ b/src/subconscious/util/Palette.java @@ -0,0 +1,17 @@ +package subconscious.util; + +import java.awt.Color; + +public class Palette { + public final static Color BLACK = new Color(29, 31, 33); + public final static Color WHITE = new Color(197, 200, 198); + public final static Color WHITE_T = new Color(197, 200, 198, 200); + public final static Color RED = new Color(165, 66, 66); + public final static Color YELLOW = new Color(250, 198, 116); + public final static Color GREEN = new Color(181, 189, 104); + public final static Color DARKGREEN = new Color(140, 148, 64); + public final static Color BLUE = new Color(95, 129, 157); + public final static Color ORANGE = new Color(222, 147, 95); + public final static Color ORANGE_T = new Color(222, 147, 95, 100); + public final static Color BROWN = new Color(51, 41, 33); +} -- cgit v1.2.1