From 7d055dbe2f9fce091ccacf86af3fe19cb293c3c8 Mon Sep 17 00:00:00 2001 From: Asecave Date: Wed, 23 Jun 2021 15:44:37 +0200 Subject: [PATCH] COMMENTS --- Zoelda/src/main/Entity.java | 32 ++++++++++--- Zoelda/src/main/LivingEntity.java | 39 +++++++++++++--- Zoelda/src/main/Malin.java | 11 ++++- Zoelda/src/main/Map.java | 20 ++++++-- Zoelda/src/main/Player.java | 18 +++++++- Zoelda/src/main/PlayerSheetLoader.java | 12 +---- Zoelda/src/main/Tile.java | 63 ++++++++++++++++++-------- Zoelda/src/main/World.java | 11 ++++- 8 files changed, 157 insertions(+), 49 deletions(-) diff --git a/Zoelda/src/main/Entity.java b/Zoelda/src/main/Entity.java index 961b17e..7cdca83 100644 --- a/Zoelda/src/main/Entity.java +++ b/Zoelda/src/main/Entity.java @@ -2,20 +2,30 @@ package main; import ea.Ticker; +/* + * Alles was sich bewegen kann oder nicht an das grid der map gebunden ist, ist ein Entity. + * Also Der Spieler, Gegner, Items, Coins, ... + */ public abstract class Entity implements Ticker { - protected float posX, posY; - protected float velX, velY; - protected float accelleration = 0.012f; - protected float friction = 0.2f; - protected float width = 1f, height = 1f; + protected float posX, posY; // Position des entities in gameunits. + protected float velX, velY; // Geschwindigkeit des eitities in gameunits pro frame. + 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. + // Das ist die Ticker-Methode von ea; wird jeden frame ausgeführt (frameloop) @Override public void tick() { + // Geschwindigkeit wird zur position addiert (es gibt natürlich auch negative + // Ges.) posX += velX; posY += velY; + // Reibung wird mit einberechnet, damit nicht unentlich beschleunigt wird velX *= (1f - friction); velY *= (1f - friction); + // Wenn die Geschwindigkeit (ungefähr) nicht mehr sichtbar ist wird sie einfach + // auf 0 gecapt. if (velX < 0.001f && velX > -0.001f) { velX = 0f; } @@ -25,8 +35,15 @@ public abstract class Entity implements Ticker { update(); } + /** + * Die Update-Methode wird jeden frame ausgeführt. Hier kann man die logik für + * sein Entity reinschreiben wenn man sie Überschreibt. + */ protected abstract void update(); + /** + * Checkt collision mit tiles von der map. Fertig, clean, nie wieder ändern. + */ public void checkTileCollisions(Map map) { for (int x = (int) (posX - 2); x < posX + 2; x++) { for (int y = (int) (posY - 2); y < posY + 2; y++) { @@ -53,7 +70,10 @@ public abstract class Entity implements Ticker { } } - public void onBlockCollision(boolean[] sides, int blockX, int blockY) { + /** + * Gehört mit zur collision detection. Hier werden kollisionen aufgelöst. + */ + private void onBlockCollision(boolean[] sides, int blockX, int blockY) { if (sides[0]) { if (velY < 0) { velY = 0; diff --git a/Zoelda/src/main/LivingEntity.java b/Zoelda/src/main/LivingEntity.java index 77275bc..b517a25 100644 --- a/Zoelda/src/main/LivingEntity.java +++ b/Zoelda/src/main/LivingEntity.java @@ -3,26 +3,48 @@ package main; import ea.ActionFigur; import ea.Figur; +/* + * Alles was zustände hat und sich Bewegen kann, ist ein LivingEntity. + */ public class LivingEntity extends Entity { - protected boolean side; - protected ActionFigur actionFigur; - protected float spriteOffsetX, spriteOffsetY; + protected boolean side; // true = gespiegelt, false = nicht + protected ActionFigur actionFigur; // Sprite des Entities + protected float spriteScale = 1f; // Skalierung des Sprites + protected float spriteOffsetX, spriteOffsetY; // Offset des Sprites. Hier kann man die relative render-Position nachjustieren. + /** + * @param figur - erstes (standart) Sprite + * @param name - name des Zustands + */ public LivingEntity(Figur figur, String name) { - actionFigur = new ActionFigur(figur, name); + actionFigur = new ActionFigur(figur, name) { + // DEBUG: render boxes + +// @Override +// public void zeichnen(Graphics2D g, BoundingRechteck r) { +// g.setColor(Color.GREEN); +// g.drawRect((int) actionFigur.positionX(), (int) actionFigur.positionY(), (int) actionFigur.getBreite(), (int) actionFigur.getHoehe()); +// g.drawRect((int) ((posX - width / 2) * World.SCALE), (int) ((posY - height / 2) * World.SCALE), (int) (width * World.SCALE), (int) (height * World.SCALE)); +// super.zeichnen(g, r); +// } + }; } @Override protected void update() { + // Prüft zu welcher seite man guckt if (velX < 0) { side = true; } else if (velX > 0) { side = false; } - int offsetX = (int) ((width * Tile.getSize()) / 2 - (actionFigur.getBreite()) / 2 + spriteOffsetX * Tile.getSize() - (width * Tile.getSize()) / 2); - int offsetY = (int) ((height * Tile.getSize()) / 2 - (actionFigur.getHoehe()) / 2 + spriteOffsetY * Tile.getSize() - (height * Tile.getSize()) / 2); - actionFigur.positionSetzen(posX * Tile.getSize() + offsetX, posY * Tile.getSize() + offsetY); + + // Packt das Sprite an die richtige Stelle + actionFigur.faktorSetzen((int) (spriteScale * World.SCALE_FACTOR)); + float offsetX = width / 2 + spriteOffsetX - width / 2; + float offsetY = height / 2 + spriteOffsetY - height / 2; + actionFigur.positionSetzen((posX + offsetX) * World.SCALE - actionFigur.getBreite() / 2, (posY + offsetY) * World.SCALE - actionFigur.getHoehe() / 2); } protected void moveLeft() { @@ -41,6 +63,9 @@ public class LivingEntity extends Entity { velY += accelleration; } + /** + * Spiegelt die figur autmatisch, wenn nötig. + */ protected void zustandSetzen(String name) { actionFigur.spiegelXSetzen(side); actionFigur.zustandSetzen(name); diff --git a/Zoelda/src/main/Malin.java b/Zoelda/src/main/Malin.java index f8f1b8d..466dbde 100644 --- a/Zoelda/src/main/Malin.java +++ b/Zoelda/src/main/Malin.java @@ -3,23 +3,30 @@ package main; import ea.Game; import ea.Manager; +/** + * Von hier wird alles initialisiert. Das ist die höchste Klasse. + */ public class Malin extends Game { private World world; private Player player; - public static final int WIDTH = 1440; - public static final int HEIGHT = 1056; + public static final int WIDTH = 1440; // Fensterbreite + public static final int HEIGHT = 1056; // Fensterhöhe public Malin() { super(WIDTH, HEIGHT); + // Lönk player = new Player(this); + // Welt initialisieren und Spieler hinzufügen world = new World(player); + // die Welt zu EA hinzufügen wurzel.add(world); Manager manager = new Manager(); + // Den Spieler als ticker registrieren (triggert dann die update methoden) manager.anmelden(player, 20); } diff --git a/Zoelda/src/main/Map.java b/Zoelda/src/main/Map.java index 6caa07d..5633da9 100644 --- a/Zoelda/src/main/Map.java +++ b/Zoelda/src/main/Map.java @@ -2,29 +2,43 @@ package main; import ea.Knoten; +/** + * Auf der Map sind alle Entities, sowie die Tiles gespiechert. + */ public class Map extends Knoten { - private Tile[][] map; + private Tile[][] map; // Die Tiles der map in einem 2D Array. public Map() { + // Größe der Map ist 15u breit und 11u hoch map = new Tile[15][11]; + + // Tiles der map definieren for (int x = 0; x < map.length; x++) { for (int y = 0; y < map[0].length; y++) { int id = 0; + + // Auf bestimmten koordinaten wird die id des Tiles geändert if (y == 1 || (x == 7 && y == 7)) { id = Tile.WALL_BOTTOM; } if (y == 0 || y == map[0].length - 1 || x == 0 || x == map.length - 1 || (x == 7 && y == 6)) { id = Tile.WALL_TOP; } + + // Tile wird erstellt map[x][y] = new Tile(id); - map[x][y].setX(x * Tile.getSize()); - map[x][y].setY(y * Tile.getSize()); + // Tile wird an die passende Position gebracht + map[x][y].positionSetzen(x * World.SCALE, y * World.SCALE); + // Tile wird zur EA hinzugefügt (damit es auch gerendert wird) add(map[x][y]); } } } + /** + * 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) { return map[x][y]; diff --git a/Zoelda/src/main/Player.java b/Zoelda/src/main/Player.java index ab4b428..8245eeb 100644 --- a/Zoelda/src/main/Player.java +++ b/Zoelda/src/main/Player.java @@ -4,22 +4,28 @@ import ea.Taste; public class Player extends LivingEntity { - private Malin main; + private Malin main; // Referenz auf die main Klasse. Wird später für den Keyboardinput verwendet private static PlayerSheetLoader loader = new PlayerSheetLoader(); public Player(Malin main) { super(loader.getPlayer(0), "idle_left"); this.main = main; + // Entity-Eigenschaften werden festgelegt width = 0.7f; height = 0.8f; spriteOffsetY = -0.14f; + spriteScale = 0.8f; posX = 4f; posY = 4f; + // unterschiedliche Animationsgeschwindigkeiten + // für idle loader.getPlayer(0).animationsGeschwindigkeitSetzen(200); + // fürs laufen loader.getPlayer(1).animationsGeschwindigkeitSetzen(50); + // Zustände werden hinzugefügt actionFigur.neuerZustand(loader.getPlayer(0), "idle"); actionFigur.neuerZustand(loader.getPlayer(1), "walk"); actionFigur.neuerZustand(loader.getPlayer(2), "strike"); @@ -29,10 +35,14 @@ public class Player extends LivingEntity { @Override protected void update() { + // Bei dieser animation bleibt man sofort stehen. 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)) { + + // wasd movement if (main.tasteGedrueckt(Taste.A)) { moveLeft(); } @@ -45,12 +55,15 @@ public class Player extends LivingEntity { if (main.tasteGedrueckt(Taste.S)) { moveDown(); } + + // Auf idle stellen wenn man sich nicht bewegt if (velX == 0 && velY == 0) { zustandSetzen("idle"); } else { zustandSetzen("walk"); } + // Attacken if (main.tasteGedrueckt(Taste.LEERTASTE)) { zustandSetzen("swipe"); } @@ -58,7 +71,10 @@ public class Player extends LivingEntity { zustandSetzen("strike"); } } + + // auf Kollisionen prüfen checkTileCollisions(main.getWorld().getCurrentMap()); + // LivingEntity auch updaten lassen super.update(); } else { velX = 0; diff --git a/Zoelda/src/main/PlayerSheetLoader.java b/Zoelda/src/main/PlayerSheetLoader.java index e756abb..a639556 100644 --- a/Zoelda/src/main/PlayerSheetLoader.java +++ b/Zoelda/src/main/PlayerSheetLoader.java @@ -13,8 +13,6 @@ public class PlayerSheetLoader { private static Figur[] player; - private static final float SCALE_DIV = 1.5f; - public PlayerSheetLoader() { try { BufferedImage sheet = ImageIO.read(Tile.class.getResourceAsStream("/res/images/player_sprite_sheet.png")); @@ -51,17 +49,11 @@ public class PlayerSheetLoader { private void loadSprites(PixelFeld[] sprites, int row, int w, int h, BufferedImage sheet) { for (int s = 0; s < sprites.length; s++) { - sprites[s] = new PixelFeld(w * (int) (World.SCALE / SCALE_DIV), h * (int) (World.SCALE / SCALE_DIV), 1); + sprites[s] = new PixelFeld(w, h, 1); for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { Color clr = new Color(sheet.getRGB((s * w + x), (row * h + y)), true); - if (clr.getAlpha() > 0) { - for (int i = 0; i < World.SCALE / SCALE_DIV; i++) { - for (int j = 0; j < World.SCALE / SCALE_DIV; j++) { - sprites[s].farbeSetzen(x * (int) (World.SCALE / SCALE_DIV) + i, y * (int) (World.SCALE / SCALE_DIV) + j, clr); - } - } - } + sprites[s].farbeSetzen(x, y, clr); } } } diff --git a/Zoelda/src/main/Tile.java b/Zoelda/src/main/Tile.java index b8f1882..ae68dee 100644 --- a/Zoelda/src/main/Tile.java +++ b/Zoelda/src/main/Tile.java @@ -1,7 +1,5 @@ package main; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.IOException; @@ -10,36 +8,45 @@ import javax.imageio.ImageIO; import ea.Bild; import ea.Knoten; +/** + * Ein feld auf der Map + */ public class Tile extends Knoten { + // IDs der Tiles public static final int GRASS = 0; public static final int WALL_TOP = 1; public static final int WALL_BOTTOM = 2; - private Bild img; - private int id; + private Bild img; // Bild, das gerendert wird + private int id; // Die id dises Tiles public Tile(int id) { this.id = id; + + // 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); } - BufferedImage after = new BufferedImage(buff.getWidth() * World.SCALE, buff.getHeight() * World.SCALE, BufferedImage.TYPE_INT_ARGB); - AffineTransform at = new AffineTransform(); - at.scale(World.SCALE, World.SCALE); - AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); - after = scaleOp.filter(buff, after); - int x = 0; - int y = 0; - img = new Bild(x, y, after); + // 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(0, 0, scaled); + } catch (IOException e) { e.printStackTrace(); } + // Bild zu EA hinzufügen. add(img); } + /** + * @return den Pfad der zu der Id gehört. + */ private String getPathFromId(int id) { switch (id) { case GRASS: @@ -52,26 +59,46 @@ public class Tile extends Knoten { return null; } + /** + * @return die Größe der Textur + */ public static int getSize() { - return 16 * World.SCALE; + return 16; } - + + /** + * @return ob man durch das Tile durchgehen kann + */ 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; } - + + /** + * Kleine Hifsmethode un die koordinate der Top-Kante rurückzugenben. + */ public int getTop() { return positionY(); } - + + /** + * Kleine Hifsmethode un die koordinate der Bottom-Kante rurückzugenben. + */ public int getBottom() { return positionY() + getSize(); } - + + /** + * Kleine Hifsmethode un die koordinate der Left-Kante rurückzugenben. + */ public int getLeft() { return positionX(); } - + + /** + * Kleine Hifsmethode un die koordinate der Right-Kante rurückzugenben. + */ public int getRight() { return positionX() + getSize(); } diff --git a/Zoelda/src/main/World.java b/Zoelda/src/main/World.java index deea772..b0273d3 100644 --- a/Zoelda/src/main/World.java +++ b/Zoelda/src/main/World.java @@ -2,16 +2,23 @@ package main; import ea.Knoten; +/** + * Hier werden alle Maps gespeichert. + */ public class World extends Knoten { - public static final int SCALE = 6; + 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; + private Map currentMap; // Die Map die aktuell angezeigt werden soll. public World(Player player) { + // Map initialisieren currentMap = new Map(); + // Map zu EA hinzufügen add(currentMap); + // und Spieler auch add(player.actionFigur); }