package eu.midnightdust.yaytris; import eu.midnightdust.yaytris.game.Space; import eu.midnightdust.yaytris.game.Tetromino; import eu.midnightdust.yaytris.ui.ScoreMenu; import eu.midnightdust.yaytris.ui.TetrisUI; import eu.midnightdust.yaytris.util.GravityTimerTask; import eu.midnightdust.yaytris.util.sound.SoundUtil; import java.time.LocalTime; import java.util.Random; import java.util.Timer; import java.util.TimerTask; public class Tetris { public static final Random random = new Random(); private static Space space; private static Timer timer; private static TetrisUI ui; private static TimerTask gravityTask; private static LocalTime startTime; public static void init() { Settings.load(); Translation.load(Settings.language.locale); HighScores.load(); Tetris.timer = new Timer("Tetris falling pieces"); Tetris.space = new Space(); Tetris.ui = new TetrisUI(); } /** * Get the active game space * * @see Space */ public static Space getSpace() { return space; } /** * Get the ui instance * * @see TetrisUI */ public static TetrisUI getUi() { return ui; } /** * Resets the game space, preparing it for a new game. * * @see Space */ public static void resetSpace() { SoundUtil.stopMusic("/music/theme.wav"); if (gravityTask != null) gravityTask.cancel(); timer.purge(); space = new Space(); } /** * Starts a new game of Tetris :D * This involves starting our gravity task, playing music and spawning the first {@link Tetromino} * * @see Space#spawnTetromino() */ public static void startGame() { SoundUtil.playMusic("/music/theme.wav", true); space.spawnTetromino(); startTime = LocalTime.now(); gravityTask = new GravityTimerTask(); timer.scheduleAtFixedRate(gravityTask, 1, Settings.difficulty.getTimerPeriod()); } /** * Stops the current game. * Disables falling, fades out music and handles saving of high scores. * * @see ScoreMenu * @see HighScores */ public static void stopGame() { SoundUtil.stopMusic("/music/theme.wav"); if (gravityTask != null) gravityTask.cancel(); timer.purge(); if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).gameOver(); ui.transferFocus(); if (HighScores.diffToMap(Settings.difficulty).values().stream().noneMatch(hs -> hs > space.getScore())) ui.showHighscoreDialog(space.getScore()); } /** * Updates the displayed score * * @param score the new score * @see ScoreMenu */ public static void updateScore(int score) { if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateScore(score); updateLevel(score); } /** * Updates the elapsed time * * @see ScoreMenu */ public static void updateTime() { if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateTime(startTime); } /** * Updates the displayed level * * @param score the new score, from which the level will be calculated * @see ScoreMenu */ public static void updateLevel(int score) { int newLevel = Math.max(0, (int) (score / 1400f)); if (newLevel != space.level) { if (gravityTask != null && Settings.shouldScaleSpeed) { gravityTask.cancel(); gravityTask = new GravityTimerTask(); timer.scheduleAtFixedRate(gravityTask, 0, Math.max(10, Settings.difficulty.getTimerPeriod() - (Settings.difficulty.getTimerPeriod() / 16) * newLevel)); } space.level = newLevel; if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateLevel(newLevel); } } }