package gamestates;
import java.awt.Color;
import java.awt.Toolkit;
import java.util.ArrayList;
import core.KeyInputHandler;
import core.Renderer;
import core.Score;
import core.Sprite;
import core.Tilemap;
import core.View;
import core.MainGame.GameLoop;
import entities.Coin;
import entities.Entity;
import entities.Finish;
import entities.GoombaBig;
import entities.GoombaSmall;
import entities.Player;
/**
* Gamestate zum Verarbeiten der Spielelogik
*
* @author Marco Strobel
*/
public class InGame extends Gamestate{
// Benötigte Instanzvariablen für den InGame State
private Tilemap tm; // Die Tilemap
private View view; // Das Sichtfeld
private static InGame inGame; // Die Instanz
private static Player player; // Der Spieler
private ArrayList<Entity> updateList = new ArrayList<Entity>(); // Liste der zu verarbeitenden Objekte
private ArrayList<Entity> deleteList = new ArrayList<Entity>(); // Liste der zu löschenden Objekte
private ArrayList<Sprite> drawList = new ArrayList<Sprite>(); // Liste der zu zeichnenden Objekte
private int level; // Das aktuelle Level
private boolean win; // Gewonnen?
private boolean gameover; // Verloren?
private int timer; // Der Timer für das Spiel
private int timertrigger; // Legt fest wieviele Durchläuft bis der Timer dekrementiert wird
private BackgroundSprite background; // Hintergrundbild
/**
* Rückgabe der liste aller aktiven Entities
*
* @return Die liste aller aktiven Entities
*/
public ArrayList<Entity> getUpdateList() {
return updateList;
}
/**
* Instanzrückgabe für das Singleton
*
* @return Die Instanz dieses Singletons
*/
public static synchronized InGame getInstance() {
if (inGame == null)
inGame = new InGame();
return inGame;
}
/**
* Initialisieren der Daten für die Spielelogik
*/
private InGame() {
super();
// Hintergrund setzen
background = new BackgroundSprite(
Toolkit.getDefaultToolkit().getImage( getClass().getResource("/images/tiles/background.png") )
);
// Tilemap initialisieren
tm = Tilemap.getInstance();
// Initialisieren des Spielerobjekts
player = new Player();
new Thread(player).start();
// Level laden
loadNextLevel();
// Sichtfeld des Spielers initialisieren
view = View.getInstance();
}
/**
* Entities erstellen und auf Startpositionen setzen
*/
private void spawnEntities() {
int entities[][] = tm.loadEntityData(level);
for (int[] entity : entities)
if (entity[0] == 0) {
// Initialisieren des Spielerobjekts
player.getHitbox().newX = entity[1] * tm.getTilesizeX();
player.getHitbox().newY = entity[2] * tm.getTilesizeY() - player.getHitbox().height;
updateList.add(player);
}
else if (entity[0] == 1) {
// Initialisieren eines kleinen Gegners
GoombaSmall e = new GoombaSmall();
e.getHitbox().newX = entity[1] * tm.getTilesizeX();
e.getHitbox().newY = entity[2] * tm.getTilesizeY() - e.getHitbox().height;
updateList.add(e);
new Thread(e).start();
}
else if (entity[0] == 2) {
// Initialisieren eines großen Gegners
GoombaBig e = new GoombaBig();
e.getHitbox().newX = entity[1] * tm.getTilesizeX();
e.getHitbox().newY = entity[2] * tm.getTilesizeY() - e.getHitbox().height;
updateList.add(e);
new Thread(e).start();
}
else if (entity[0] == 3) {
// Initialisieren eines großen Gegners
Coin e = new Coin();
e.getHitbox().newX = entity[1] * tm.getTilesizeX();
e.getHitbox().newY = entity[2] * tm.getTilesizeY() - e.getHitbox().height;
updateList.add(e);
new Thread(e).start();
}
else if (entity[0] == 4) {
// Initialisieren eines großen Gegners
Finish e = new Finish();
e.getHitbox().newX = entity[1] * tm.getTilesizeX();
e.getHitbox().newY = entity[2] * tm.getTilesizeY() - e.getHitbox().height;
updateList.add(e);
new Thread(e).start();
}
}
/**
* Respawnen aller Entities des Levels
*/
public void respawn() {
synchronized (updateList) {
// Alle Entities töten
for (Entity e : updateList)
if (!e.equals(player) && !e.dead)
e.dead = true;
updateList.clear();
player.collidesX = false;
player.collidesY = false;
spawnEntities();
}
// Timer zurücksetzen
timer = 120;
timertrigger = 50;
}
/* (non-Javadoc)
* @see core.Gamestate#update()
*/
@Override
public void update() {
synchronized (updateList) {
if (!(win || gameover)) {
// Wenn der Timertrigger abgelaufen ist den Timer dekrementieren
--timertrigger;
if (timertrigger < 0) {
--timer;
timertrigger = 50;
}
// Listen aktualisieren
drawList.clear();
updateList.removeAll(deleteList);
deleteList.clear();
for (Entity e : updateList) {
// Wenn die Entity tot ist auf die Löschliste setzen
if (e.dead)
deleteList.add(e);
else {
// Falls die Entity angehalten ist weiterlaufen lassen
if (!e.active)
e.active = true;
// Objekte im Sichtfeld auf die Zeichenliste setzen
if (isInView(e))
drawList.add(e);
}
}
}
else {
// Wenn gewonnen oder verloren wurde alle Entities entfernen
for (Entity e : updateList)
if (!e.dead)
e.dead = true;
updateList.clear();
}
}
updateView();
inputHandling();
}
/**
* Behandlung für ein gewonnenes Level
*/
public void win() {
Score.getInstance().calcWithTime(timer);
if (level < 3)
loadNextLevel();
else {
win = true;
Score.getInstance().enterName();
}
}
/**
* Behandlung für das Verlieren
*/
public void gameover() {
gameover = true;
Score.getInstance().enterName();
}
/**
* Nächstes Level laden
*/
private void loadNextLevel() {
// Spielerlogik für die Ladezeit anhalten
player.active = false;
tm.loadMap(++level);
respawn();
}
/**
* Das Sichtfeld aktualisieren
*
* Sichtfeld wird um den Spieler zentriert sofern sich dieser nicht am Rand des Levels befindet
*/
private void updateView() {
int playercenter = player.getHitbox().x + player.getHitbox().width / 2;
int viewcenter = view.width / 2;
// Falls der Spieler am Anfang des Levels ist die View an den Anfang setzen
if (playercenter - viewcenter < 0)
view.x = 0;
// Falls der Spieler am Ende des Levels ist die View an das Ende setzen
else if (playercenter + viewcenter > Tilemap.getInstance().getMap()[0].length * Tilemap.getInstance().getTilesizeX())
view.x = Tilemap.getInstance().getMap()[0].length * Tilemap.getInstance().getTilesizeX() - view.width;
// Sonst um den Spieler zentrieren
else
view.x = playercenter - viewcenter;
background.getHitbox().setLocation(view.getLocation());
}
/**
* Verarbeitung von Tastatureingaben
*/
private void inputHandling() {
// Mit Escape ins Menü wechseln
if(KeyInputHandler.getInstance().escapeIsPressed)
{
for (Entity e : updateList)
e.active = false;
view.x = 0;
GameLoop.getInstance().goInMenu();
}
}
/* (non-Javadoc)
* @see core.Gamestate#draw()
*/
@Override
public void draw() {
background.draw();
tm.draw();
super.draw(drawList);
// GUI in den Vordergrund zeichnen
Renderer.getInstance().drawText("Leben: " + player.getLives(), 30, 30, Color.WHITE);
Renderer.getInstance().drawText("Zeit: " + timer, 330, 30, Color.WHITE);
Renderer.getInstance().drawText("Score: " + Score.getInstance().getCurrentScore(), 600, 30, Color.WHITE);
if (win) {
Renderer.getInstance().drawText("Gewonnen!",
Renderer.getInstance().getWidth() / 2 - 40, Renderer.getInstance().getHeight() / 2 - 40,
Color.RED);
}
else if (gameover) {
Renderer.getInstance().drawText("Verloren!",
Renderer.getInstance().getWidth() / 2 - 50, Renderer.getInstance().getHeight() / 2 - 40,
Color.RED);
}
}
/**
* Überprüfung ob das Objekt im Sichtfeld ist
*
* @param e Die zu überprüfende Entity
* @return Objekt ist in der View oder nicht? true/false
*/
private boolean isInView(Entity e) {
return e.getHitbox().intersects(view);
}
}