cicaprojekt/cicaprojekt/Game.java

426 lines
14 KiB
Java

package cicaprojekt;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;
/**
* Egy játékmenetet reprezentáló oszály.
*/
public class Game {
/**
* Az egyik játékos, O'Neill ezredes tárolása.
*/
private Player oneill = null;
/**
* A másik játékos, Jaffa tárolása.
*/
private Player jaffa = null;
/**
* A Replikátor tárolása.
*/
private PlayerBase replicator = null;
/**
* Az aktuális útvesztő tárolása.
*/
private Dungeon dungeon;
/**
* A játékidő tárolása.
*/
private FlowOfTime flowoftime;
/**
* A megjelenítési felület tárolása.
*/
private Display display;
/**
* Egy játékpéldány.
*/
public static Game instance = new Game();
/**
* Az osztály konstruktora.
*/
private Game() {}
/**
* A Replikátor megsemmisítését implementáló függvény.
* Ha a Replikátor úgy semmisült meg, hogy szakadékba esett, akkor
* a szakadék helyét egy mező veszi át.
*
* @param caller a megsemmisülő Replikátor
* @see Tile#setX(int)
* @see Tile#setY(int)
* @see Tile#setAdajacentTile(Tile, Direction)
* @see Tile#getAdjacentTile(Direction)
* @see Display#gapMagic(Gap, Field, int)
*/
public void playerBaseDestroyed(PlayerBase caller) {
if (caller.getCurrentTile().isGap()) {
Field field = new Field();
Tile callertile = caller.getCurrentTile();
field.setX(callertile.getX());
field.setY(callertile.getY());
field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.NORTH), Direction.NORTH);
callertile.getAdjacentTile(Direction.NORTH).setAdajacentTile(field, Direction.SOUTH);
field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.SOUTH), Direction.SOUTH);
callertile.getAdjacentTile(Direction.SOUTH).setAdajacentTile(field, Direction.NORTH);
field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.WEST), Direction.WEST);
callertile.getAdjacentTile(Direction.WEST).setAdajacentTile(field, Direction.EAST);
field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.EAST), Direction.EAST);
callertile.getAdjacentTile(Direction.EAST).setAdajacentTile(field, Direction.WEST);
display.gapMagic((Gap) callertile, field, dungeon.getMapWidth());
Game.instance.updateDisplay();
}
}
/**
* Egy játékos megsemmisítését implementáló függvény. Csökkenti a játék
* teljesítéséhez szükséges ZPM-ek számát a megsemmisülő általá
* összegyűjtött ZPM-ekkel, majd frissíti a megjelenítést.
* Ha mindkét játékos halott, akkor a játék véget ér Anubis győzelmével.
*
* @param caller a megsemmisülő játékos
* @see #updateDisplay()
* @see FlowOfTime#stopTime()
* @see #stopGame(GameoverCause)
*/
public void playerDestroyed(Player caller) {
dungeon.setZPMsToWin(dungeon.getZPMsToWin() - caller.getZPMCount());
Game.instance.updateDisplay();
if (jaffa.isDestroyed() && oneill.isDestroyed()) {
flowoftime.stopTime();
stopGame(GameoverCause.ANUBIS);
}
}
/**
* Beállítja az aktuális útvesztőt a kapott útvesztőre.
*
* @param dungeon kapott útvesztő
*/
public void setDungeon(Dungeon dungeon) {
this.dungeon = dungeon;
}
/**
* Beállítja az akutális megjelenítést a kapott megjelenítésre.
*
* @param display kapott megjelenítés
*/
public void setDisplay(Display display) {
this.display = display;
}
/**
* Elindítja a játékot a kapott útvesztőt tartalmazó fájl alapján.
* Inicializálja a csillagkapukat, felépíti az útvesztőt, létrehozza
* a játékosokat és a Replikátort, valamint beállítja a megjelenítést.
* Elindítja a zenét, majd a játékidőt is.
*
* @param dungeonFile kapott útvesztő
* @throws IOException Ha nem található a fájl.
* @see Stargate#init()
* @see Dungeon#buildDungeon(File, Display)
* @see Display#addVisual(Drawer)
* @see Display#startMusic()
* @see FlowOfTime#start(long)
*/
public void startGame(File dungeonFile) throws IOException {
Stargate.init();
Map<String, Tile> players = dungeon.buildDungeon(dungeonFile, display);
oneill = new Player("O'Neill", players.get("oneill"), Direction.getRandom());
jaffa = new Player("Jaffa", players.get("jaffa"), Direction.getRandom());
replicator = new PlayerBase("Replicator", players.get("replicator"), Direction.getRandom());
display.setMapSize(dungeon.getMapWidth(), dungeon.getMapHeight());
display.addVisual(new PlayerDrawer(oneill));
display.addVisual(new PlayerDrawer(jaffa));
display.addVisual(new PlayerBaseDrawer(replicator));
display.startMusic();
flowoftime = new FlowOfTime();
flowoftime.start(dungeon.getTimeLimit());
}
/**
* A játék megállítása valamilyen kapott okból. Az oknak megfelelően
* más és más befejezése van a játéknak. Végül a zene leállítása.
*
* @param cause a leállítás oka
* @see Display#stopMusic()
*/
public void stopGame(GameoverCause cause) {
switch (cause){
case TIMEOUT:
JOptionPane.showMessageDialog(null, "Time is up! Anubis has enslaved the world by now.",
"Game over",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("Anubis.png"));
Application.frameInstance.backToMapSelection();
break;
case ONEILLWON:
JOptionPane.showMessageDialog(null, "Colonel O'Neill won!", "Game over",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("Deal_with_iit.png"));
Application.frameInstance.backToMapSelection();
break;
case JAFFAWON:
JOptionPane.showMessageDialog(null, "Jaffa won!", "Game over",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("Deal_with_iit.png"));
Application.frameInstance.backToMapSelection();
break;
case DRAW:
JOptionPane.showMessageDialog(null, "Draw! While O'Neill and the Jaffa struggled against eachother, Anubis has enslaved the world.",
"Game over",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("Anubis.png"));
Application.frameInstance.backToMapSelection();
break;
case ANUBIS:
JOptionPane.showMessageDialog(null, "There is no one left to stop Anubis from enslaving the world",
"Game over",
JOptionPane.INFORMATION_MESSAGE,
new ImageIcon("Anubis.png"));
Application.frameInstance.backToMapSelection();
break;
}
display.stopMusic();
}
/**
* O'Neill ezredes léptetése a kapott irányba.
*
* @param direction kapott irány
* @see Player#move(Direction)
* @see #checkZPMStatus()
*/
public void moveONeill(Direction direction) {
oneill.move(direction);
checkZPMStatus();
}
/**
* Jaffa léptetése a kapott irányba.
*
* @param direction kapott irány
* @see Player#move(Direction)
* @see #checkZPMStatus()
*/
public void moveJaffa(Direction direction) {
jaffa.move(direction);
checkZPMStatus();
}
/**
* A Replikátor léptetése a kapott irányba.
*
* @param direction kapott irány
* @see PlayerBase#move(Direction)
*/
public void moveReplicator(Direction direction) {
replicator.move(direction);
}
/**
* O'Neill ezredes forgatása balra.
*
* @see Player#rotateLeft()
*/
public void rotateOneillLeft() {
oneill.rotateLeft();
}
/**
* O'Neill ezredes forgatása jobbra.
*
* @see Player#rotateRight()
*/
public void rotateOneillRight() {
oneill.rotateRight();
}
/**
* Jaffa forgatása balra.
*
* @see Player#rotateLeft()
*/
public void rotateJaffaLeft() {
jaffa.rotateLeft();
}
/**
* Jaffa forgatása jobbra.
*
* @see Player#rotateRight()
*/
public void rotateJaffaRight() {
jaffa.rotateRight();
}
/**
* O'Neill ezredes dobozainak kezelése.
*
* @see Player#hasBox()
* @see Player#boxDrop()
* @see Player#boxLift()
*/
public void boxONeill() {
if(oneill.hasBox())
oneill.boxDrop();
else
oneill.boxLift();
}
/**
* Jaffa dobozainak kezelése.
*
* @see Player#hasBox()
* @see Player#boxDrop()
* @see Player#boxLift()
*/
public void boxJaffa() {
if(jaffa.hasBox())
jaffa.boxDrop();
else
jaffa.boxLift();
}
/**
* Csillagkapu lövését implementáló függvény.
* Ha a kilőtt csillagkapu sárga vagy kék, akkor O'Neill
* ezredeshez tartozik, egyébként Jaffához.
*
* @param color a csillagkapu színe
*/
public void shootStargate(Color color) {
if(color == Color.YELLOW || color == Color.BLUE)
oneill.shootStargate(Stargate.get(color));
else
jaffa.shootStargate(Stargate.get(color));
}
/**
* A megjelenítő panel frissítése, újrarajzolása.
*
* @see Control#ioErrorMessage()
*/
public void updateDisplay() {
try {
display.drawVisuals();
display.repaint();
}
catch (IOException e) {
Control.ioErrorMessage();
}
}
/**
* A ZPM-ek állapotának ellenőrzése. Ha O'Neill ezredes és Jaffa összesen
* összegyűjtöttek annyi ZPM-et, amennyi szükséges a játék megnyeréséhez,
* akkor az fog nyerni, aki több ZPM-et gyűjtött, egyébként veszítettek.
* A játékidő leállítódik és a játék véget ér.
*
* @see Player#getZPMCount()
* @see FlowOfTime#stopTime()
* @see #stopGame(GameoverCause)
*/
private void checkZPMStatus() {
if (oneill.getZPMCount() + jaffa.getZPMCount() >= dungeon.getZPMsToWin()) {
if (oneill.getZPMCount() > jaffa.getZPMCount()) {
flowoftime.stopTime();
stopGame(GameoverCause.ONEILLWON);
}
else if (oneill.getZPMCount() < jaffa.getZPMCount()) {
flowoftime.stopTime();
stopGame(GameoverCause.JAFFAWON);
}
else {
flowoftime.stopTime();
stopGame(GameoverCause.DRAW);
}
return;
}
if (oneill.getZPMCount() >= dungeon.getZPMsToWin())
{
flowoftime.stopTime();
stopGame(GameoverCause.ONEILLWON);
}
else if (jaffa.getZPMCount() >= dungeon.getZPMsToWin())
{
flowoftime.stopTime();
stopGame(GameoverCause.JAFFAWON);
}
}
/**
* A ZPM-ek véletlenszerű generálását implementáló függvény. A függvény addig
* iterál, amíg nem talál alkalmas helyet egy új ZPM-nek. Ha ezt megtalálta,
* akkor létrehoz oda egy új ZPM-et, majd megnöveli a játékban való győzelemhez
* szükséges ZPM-ek számát.
*
* @see Tile#setZPMOnTile(ZPM)
* @see Dungeon#setZPMsToWin(int)
*/
public void generateZPM() {
if(((jaffa.getZPMCount() + oneill.getZPMCount()) % 2) == 0) {
Tile source = oneill.getCurrentTile();
Tile compare;
for (int i = 0; i < dungeon.getMapHeight(); i++) {
compare = source.getAdjacentTile(Direction.getRandom());
if (compare != null)
source = compare;
}
while (!source.canHazZPM() || source.hasZPM()) {
int newSourceCounter = 0;
for (int i = 0; i < dungeon.getMapHeight(); i++) {
compare = source.getAdjacentTile(Direction.getRandom());
if (compare != null)
source = compare;
}
while(newSourceCounter != 20) {
compare = source.getAdjacentTile(Direction.getRandom());
if (compare != null) {
source = compare;
if (!compare.hasZPM() && (compare.playerBaseOnTile == null)) {
if (source.canHazZPM() && !source.hasZPM()) {
break;
}
}
}
newSourceCounter++;
}
}
source.setZPMOnTile(new ZPM());
dungeon.setZPMsToWin(dungeon.getZPMsToWin()+1);
}
}
}