package de.sanguinik.view;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
import de.sanguinik.model.Bullet;
import de.sanguinik.model.Enemy;
import de.sanguinik.model.HighscoreEntry;
import de.sanguinik.model.Keyboard;
import de.sanguinik.model.Maze;
import de.sanguinik.model.Player;
import de.sanguinik.model.ShootCallback;
import de.sanguinik.model.TypeOfFigure;
public class PlayFieldScreen extends Application {
private class ShootCallbackImpl implements ShootCallback {
@Override
public void shootBullet(final Bullet bullet) {
bulletList.add(bullet);
root.getChildren().add(bullet.getGroup());
}
}
private final static int START_X_PLAYER_1 = 130;
private final static int START_Y_PLAYER_1 = 510;
private final Timeline timeline = new Timeline();
private final List<Enemy> enemyList = new ArrayList<Enemy>();
private final List<Bullet> bulletList = new ArrayList<Bullet>();
private static final int ONE_SECOND = 1000;
private static final int FPS = 30;
private final Group root = new Group();
private boolean gameWasPaused = true;
private final Label pause = new Label("PAUSE");
private HighscoreEntry entry;
private Media music;
private MediaPlayer mediaPlayer;
/**
* Mit dieser Wahrscheinlichkeit wird ein mal pro Sekunde geschossen.
*/
private static final double SHOOT_LIKELIHOOD = 0.7;
private Maze maze;
private Player player;
private Stage primaryStage;
private Enemy createEnemy(final TypeOfFigure enemyType, final int x,
final int y) {
Enemy enemy = new Enemy(maze, enemyType, x, y);
enemy.addTargets(player);
enemy.setShootCallback(new ShootCallbackImpl());
enemyList.add(enemy);
return enemy;
}
@Override
public void start(final Stage primaryStage) {
this.primaryStage = primaryStage;
primaryStage.setTitle("Knight of Wor");
primaryStage.setResizable(false);
URL pathToLevelMusic = getClass().getResource("KoWLong.mp3");
if (pathToLevelMusic != null) {
music = new Media(pathToLevelMusic.toString());
mediaPlayer = new MediaPlayer(music);
mediaPlayer.setVolume(0.5);
mediaPlayer.play();
} else {
System.err.println("Musikdatei 'KoWLong.pm3' nicht gefunden!");
}
maze = new Maze("level1");
player = new Player(maze, START_X_PLAYER_1, START_Y_PLAYER_1);
player.setShootCallback(new ShootCallbackImpl());
final Enemy enemy1 = createEnemy(TypeOfFigure.BURWOR, 130, 130);
final Enemy enemy2 = createEnemy(TypeOfFigure.GARWOR, 855, 510);
final Enemy enemy3 = createEnemy(TypeOfFigure.THORWOR, 855, 130);
player.addTargets(enemy1, enemy2, enemy3);
Label score = new Label("Score: " + player.getScore());
Label lives = new Label("Leben: " + player.getLives());
lives.setLayoutY(40);
Keyboard keyboard = new Keyboard(player, this);
root.getChildren().add(player.getGroup());
root.getChildren().add(enemy1.getGroup());
root.getChildren().add(enemy2.getGroup());
root.getChildren().add(enemy3.getGroup());
root.getChildren().addAll(maze.getWalls());
root.getChildren().add(score);
root.getChildren().add(lives);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(false);
EventHandler<ActionEvent> actionPerFrame = new EventHandler<ActionEvent>() {
@Override
public void handle(final ActionEvent t) {
introSequence();
if(checkThatPlayerIsStillAlive()){
moveAllEnemies();
moveAllBullets();
score.setText("Score: " + player.getScore());
}else{
if(player.getLives() == 0){
enterHighscore();
}else{
timeline.pause();
player.getRectangle().setX(START_X_PLAYER_1);
player.getRectangle().setY(START_Y_PLAYER_1);
player.getImageView().setX(START_X_PLAYER_1);
player.getImageView().setY(START_Y_PLAYER_1);
player.setLives(player.getLives() - 1);
lives.setText("Leben: " + player.getLives());
player.setInvincible(true);
player.setAlive(true);
timeline.play();
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
Platform.runLater(() -> {
player.setInvincible(false);
});
}
}, 3000);
}
}
}
};
KeyFrame keyframe = new KeyFrame(Duration.millis(ONE_SECOND / FPS),
actionPerFrame);
timeline.getKeyFrames().add(keyframe);
timeline.play();
Scene scene = new Scene(root, 1024, 740);
scene.getStylesheets().add(TitleScreen.class.getResource("controls.css").toExternalForm());
scene.setOnKeyPressed(keyboard);
scene.setFill(Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(final WindowEvent w) {
timeline.stop();
if (mediaPlayer != null) {
mediaPlayer.stop();
}
System.exit(0);
}
});
}
private boolean checkThatPlayerIsStillAlive() {
if (!player.isAlive()) {
gameWasPaused = true;
player.toggleMoveable();
return false;
}
return true;
}
private void enterHighscore(){
if (mediaPlayer != null) {
mediaPlayer.stop();
}
timeline.stop();
int finalScore = player.getScore();
String playerName = "Spieler 1";
Label playersPoints = new Label("Du hast "+finalScore+ " Punkte!");
playersPoints.setTextFill(Color.WHITESMOKE);
Label enterHighscore = new Label("Trage deinen Namen ein! ");
enterHighscore.setTextFill(Color.WHITESMOKE);
TextField name = new TextField(playerName);
Button ok = new Button("Ok");
VBox highscorePopup = new VBox();
highscorePopup.setAlignment(Pos.CENTER);
highscorePopup.getChildren().add(playersPoints);
highscorePopup.getChildren().add(enterHighscore);
HBox highscoreBox = new HBox();
highscoreBox.getChildren().add(name);
highscoreBox.getChildren().add(ok);
highscorePopup.getChildren().add(highscoreBox);
highscorePopup.setLayoutX(root.getScene().getWidth()/2 - 120);
highscorePopup.setLayoutY(root.getScene().getHeight() - 100);
root.getChildren().add(highscorePopup);
ok.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
//highscore eintragen
entry = new HighscoreEntry(name.getText(), finalScore);
//gameover
gameOver();
}
});
}
private void introSequence() {
Label ready = new Label("READY?");
ready.setLayoutX(root.getScene().getWidth()/2);
ready.setLayoutY(root.getScene().getHeight()/2);
if(gameWasPaused){
timeline.pause();
root.getChildren().add(ready);
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
Platform.runLater(() -> {
ready.setText("START!");
});
}
}, 1000);
timer.schedule(new TimerTask(){
@Override
public void run() {
Platform.runLater(() -> {
timeline.play();
player.toggleMoveable();
root.getChildren().remove(ready);
});
}
}, 2000);
gameWasPaused = false;
}
}
private void moveAllBullets() {
List<Bullet> bulletsToDelete = new ArrayList<Bullet>();
for (Bullet b : bulletList) {
b.move();
if (!b.isActive()) {
bulletsToDelete.add(b);
}
}
for (Bullet b : bulletsToDelete) {
bulletList.remove(b);
root.getChildren().remove(b.getGroup());
}
}
private void moveAllEnemies() {
List<Enemy> enemiesToDelete = new ArrayList<Enemy>();
if (enemyList.isEmpty()) {
enterHighscore();
}
for (Enemy e : enemyList) {
if (e.isAlive()) {
e.move();
int d = (int) (FPS * (1 / SHOOT_LIKELIHOOD));
int random = new Random().nextInt(d);
if (random == 0) {
e.shoot();
}
} else {
enemiesToDelete.add(e);
}
}
for (Enemy e : enemiesToDelete) {
enemyList.remove(e);
root.getChildren().remove(e.getGroup());
player.getTargets().remove(e);
}
}
private void gameOver() {
final GameOver gameOver = new GameOver();
gameOver.start(primaryStage);
if (mediaPlayer != null) {
mediaPlayer.stop();
}
}
public void pauseGame(){
if(gameWasPaused){
root.getChildren().remove(pause);
timeline.play();
gameWasPaused = false;
}else{
pause.setLayoutX(root.getScene().getWidth()/2);
pause.setLayoutY(root.getScene().getHeight()/2);
root.getChildren().add(pause);
timeline.pause();
gameWasPaused = true;
}
}
public void muteMusic() {
if(mediaPlayer.isMute()){
mediaPlayer.setMute(false);
}else{
mediaPlayer.setMute(true);
}
}
}