diff --git a/.gitignore b/.gitignore index fcf9215..eedce7e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ .classpath .project *.log +/.idea/ +/out/ +/Zoelda.iml diff --git a/Zoelda/lib/Engine.Alpha.jar b/Zoelda/lib/Engine.Alpha.jar index a3d7fc2..efbc5d0 100644 Binary files a/Zoelda/lib/Engine.Alpha.jar and b/Zoelda/lib/Engine.Alpha.jar differ diff --git a/Zoelda/src/main/DoorTile.java b/Zoelda/src/main/DoorTile.java new file mode 100644 index 0000000..4df59f1 --- /dev/null +++ b/Zoelda/src/main/DoorTile.java @@ -0,0 +1,65 @@ +package main; + +import ea.Ticker; +import main.entities.player.Player; +import main.maps.ImageMap; + +public class DoorTile extends Tile implements Ticker { + + public static final int TOP = 0; + public static final int BOTTOM = 1; + public static final int LEFT = 2; + public static final int RIGHT = 3; + + private int side; + private DoorTile connected; + private ImageMap map; + private boolean waitForLeave; + + public DoorTile(float x, float y, ImageMap map) { + super(Tile.DOOR, x, y); + this.map = map; + + Main.instance.tickerAnmelden(this, 50); + } + + @Override + public void tick() { + if (Main.instance.getWorld() != null) { + Player player = Main.instance.getWorld().getPlayer(); + float dist = player.dist(posX + 0.5f, posY + 0.5f); + if (dist < 0.5f) { + if (!waitForLeave) { + Main.instance.getWorld().changeMap(this); + waitForLeave = true; + } + } else { + waitForLeave = false; + } + } + } + + public int getSide() { + return side; + } + + public void setSide(int side) { + this.side = side; + } + + public void setConnectedDoor(DoorTile door) { + connected = door; + } + + public DoorTile getConnectedDoor() { + return connected; + } + + public ImageMap getMap() { + return map; + } + + public void waitForLeave() { + waitForLeave = true; + } +} diff --git a/Zoelda/src/main/HUD.java b/Zoelda/src/main/HUD.java new file mode 100644 index 0000000..c8e5db6 --- /dev/null +++ b/Zoelda/src/main/HUD.java @@ -0,0 +1,72 @@ +package main; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.imageio.ImageIO; +import ea.BoundingRechteck; +import ea.Knoten; +import ea.Ticker; + +public class HUD extends Knoten implements Ticker { + private BufferedImage volles_Herz; + private BufferedImage halbes_Herz; + private BufferedImage leeres_Herz; + private BufferedImage hauptBild; + private BufferedImage[] HPLeiste; + private final static int SCALE = 50; + + public HUD() { + // inizialisieren der Variablen, laden der Bilder und für den ticker anmelden + HPLeiste = new BufferedImage[3]; + Main.instance.manager.anmelden(this, 50); + try { + hauptBild = ImageIO.read(HUD.class.getResourceAsStream("/res/images/icons.png")); + } catch (IOException e) { + e.printStackTrace(); + } + BufferedImage buff; + // volles_Herz: + buff = hauptBild.getSubimage(16, 0, 16, 16); + volles_Herz = buff; + // halbes_Herz: + buff = hauptBild.getSubimage(32, 0, 16, 16); + halbes_Herz = buff; + // leeres_Herz + buff = hauptBild.getSubimage(48, 0, 16, 16); + leeres_Herz = buff; + HPLeiste[0] = volles_Herz; + HPLeiste[1] = volles_Herz; + HPLeiste[2] = volles_Herz; + } + + //wird alle 50ms ausgeführt: + @Override + public void tick() { + // teilt den Wert der HP in Teile auf, welche der Anzahl der Herzen entspricht + // und prüft dann für den eigenen Teil des Herzens, ob das jeweilige Herz voll, + // halb oder leer ist (BIG BRAIN): + float localeHP; + for (int i = 0; i < HPLeiste.length; i++) { + localeHP = Main.instance.getWorld().getPlayer().getHP(); + ; + localeHP -= ((float) i) * (1f / HPLeiste.length); + if (localeHP <= 0f) { + HPLeiste[i] = leeres_Herz; + } else if (localeHP < (1 / (float) (2 * HPLeiste.length))) { + HPLeiste[i] = halbes_Herz; + } else if (localeHP > 1 / (float) (2 * HPLeiste.length)) { + HPLeiste[i] = volles_Herz; + } + } + } + + //Zeichnet alle Herzen im Array HPLeiste[] auf den Bildschirm + @Override + public void zeichnen(Graphics2D g, BoundingRechteck r) { + for (int i = 0; i < HPLeiste.length; i++) { + g.drawImage(HPLeiste[i], i * SCALE, 0, SCALE, SCALE, null); + } + } + +} diff --git a/Zoelda/src/main/Main.java b/Zoelda/src/main/Main.java index 24ef6d8..ce4b004 100644 --- a/Zoelda/src/main/Main.java +++ b/Zoelda/src/main/Main.java @@ -10,18 +10,18 @@ public class Main extends Game { public static Main instance; private World world; - - public static final int WIDTH = 1000; // Fensterbreite - public static final int HEIGHT = 800; // Fensterhöhe + private HUD hud; public Main() { - super(WIDTH, HEIGHT); + super(World.SCALE * 15, World.SCALE * 11, 16); instance = this; // Welt initialisieren und Spieler hinzufügen world = new World(); + hud = new HUD(); // die Welt zu EA hinzufügen wurzel.add(world); + wurzel.add(hud); } @Override diff --git a/Zoelda/src/main/SheetLoader.java b/Zoelda/src/main/SheetLoader.java index 26feaca..17acd13 100644 --- a/Zoelda/src/main/SheetLoader.java +++ b/Zoelda/src/main/SheetLoader.java @@ -11,7 +11,7 @@ import ea.internal.gra.PixelFeld; public class SheetLoader { - private static Figur[] figures; + private Figur[] figures; /** * Macht aus einem Spritesheet Figuren. diff --git a/Zoelda/src/main/Tile.java b/Zoelda/src/main/Tile.java index 2cb98ec..036763c 100644 --- a/Zoelda/src/main/Tile.java +++ b/Zoelda/src/main/Tile.java @@ -19,36 +19,48 @@ public class Tile extends Knoten { public static final int WALL_BOTTOM = 2; public static final int STONE_WALL = 3; public static final int STONE_WALL_BOTTOM = 4; + public static final int STONE_FLOOR = 5; + public static final int VOID = 6; + public static final int DOOR = 7; private Bild img; // Bild, das gerendert wird private int id; // Die id dises Tiles + protected float posX, posY; // Position dieses Tiles /** * @param id - * @param x - X-Koordinate in units - * @param y - Y-Koordinate in units + * @param x - X-Koordinate in units + * @param y - Y-Koordinate in units */ public Tile(int id, float x, float y) { this.id = id; + posX = x; + posY = y; - // Das Bild laden - try { - BufferedImage buff = ImageIO.read(Tile.class.getResourceAsStream(getPathFromId(id))); - // Gras hat 8 verschiedene Texturen von denen eine zufällig ausgewählt werden - // muss. - if (id == GRASS) { - buff = buff.getSubimage(16 * (int) (Math.random() * 8), 0, 16, 16); - } - // Skalieren - BufferedImage scaled = new BufferedImage(World.SCALE, World.SCALE, BufferedImage.TYPE_INT_RGB); - scaled.getGraphics().drawImage(buff, 0, 0, World.SCALE, World.SCALE, null); - img = new Bild(x * World.SCALE, y * World.SCALE, scaled); + if (id != VOID) { + // Das Bild laden + try { + BufferedImage buff = ImageIO.read(Tile.class.getResourceAsStream(getPathFromId(id))); + // Gras hat 8 verschiedene Texturen von denen eine zufällig ausgewählt werden + // muss. + if (id == GRASS) { + buff = buff.getSubimage(16 * (int) (Math.random() * 8), 0, 16, 16); + } + // if (id == STONE_FLOOR) { + // buff = buff.getSubimage(16 * (int) (Math.random() * 10), 0, 16, 16); + // } + // Skalieren + BufferedImage scaled = new BufferedImage(World.SCALE, World.SCALE, BufferedImage.TYPE_INT_RGB); + scaled.getGraphics().drawImage(buff, 0, 0, World.SCALE, World.SCALE, null); + img = new Bild(x * World.SCALE, y * World.SCALE, scaled); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + // Bild zu EA hinzufügen. + add(img); } - // Bild zu EA hinzufügen. - add(img); + } /** @@ -63,9 +75,13 @@ public class Tile extends Knoten { case WALL_BOTTOM: return "/res/images/tiles/wall_bottom.png"; case STONE_WALL: - return "/res/images/tiles/stone_wall.png"; + return "/res/images/tiles/test.png"; case STONE_WALL_BOTTOM: return "/res/images/tiles/stone_wall_bottom.png"; + case STONE_FLOOR: + return "/res/images/tiles/TestTest.png"; + case DOOR: + return "/res/images/tiles/door.png"; } return null; } @@ -83,7 +99,7 @@ public class Tile extends Knoten { public boolean isCollidable() { // Alle Tiles durch die man nicht laufen soll müssen hier true zurückgeben, // sonst werden sie bei der Collisiondetection nicht berücksichtigt. - return id == WALL_TOP || id == STONE_WALL ; + return id == WALL_TOP || id == STONE_WALL; } /** @@ -113,4 +129,8 @@ public class Tile extends Knoten { public int getRight() { return positionX() + getSize(); } + + public int getID() { + return id; + } } diff --git a/Zoelda/src/main/World.java b/Zoelda/src/main/World.java index ce2ffe7..bbf2589 100644 --- a/Zoelda/src/main/World.java +++ b/Zoelda/src/main/World.java @@ -1,51 +1,61 @@ package main; +import java.util.ArrayList; + import ea.Knoten; -import main.entities.Entity; -import main.entities.Player; -import main.entities.Snake; -import main.entities.Spider; +import main.entities.player.Player; +import main.maps.ImageMap; import main.maps.Map; -import main.maps.TestMap; /** * Hier werden alle Maps gespeichert. */ public class World extends Knoten { - public static final int SCALE_FACTOR = 4; // Der Basis Zoomfaktor + public static final int SCALE_FACTOR = 6; // Der Basis Zoomfaktor public static final int SCALE = SCALE_FACTOR * Tile.getSize(); // Eine Gameunit ist so viele pixel lang private Map currentMap; // Die Map die aktuell angezeigt werden soll. + private ArrayList dungeon; + + private Player player; public World() { - // Map initialisieren - currentMap = new TestMap(); - // Map zu EA hinzufügen - add(currentMap); - - // und Entities auch - Player player = new Player(); - add(player.actionFigur); - currentMap.getEntities().add(player); - - Spider spider = new Spider(); - // und Spinnen auch - add(spider.actionFigur); - currentMap.getEntities().add(spider); + dungeon = new ArrayList<>(50); + + ImageMap start = new ImageMap("/res/images/maps/map2.png"); + dungeon.add(start); + currentMap = start; + + start.generate(dungeon, DoorTile.BOTTOM); + + + player = new Player(); + currentMap.getEntities().add(player); + currentMap.add(player.actionFigur); + Main.instance.manager.anmelden(player, 20); + + add(currentMap); - Snake snake = new Snake(); - add(snake.actionFigur); - currentMap.getEntities().add(snake); - - // Alle Entities als ticker registrieren (triggert dann die update methoden) - for (Entity e : currentMap.getEntities()) { - Main.instance.manager.anmelden(e, 20); - } } - + public Map getCurrentMap() { return currentMap; } + + public Player getPlayer() { + return player; + } + + public void changeMap(DoorTile door) { + currentMap.entfernen(player.actionFigur); + entfernen(currentMap); + System.out.println(door); + currentMap = door.getConnectedDoor().getMap(); + currentMap.add(player.actionFigur); + add(currentMap); + door.getConnectedDoor().waitForLeave(); + player.setPos(door.getConnectedDoor().posX + 0.5f, door.getConnectedDoor().posY + 0.5f); + } } diff --git a/Zoelda/src/main/entities/Entity.java b/Zoelda/src/main/entities/Entity.java index 3a8dd90..1d25735 100644 --- a/Zoelda/src/main/entities/Entity.java +++ b/Zoelda/src/main/entities/Entity.java @@ -1,6 +1,9 @@ package main.entities; import ea.Ticker; +import ea.Vektor; +import main.Main; +import main.Tile; import main.maps.Map; /* @@ -14,6 +17,7 @@ public abstract class Entity implements Ticker { protected float accelleration = 0.012f; // Beschleunigung des entities in gameunits pro frame. protected float friction = 0.2f; // Entschleunigung des entities in gameunits pro frame. protected float width = 1f, height = 1f; // Breite und Höhe der Hitbox. + private boolean deleteEntity; // Wenn true wird dieses Entity von der map gelöscht // Das ist die Ticker-Methode von ea; wird jeden frame ausgeführt (frameloop) @Override @@ -107,5 +111,95 @@ public abstract class Entity implements Ticker { public float dist(Entity e) { return (float) Math.sqrt((e.posX - posX) * (e.posX - posX) + (e.posY - posY) * (e.posY - posY)); } + + /** + * @return die entifernung zu dieser Koordinate + */ + public float dist(float x, float y) { + return (float) Math.sqrt((x - posX) * (x - posX) + (y - posY) * (y - posY)); + } + + /** + * Generiert einen vektor von diesm Entity zu einem anderen + */ + public Vektor vectorToEntity(Entity e) { + Vektor v = new Vektor(e.posX - posX, e.posY - posY);; + if (v.x == 0 && v.y == 0) { + return new Vektor(0.0000001f, 0.0000001f); + } + return v; + } + + protected boolean lineOfSightClear(Entity e) { + Vektor direct = vectorToEntity(e).normiert(); + direct = direct.teilen(4f); + Vektor loc = new Vektor(posX, posY); + float lastDist; + float dist = Float.MAX_VALUE; + boolean clear = true; + do { + loc = loc.summe(direct); + lastDist = dist; + dist = Math.abs(e.posX - loc.x) + Math.abs(e.posY - loc.y); + Tile t = Main.instance.getWorld().getCurrentMap().getTile((int) loc.x, (int) loc.y); + if (t != null && t.isCollidable()) { + clear = false; + break; + } + } while (dist < lastDist); + return clear; + } + /** + * Gibt den velX Wert zurück. + * @return gibt den velX Wert als float zurück. + */ + public float getVelX() { + return velX; + } + + /** + * Gibt den velY Wert zurück. + * @return gibt den velY Wert als float zurück. + */ + public float getVelY() { + return velY; + } + + /** + * Setzt eine neue velX velocity. + * @param velX neuer float velX Wert. + */ + public void setVelX(float velX) { + this.velX = velX; + } + + /** + * Setzt eine neue Y velocity. + * @param velY neuer float velY Wert. + */ + public void setVelY(float velY) { + this.velY = velY; + } + + public void setPosX(float x) { + posX = x; + } + + public void setPosY(float y) { + posY = y; + } + + public void setPos(float x, float y) { + posX = x; + posY = y; + } + + public void deleteEntity() { + deleteEntity = true; + } + + public boolean isReadyToDelete() { + return deleteEntity; + } } diff --git a/Zoelda/src/main/entities/LivingEntity.java b/Zoelda/src/main/entities/LivingEntity.java index a280da0..b3e977a 100644 --- a/Zoelda/src/main/entities/LivingEntity.java +++ b/Zoelda/src/main/entities/LivingEntity.java @@ -7,7 +7,7 @@ import main.World; /* * Alles was zustände hat und sich Bewegen kann, ist ein LivingEntity. */ -public class LivingEntity extends Entity { +public abstract class LivingEntity extends Entity { protected boolean side; // true = gespiegelt, false = nicht public ActionFigur actionFigur; // Sprite des Entities @@ -15,6 +15,7 @@ public class LivingEntity extends Entity { protected float spriteOffsetX, spriteOffsetY; // Offset des Sprites. Hier kann man die relative render-Position nachjustieren. protected float hp = 1f; //hp des Entitys protected boolean mirrored; + /** * @param figur - erstes (standart) Sprite * @param name - name des Zustands @@ -41,6 +42,15 @@ public class LivingEntity extends Entity { } else if (velX > 0) { side = false; } + + if (hp <= 0) { + actionFigur.zustandSetzen(getDeathAnimationName()); + velX = 0; + velY = 0; + if (actionFigur.aktuelleFigur().aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { + deleteEntity(); + } + } // Packt das Sprite an die richtige Stelle actionFigur.faktorSetzen((int) (spriteScale * World.SCALE_FACTOR)); @@ -54,10 +64,23 @@ public class LivingEntity extends Entity { */ protected void zustandSetzen(String name) { actionFigur.spiegelXSetzen(mirrored ? !side : side); - actionFigur.zustandSetzen(name); + if (!actionFigur.aktuellesVerhalten().equals(name)) { + actionFigur.zustandSetzen(name); + actionFigur.aktuelleFigur().animationsBildSetzen(0); + } } - protected float getHealthPoints() { + + public float getHP() { return hp; } + + public void takeDamage(float damage, Entity e) { + zustandSetzen(getDamageAnimationName()); + actionFigur.aktuelleFigur().animationsBildSetzen(0); + hp -= damage; + } + + public abstract String getDeathAnimationName(); + public abstract String getDamageAnimationName(); } diff --git a/Zoelda/src/main/entities/Snake.java b/Zoelda/src/main/entities/Snake.java index 5ff1cbf..9a0ca7e 100644 --- a/Zoelda/src/main/entities/Snake.java +++ b/Zoelda/src/main/entities/Snake.java @@ -1,16 +1,14 @@ package main.entities; -import java.util.ArrayList; - import ea.Vektor; import main.Main; import main.SheetLoader; -import main.Tile; +import main.entities.player.Player; public class Snake extends LivingEntity { private static SheetLoader loader = new SheetLoader("/res/images/snake_spritesheet_calciumtrice.png", 32, 32, - new int[] { 10, 10, 10, 10, 10 }); + new int[] { 10, 10, 10, 10, 13, 8 }); public Snake() { super(loader.getFigur(0), "idle"); @@ -26,64 +24,50 @@ public class Snake extends LivingEntity { actionFigur.neuerZustand(loader.getFigur(1), "lost_sight"); actionFigur.neuerZustand(loader.getFigur(2), "walk"); actionFigur.neuerZustand(loader.getFigur(3), "attack"); - actionFigur.neuerZustand(loader.getFigur(4), "die"); + actionFigur.neuerZustand(loader.getFigur(4), getDeathAnimationName()); + actionFigur.neuerZustand(loader.getFigur(5), getDamageAnimationName()); + + loader.getFigur(3).animationsGeschwindigkeitSetzen(80); + loader.getFigur(5).animationsGeschwindigkeitSetzen(60); } @Override protected void update() { - ArrayList entities = Main.instance.getWorld().getCurrentMap().getEntities(); - Entity nearestPlayer = null; - for (Entity e : entities) { - if (e instanceof Player) { - if (nearestPlayer == null || e.dist(this) < nearestPlayer.dist(this)) { - nearestPlayer = e; + Player player = Main.instance.getWorld().getPlayer(); + if (!actionFigur.aktuellesVerhalten().equals(getDamageAnimationName())) { + if (lineOfSightClear(player)) { + if (dist(player) < 1f) { + zustandSetzen("attack"); + } else { + Vektor toPlayer = vectorToEntity(player).normiert(); + velX += toPlayer.x * accelleration; + velY += toPlayer.y * accelleration; + zustandSetzen("walk"); + } + } else { + if (!actionFigur.aktuellesVerhalten().equals("idle")) { + zustandSetzen("lost_sight"); + if (actionFigur.aktuelleFigur().aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { + zustandSetzen("idle"); + } } } - } - if (nearestPlayer != null && lineOfSightClear(nearestPlayer)) { - if (dist(nearestPlayer) < 1f) { - zustandSetzen("attack"); - } else { - Vektor toPlayer = new Vektor(nearestPlayer.posX - posX, nearestPlayer.posY - posY); - toPlayer = toPlayer.normiert(); - velX += toPlayer.x * accelleration; - velY += toPlayer.y * accelleration; + } else { + if (actionFigur.aktuelleFigur().aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { zustandSetzen("walk"); } - - } else - - { - if (actionFigur.aktuellesVerhalten().equals("walk")) { - zustandSetzen("lost_sight"); - } - if (actionFigur.aktuellesVerhalten().equals("lost_sight") && actionFigur.aktuelleFigur() - .aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { - actionFigur.aktuelleFigur().animationsBildSetzen(0); - zustandSetzen("idle"); - } } this.checkTileCollisions(Main.instance.getWorld().getCurrentMap()); super.update(); } - private boolean lineOfSightClear(Entity e) { - Vektor direct = new Vektor(e.posX - posX, e.posY - posY).normiert(); - direct = direct.teilen(4f); - Vektor loc = new Vektor(posX, posY); - float lastDist; - float dist = Float.MAX_VALUE; - boolean clear = true; - do { - loc = loc.summe(direct); - lastDist = dist; - dist = Math.abs(e.posX - loc.x) + Math.abs(e.posY - loc.y); - Tile t = Main.instance.getWorld().getCurrentMap().getTile((int) loc.x, (int) loc.y); - if (t != null && t.isCollidable()) { - clear = false; - break; - } - } while (dist < lastDist); - return clear; + @Override + public String getDeathAnimationName() { + return "die"; + } + + @Override + public String getDamageAnimationName() { + return "damage"; } } diff --git a/Zoelda/src/main/entities/Spider.java b/Zoelda/src/main/entities/Spider.java index 8c24f25..4cd2782 100644 --- a/Zoelda/src/main/entities/Spider.java +++ b/Zoelda/src/main/entities/Spider.java @@ -1,15 +1,16 @@ package main.entities; +import ea.Vektor; import main.Main; import main.SheetLoader; +import main.entities.player.Player; public class Spider extends LivingEntity { - private static SheetLoader loader = new SheetLoader("/res/images/spider_sprite_sheet.png", 32, 32, - new int[] { 5, 6, 9, 1, 4, 3, 9, 6, 5, 6, 9, 1, 4, 3, 9, 6 }); + private static SheetLoader loader = new SheetLoader("/res/images/spider_sprite_sheet.png", 32, 32, new int[] { 5, 3, 6, 9, 9, 8 }); public Spider() { - super(loader.getFigur(0), "walk"); + super(loader.getFigur(0), "idle"); width = 0.7f; height = 0.8f; @@ -17,17 +18,55 @@ public class Spider extends LivingEntity { spriteScale = 0.8f; posX = 4f; posY = 4f; + mirrored = true; + + actionFigur.neuerZustand(loader.getFigur(1), "lost_sight"); + actionFigur.neuerZustand(loader.getFigur(2), "walk"); + actionFigur.neuerZustand(loader.getFigur(3), "attack"); + actionFigur.neuerZustand(loader.getFigur(4), getDeathAnimationName()); + actionFigur.neuerZustand(loader.getFigur(5), getDamageAnimationName()); + + loader.getFigur(3).animationsGeschwindigkeitSetzen(80); + loader.getFigur(5).animationsGeschwindigkeitSetzen(40); } protected void update() { - - // auf Kollisionen prüfen - checkTileCollisions(Main.instance.getWorld().getCurrentMap()); - // LivingEntity auch updaten lassen + Player player = Main.instance.getWorld().getPlayer(); + if (!actionFigur.aktuellesVerhalten().equals(getDamageAnimationName())) { + if (lineOfSightClear(player)) { + if (dist(player) < 1f) { + zustandSetzen("attack"); + } else { + Vektor toPlayer = vectorToEntity(player).normiert(); + velX += toPlayer.x * accelleration; + velY += toPlayer.y * accelleration; + zustandSetzen("walk"); + } + } else { + if (!actionFigur.aktuellesVerhalten().equals("idle")) { + zustandSetzen("lost_sight"); + if (actionFigur.aktuelleFigur().aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { + zustandSetzen("idle"); + } + } + } + } else { + if (actionFigur.aktuelleFigur().aktuellesBild() == actionFigur.aktuelleFigur().animation().length - 1) { + zustandSetzen("walk"); + } + } + this.checkTileCollisions(Main.instance.getWorld().getCurrentMap()); super.update(); - velX = 0; - velY = 0; + } + @Override + public String getDeathAnimationName() { + return "die"; + } + + @Override + public String getDamageAnimationName() { + return "damage"; } } diff --git a/Zoelda/src/main/entities/Player.java b/Zoelda/src/main/entities/player/Player.java similarity index 56% rename from Zoelda/src/main/entities/Player.java rename to Zoelda/src/main/entities/player/Player.java index fe18eb1..5097ccd 100644 --- a/Zoelda/src/main/entities/Player.java +++ b/Zoelda/src/main/entities/player/Player.java @@ -1,12 +1,20 @@ -package main.entities; +package main.entities.player; + +import java.util.ArrayList; import ea.Taste; +import ea.Vektor; import main.Main; import main.SheetLoader; +import main.entities.Entity; +import main.entities.LivingEntity; public class Player extends LivingEntity { - private static SheetLoader loader = new SheetLoader("/res/images/player_sprite_sheet.png", 64, 32, new int[] {5, 8, 7, 6, 2, 5, 4, 7}); + private static SheetLoader loader = new SheetLoader("/res/images/player_sprite_sheet.png", 64, 32, + new int[] { 5, 8, 7, 6, 2, 5, 4, 7 }); + private boolean onlyAttackOnceTrigger; + private float range = 1.2f; // die reichweite der Attacke public Player() { super(loader.getFigur(0), "idle"); @@ -16,9 +24,9 @@ public class Player extends LivingEntity { height = 0.8f; spriteOffsetY = -0.14f; spriteScale = 0.8f; - posX = 4f; - posY = 4f; - + posX = 7.5f; + posY = 5.5f; + // unterschiedliche Animationsgeschwindigkeiten // für idle loader.getFigur(0).animationsGeschwindigkeitSetzen(200); @@ -30,7 +38,8 @@ public class Player extends LivingEntity { actionFigur.neuerZustand(loader.getFigur(1), "walk"); actionFigur.neuerZustand(loader.getFigur(2), "strike"); actionFigur.neuerZustand(loader.getFigur(3), "swipe"); - actionFigur.neuerZustand(loader.getFigur(7), "die"); + actionFigur.neuerZustand(loader.getFigur(6), getDamageAnimationName()); + actionFigur.neuerZustand(loader.getFigur(7), getDeathAnimationName()); } @Override @@ -39,9 +48,9 @@ public class Player extends LivingEntity { if (!((actionFigur.aktuellesVerhalten().equals("strike")) && actionFigur.aktuelleFigur().aktuellesBild() < actionFigur.aktuelleFigur().animation().length - 1)) { // Bei diser soll man sich nicht bewegen können aber weiter rutschen - if (!((actionFigur.aktuellesVerhalten().equals("swipe")) - && actionFigur.aktuelleFigur().aktuellesBild() < actionFigur.aktuelleFigur().animation().length - 1)) { - + if (!((actionFigur.aktuellesVerhalten().equals("swipe")) && actionFigur.aktuelleFigur() + .aktuellesBild() < actionFigur.aktuelleFigur().animation().length - 1)) { + // wasd movement if (Main.instance.tasteGedrueckt(Taste.A)) { velX -= accelleration; @@ -55,7 +64,7 @@ public class Player extends LivingEntity { if (Main.instance.tasteGedrueckt(Taste.S)) { velY += accelleration; } - + // Auf idle stellen wenn man sich nicht bewegt if (velX == 0 && velY == 0) { zustandSetzen("idle"); @@ -73,8 +82,9 @@ public class Player extends LivingEntity { if (Main.instance.tasteGedrueckt(Taste.F)) { zustandSetzen("die"); } + onlyAttackOnceTrigger = false; } - + // auf Kollisionen prüfen checkTileCollisions(Main.instance.getWorld().getCurrentMap()); // LivingEntity auch updaten lassen @@ -83,5 +93,38 @@ public class Player extends LivingEntity { velX = 0; velY = 0; } + + // auf Kollisionen prüfen + checkTileCollisions(Main.instance.getWorld().getCurrentMap()); + + if (!onlyAttackOnceTrigger && actionFigur.aktuellesVerhalten().equals("swipe") + && actionFigur.aktuelleFigur().aktuellesBild() == 1) { + onlyAttackOnceTrigger = true; + ArrayList entities = Main.instance.getWorld().getCurrentMap().getEntities(); + for (Entity e : entities) { + if (e instanceof LivingEntity && e != this && e.dist(this) <= range) { + LivingEntity le = (LivingEntity) e; + if (le.getHP() > 0) { + Vektor toE = vectorToEntity(le); + toE = toE.normiert(); + if ((toE.x > 0 && !side) || (toE.x <= 0 && side)) { + le.setVelX(le.getVelX() + toE.x * 0.1f); + le.setVelY(le.getVelY() + toE.y * 0.1f); + le.takeDamage(0.1f, this); + } + } + } + } + } + } + + @Override + public String getDeathAnimationName() { + return "die"; + } + + @Override + public String getDamageAnimationName() { + return "damage"; } } diff --git a/Zoelda/src/main/entities/player/PlayerInventory.java b/Zoelda/src/main/entities/player/PlayerInventory.java new file mode 100644 index 0000000..1764a17 --- /dev/null +++ b/Zoelda/src/main/entities/player/PlayerInventory.java @@ -0,0 +1,114 @@ +package main.entities.player; + +import main.items.Item; + +/** + * Container Klasse für das Inventar des Spielers, + * eventuell später verallgemeinerbar für Truhen o.ä. je nach design dieser. + */ +public class PlayerInventory { + private int coins; + private Item[] items; + private int currentItem; + + /** + * Erstellt ein Player Inventar, welches einen Coin counter und ein Item Inventar enthält. + * @param inventorySize Gibt die größe des Item inventars als int an. + */ + public PlayerInventory(int inventorySize){ + items = new Item [inventorySize]; + currentItem = 0; + } + + /** + * Getter für den Coin counter + * @return Gibt die Anzahl der Coins im Inventar als int zurück. + */ + public int getCoins(){ + return coins; + } + + /** + * Setzt die Anzahl von Coins im Inventar zu angegebener Anzahl. + * @param coins Anzahl an coins als int, die im Inventar sein sollen. + */ + public void setCoins(int coins) { + this.coins = coins; + } + + /** + * Fügt die angegebene Anzahl an Coins in das Inventar hinzu. + * @param amount Die Anzahl an Coins als int, die hinzugefügt werden soll. + */ + public void addCoins(int amount){ + this.coins+= amount; + } + + /** + * Entfernt die angegebene Anzahl an Coins vom Inventar. + * @param amount Die Anzahl an Coins als int, die entfernt werden soll. + */ + public void subtractCoins(int amount){ + this.coins-= amount; + } + + /** + * Getter für das Items im Inventar. + * @return gibt ein Array mit allen Item Objekten zurück, die im Inventar enthalten sind. + */ + public Item[] getItems(){ + return items; + } + + /** + * Ersetzt das jetzige Inventar um ein neues mit im Item-Array items angegebenen Items. + * @param items Array mit Items die das Inventar ersetzen sollen. + */ + public void setItems(Item[] items) { + this.items = items; + } + + /** + * Entfernt ein Item auf angegebner Position im Item-Array. + * @param itemPosition Position des Items das entfernt werden soll, angegeben als int. + */ + public void removeItem(int itemPosition) { + items[itemPosition]=null; + } + + /** + * Setzt das gerade ausgewählte Item fest. + * @param currentItem int gibt an welcher Index des Item Arrays ausgewählt werden soll. + */ + public void setCurrentItem(int currentItem) { + this.currentItem = currentItem; + } + + /** + * Wechselt auf den nächsten Slot im Inventar. + */ + public void changeCurrentItem(){ + if(currentItem>=items.length) currentItem=0; + else currentItem++; + } + + /** + * Methode zum Hinzufügen von Items. + * @param newItem Das Item, dass hinzugefügt werden soll. + * @return gibt zurück ob das Item hinzugefügt wurde, d.h. true wenn hinzugefügt und false wenn nicht hinzugefügt. + */ + public boolean addItem(Item newItem){ + for(int i =0;i< items.length;i++) { + if (items[i] == null) { + items[i] = newItem; + return true; + } + } + return false; + } + + + + + +} diff --git a/Zoelda/src/main/items/Item.java b/Zoelda/src/main/items/Item.java new file mode 100644 index 0000000..5aebdd0 --- /dev/null +++ b/Zoelda/src/main/items/Item.java @@ -0,0 +1,16 @@ +package main.items; +//TODO:Hier soll die Item Oberklasse entstehen +public class Item { + private String icon; + + public Item(String iconPath){ + icon=iconPath; + } + /** + * Gibt den Pfad zu dem Icon dieses Items an. + * @return String, der den Pfad des Icons dieses Items beschreibt + */ + public String getIconPath(){ + return icon; + } +} diff --git a/Zoelda/src/main/maps/Corridor.java b/Zoelda/src/main/maps/Corridor.java index 565f749..957d88b 100644 --- a/Zoelda/src/main/maps/Corridor.java +++ b/Zoelda/src/main/maps/Corridor.java @@ -5,22 +5,34 @@ import main.Tile; public class Corridor extends Map { public Corridor() { - super(5, 10); - + super(15, 11); + for (int x = 0; x < map.length; x++) { for (int y = 0; y < map[0].length; y++) { - if((y == 0 || x == 0 || y == 9 || x == 4) && x != 2 ) { - map[x][y] = new Tile(3, x, y); - add(map[x][y]); - } else if(y == 1 && (x != 0 || x != 4)&& x != 2 ) { - map[x][y] = new Tile(4, x, y); + // Wand + if ((y == 0 || x == 5 || y == 10 || x == 9) && x != 7 && x >= 5 && x <= 9) { + map[x][y] = new Tile(Tile.STONE_WALL, x, y); add(map[x][y]); } - else { - map[x][y] = new Tile(0, x, y); + // 3D-Wand + else if (y == 1 && (x != 0 || x != 4) && x != 7 && x >= 6 && x <= 8) { + map[x][y] = new Tile(Tile.STONE_WALL_BOTTOM, x, y); + add(map[x][y]); + } + // Steinboden + else if (x >= 6 && x <= 8) { + if (x == 7 && (y == 0 || y == map[0].length - 1)) { + } else { + map[x][y] = new Tile(Tile.STONE_FLOOR, x, y); + add(map[x][y]); + } + } else { + map[x][y] = new Tile(Tile.VOID, x, y); add(map[x][y]); } } } + + registerEntities(); } } diff --git a/Zoelda/src/main/maps/ImageMap.java b/Zoelda/src/main/maps/ImageMap.java new file mode 100644 index 0000000..ba2980a --- /dev/null +++ b/Zoelda/src/main/maps/ImageMap.java @@ -0,0 +1,165 @@ +package main.maps; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.ArrayList; + +import javax.imageio.ImageIO; + +import main.DoorTile; +import main.Tile; + +public class ImageMap extends Map { + + private static PixelTile[] pixels = { + new PixelTile(Tile.STONE_WALL, new Color(100, 100, 100)), + new PixelTile(Tile.STONE_FLOOR, new Color(127, 127, 127)), + new PixelTile(Tile.VOID, new Color(0, 0, 0)), + new PixelTile(Tile.DOOR, new Color(255, 0, 0)) }; + + public DoorTile topDoor; + public DoorTile leftDoor; + public DoorTile rightDoor; + public DoorTile bottomDoor; + + public ImageMap(String path) { + super(15, 11); + + try { + BufferedImage img = ImageIO.read(ImageMap.class.getResourceAsStream(path)); + if (img.getWidth() != 15 || img.getHeight() != 11) { + System.err.println("Odd map size! Use 15x11"); + } + for (int x = 0; x < img.getWidth(); x++) { + for (int y = 0; y < img.getHeight(); y++) { + int id = Tile.VOID; + int rgb = img.getRGB(x, y); + for (PixelTile t : pixels) { + if (t.c == rgb) { + id = t.id; + break; + } + } + if (id == Tile.DOOR) { + DoorTile door = new DoorTile(x, y, this); + map[x][y] = door; + if (x == 7) { + if (y < 5) { + topDoor = door; + door.setSide(DoorTile.TOP); + } else { + bottomDoor = door; + door.setSide(DoorTile.BOTTOM); + } + } + if (y == 5) { + if (x < 7) { + leftDoor = door; + door.setSide(DoorTile.LEFT); + } else { + rightDoor = door; + door.setSide(DoorTile.RIGHT); + } + } + } else { + map[x][y] = new Tile(id, x, y); + } + add(map[x][y]); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static class PixelTile { + public final int c; + public final int id; + + public PixelTile(int id, Color c) { + this.c = c.getRGB(); + this.id = id; + } + } + + public void generate(ArrayList dungeon, int fromSide) { + if (topDoor != null && fromSide != DoorTile.TOP) { + ImageMap map; + do { + map = nextMap(); + } while (!connectDoors(topDoor, map)); + dungeon.add(map); + System.out.println("TOP"); + map.generate(dungeon, DoorTile.BOTTOM); + } + if (bottomDoor != null && fromSide != DoorTile.BOTTOM) { + ImageMap map; + do { + map = nextMap(); + } while (!connectDoors(bottomDoor, map)); + dungeon.add(map); + System.out.println("BOTTOM"); + map.generate(dungeon, DoorTile.TOP); + } + if (leftDoor != null && fromSide != DoorTile.LEFT) { + ImageMap map; + do { + map = nextMap(); + } while (!connectDoors(leftDoor, map)); + dungeon.add(map); + System.out.println("LEFT"); + map.generate(dungeon, DoorTile.RIGHT); + } + if (rightDoor != null && fromSide != DoorTile.RIGHT) { + ImageMap map; + do { + map = nextMap(); + } while (!connectDoors(rightDoor, map)); + dungeon.add(map); + System.out.println("RIGHT"); + map.generate(dungeon, DoorTile.LEFT); + } + System.out.println(); + } + + private ImageMap nextMap() { + return new ImageMap("/res/images/maps/map" + ((int) (Math.random() * 4) + 5) + ".png"); + } + + private boolean connectDoors(DoorTile door, ImageMap otherMap) { + switch (door.getSide()) { + case DoorTile.TOP: + if (otherMap.bottomDoor == null) { + return false; + } + door.setConnectedDoor(otherMap.bottomDoor); + otherMap.bottomDoor.setConnectedDoor(door); + System.out.println(door.getConnectedDoor()); + System.out.println(otherMap.bottomDoor.getConnectedDoor()); + return true; + case DoorTile.BOTTOM: + if (otherMap.topDoor == null) { + return false; + } + door.setConnectedDoor(otherMap.topDoor); + otherMap.topDoor.setConnectedDoor(door); + return true; + case DoorTile.LEFT: + if (otherMap.rightDoor == null) { + return false; + } + door.setConnectedDoor(otherMap.rightDoor); + otherMap.rightDoor.setConnectedDoor(door); + return true; + case DoorTile.RIGHT: + if (otherMap.leftDoor == null) { + return false; + } + door.setConnectedDoor(otherMap.leftDoor); + otherMap.leftDoor.setConnectedDoor(door); + return true; + } + return true; + } +} diff --git a/Zoelda/src/main/maps/Map.java b/Zoelda/src/main/maps/Map.java index 4605914..cd6ed88 100644 --- a/Zoelda/src/main/maps/Map.java +++ b/Zoelda/src/main/maps/Map.java @@ -3,25 +3,32 @@ package main.maps; import java.util.ArrayList; import ea.Knoten; +import ea.Ticker; +import main.Main; import main.Tile; import main.entities.Entity; +import main.entities.LivingEntity; /** * Auf der Map sind alle Entities, sowie die Tiles gespiechert. */ -public abstract class Map extends Knoten { +public abstract class Map extends Knoten implements Ticker { protected Tile[][] map; // Die Tiles der map in einem 2D Array. private ArrayList entities; + public Map(int width, int height) { map = new Tile[width][height]; entities = new ArrayList<>(100); + + Main.instance.manager.anmelden(this, 20); } - + /** - * Gibt das Tile-Objekt an der gegebenen Koordinate zurück. (nur wenn es existiert) + * Gibt das Tile-Objekt an der gegebenen Koordinate zurück. (nur wenn es + * existiert) */ public Tile getTile(int x, int y) { if (x >= 0 && x < map.length && y >= 0 && y < map[0].length) { @@ -29,11 +36,25 @@ public abstract class Map extends Knoten { } return null; } - + + @Override + public void tick() { + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + if (e.isReadyToDelete()) { + if (e instanceof LivingEntity) { + entfernen(((LivingEntity) e).actionFigur); + } + Main.instance.manager.abmelden(e); + entities.remove(e); + } + } + } + public int getWidth() { return map.length; } - + public int getHeight() { return map[0].length; } @@ -41,4 +62,10 @@ public abstract class Map extends Knoten { public ArrayList getEntities() { return entities; } + + public void registerEntities() { + for (Entity e : getEntities()) { + Main.instance.manager.anmelden(e, 20); + } + } } diff --git a/Zoelda/src/main/maps/Map01.java b/Zoelda/src/main/maps/Map01.java new file mode 100644 index 0000000..811e5f8 --- /dev/null +++ b/Zoelda/src/main/maps/Map01.java @@ -0,0 +1,25 @@ +package main.maps; + +import main.Tile; + +public class Map01 extends Map { + + public Map01 () { + super (15,11); + for (int x = 0; x < map.length; x++) { + for (int y = 0; y < map[0].length; y++) { + //Wand + if((x == 4 || y == 9 || x == 10) && x > 3 && y > 0 && x < 11 && y < 10 && x != 7 ) { + map[x][y] = new Tile(3, x, y); + add(map[x][y]); + } + //Boden + else if(x > 3 && y > 0 && x < 11 && y < 10) { + map[x][y] = new Tile(5, x, y); + add(map[x][y]); + } + } + } + } + +} diff --git a/Zoelda/src/main/maps/Map02.java b/Zoelda/src/main/maps/Map02.java new file mode 100644 index 0000000..54bfe25 --- /dev/null +++ b/Zoelda/src/main/maps/Map02.java @@ -0,0 +1,38 @@ +package main.maps; + +import main.Tile; + +public class Map02 extends Map { + + public Map02() { + super(15, 11); + + for (int x = 0; x < map.length; x++) { + for (int y = 0; y < map[0].length; y++) { + // Wand + if (y == 0 || x == 0 || y == 10 || x == 14) { + // Übergang, Tür + if (y == 10) { + if (x > 4 && x < 10) { + map[x][y] = new Tile(5, x, y); + add(map[x][y]); + continue; + } + } + map[x][y] = new Tile(3, x, y); + add(map[x][y]); + } + // 3D-Wand + else if(y == 1 ) { + map[x][y] = new Tile(4, x, y); + add(map[x][y]); + } + // Steinboden + else { + map[x][y] = new Tile(5, x, y); + add(map[x][y]); + } + } + } + } +} diff --git a/Zoelda/src/main/maps/TutorialMap.java b/Zoelda/src/main/maps/TutorialMap.java new file mode 100644 index 0000000..1e0e716 --- /dev/null +++ b/Zoelda/src/main/maps/TutorialMap.java @@ -0,0 +1,44 @@ +package main.maps; + +import main.Tile; +import main.entities.Snake; +import main.entities.Spider; + +public class TutorialMap extends Map { + + public TutorialMap() { + super(15, 11); + for (int x = 0; x < map.length; x++) { + for (int y = 0; y < map[0].length; y++) { + //Wand, Sichtschutz + if (y == 0 ||y == map[0].length - 1 || x == 0 || x == map.length - 1 || ((y == 4|| y == 5) && x == 10 )) { + map[x][y] = new Tile (1, x, y); + add(map [x][y]); + } + //3D-Wand, 3F-Sichtschutz + else if(y == 1 || ( y == 6 && x == 10)) { + map[x][y] = new Tile (2, x, y); + add(map [x][y]); + } + //Grasboden + else{ + map[x][y] = new Tile(0, x, y); + add(map[x][y]); + } + } + } + + // und Spinnen auch + Spider spider = new Spider(); + add(spider.actionFigur); + getEntities().add(spider); + + //und + Snake snake = new Snake(); + add(snake.actionFigur); + getEntities().add(snake); + + // Alle Entities als ticker registrieren (triggert dann die update methoden) + registerEntities(); + } +} diff --git a/Zoelda/src/res/images/herzen.png b/Zoelda/src/res/images/herzen.png new file mode 100644 index 0000000..c64d5e7 Binary files /dev/null and b/Zoelda/src/res/images/herzen.png differ diff --git a/Zoelda/src/res/images/icons.png b/Zoelda/src/res/images/icons.png new file mode 100644 index 0000000..0ae4752 Binary files /dev/null and b/Zoelda/src/res/images/icons.png differ diff --git a/Zoelda/src/res/images/maps/map1.png b/Zoelda/src/res/images/maps/map1.png new file mode 100644 index 0000000..bea5452 Binary files /dev/null and b/Zoelda/src/res/images/maps/map1.png differ diff --git a/Zoelda/src/res/images/maps/map2.png b/Zoelda/src/res/images/maps/map2.png new file mode 100644 index 0000000..5361062 Binary files /dev/null and b/Zoelda/src/res/images/maps/map2.png differ diff --git a/Zoelda/src/res/images/maps/map3.png b/Zoelda/src/res/images/maps/map3.png new file mode 100644 index 0000000..8182b79 Binary files /dev/null and b/Zoelda/src/res/images/maps/map3.png differ diff --git a/Zoelda/src/res/images/maps/map4.png b/Zoelda/src/res/images/maps/map4.png new file mode 100644 index 0000000..a3e5eee Binary files /dev/null and b/Zoelda/src/res/images/maps/map4.png differ diff --git a/Zoelda/src/res/images/maps/map5.png b/Zoelda/src/res/images/maps/map5.png new file mode 100644 index 0000000..2c0ed6d Binary files /dev/null and b/Zoelda/src/res/images/maps/map5.png differ diff --git a/Zoelda/src/res/images/maps/map6.png b/Zoelda/src/res/images/maps/map6.png new file mode 100644 index 0000000..0c17146 Binary files /dev/null and b/Zoelda/src/res/images/maps/map6.png differ diff --git a/Zoelda/src/res/images/maps/map7.png b/Zoelda/src/res/images/maps/map7.png new file mode 100644 index 0000000..fd4ad1e Binary files /dev/null and b/Zoelda/src/res/images/maps/map7.png differ diff --git a/Zoelda/src/res/images/maps/map8.png b/Zoelda/src/res/images/maps/map8.png new file mode 100644 index 0000000..0f3cc49 Binary files /dev/null and b/Zoelda/src/res/images/maps/map8.png differ diff --git a/Zoelda/src/res/images/snake_spritesheet_calciumtrice.png b/Zoelda/src/res/images/snake_spritesheet_calciumtrice.png index 0417b5e..55dd879 100644 Binary files a/Zoelda/src/res/images/snake_spritesheet_calciumtrice.png and b/Zoelda/src/res/images/snake_spritesheet_calciumtrice.png differ diff --git a/Zoelda/src/res/images/spider_sprite_sheet.png b/Zoelda/src/res/images/spider_sprite_sheet.png index 89de203..82a546c 100644 Binary files a/Zoelda/src/res/images/spider_sprite_sheet.png and b/Zoelda/src/res/images/spider_sprite_sheet.png differ diff --git a/Zoelda/src/res/images/tiles/Test.png b/Zoelda/src/res/images/tiles/Test.png new file mode 100644 index 0000000..ba2cd98 Binary files /dev/null and b/Zoelda/src/res/images/tiles/Test.png differ diff --git a/Zoelda/src/res/images/tiles/TestTest.png b/Zoelda/src/res/images/tiles/TestTest.png new file mode 100644 index 0000000..c439029 Binary files /dev/null and b/Zoelda/src/res/images/tiles/TestTest.png differ diff --git a/Zoelda/src/res/images/tiles/door.png b/Zoelda/src/res/images/tiles/door.png new file mode 100644 index 0000000..92edddf Binary files /dev/null and b/Zoelda/src/res/images/tiles/door.png differ diff --git a/Zoelda/src/res/images/tiles/stone_floor.png b/Zoelda/src/res/images/tiles/stone_floor.png deleted file mode 100644 index 5638a31..0000000 Binary files a/Zoelda/src/res/images/tiles/stone_floor.png and /dev/null differ diff --git a/Zoelda/src/res/images/tiles/stone_wall.png b/Zoelda/src/res/images/tiles/stone_wall.png deleted file mode 100644 index b0842b0..0000000 Binary files a/Zoelda/src/res/images/tiles/stone_wall.png and /dev/null differ diff --git a/Zoelda/src/res/images/tiles/stone_wall_bottom.png b/Zoelda/src/res/images/tiles/stone_wall_bottom.png index 21d5f5c..5279d0f 100644 Binary files a/Zoelda/src/res/images/tiles/stone_wall_bottom.png and b/Zoelda/src/res/images/tiles/stone_wall_bottom.png differ