COMMENTS
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user