package game.model;
import beans.core.Core;
import beans.serializable.EventBloc;
import beans.enumeration.EventBlocType;
import beans.core.GeneralConstant;
import beans.serializable.MapConfig;
import beans.serializable.Objet;
import game.core.Collision;
import game.core.event.Event;
import game.core.event.GameEvent;
import game.core.MessagePropertie;
import game.core.event.InventoryEvent;
import game.entity.Player;
import game.model.dialog.Message;
import game.model.fight.FightModel;
import game.view.PlayScreen;
import game.view.fight.FightView;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
/**
* Classe principal qui gére le déroulement du jeu
*
* @author mastersnes
*/
public class GameModel extends Observable {
// TODO : fusioner les deux lists
private Map<Integer, BufferedImage> mapCouches = new HashMap<Integer, BufferedImage>();
private MapConfig config;
private int camx, camy;
private final Player player;
private final GUIModel guiModel;
private boolean inventoryIsDisplayed;
// Flag pour indiquer si le combat est lancé
private boolean fightIsDisplayed = false;
private final Map<Point, EventBloc> autoEvent = new HashMap<Point, EventBloc>();
private final Map<Point, EventBloc> manualEvent = new HashMap<Point, EventBloc>();
private final List<Message> messageBuffer = new ArrayList<Message>();
/**
*
* @param guiModel
* @param map
*/
public GameModel(final GUIModel guiModel, final String map) {
super();
this.guiModel = guiModel;
player = new Player(this, guiModel);
player.initInventory();
Event.setGameEvent(new GameEvent(this));
player.setMotion(50, 50);
final List<Message> messagesDebut = MessagePropertie.getMessage(map);
if (messagesDebut != null) {
messageBuffer.addAll(messagesDebut);
}
mapCouches = Core.loadCouche(map);
reajustColisionPane();
config = (MapConfig) GeneralConstant.deSerialize(GeneralConstant.SAVE_MAPCONFIG_PATH + map);
for (final Entry<Point, EventBloc> event : config.getEvent().entrySet()) {
if (event.getValue().isPlayerPosition()) {
teleport(event.getKey().x * GeneralConstant.BLOC_WIDTH, event.getKey().y * GeneralConstant.BLOC_HEIGHT);
} else if (event.getValue().isAutomatique()) {
autoEvent.put(event.getKey(), event.getValue());
} else {
manualEvent.put(event.getKey(), event.getValue());
}
if (event.getValue().isColisionOn()) {
addColision(event.getKey(), GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
}
}
camx = 0;
camy = 0;
final PlayScreen playScreen = new PlayScreen(guiModel, this);
guiModel.setScreen(playScreen);
}
/**
*
* @return
*/
public Player getPlayer() {
return player;
}
/**
*
* @param x
* @param y
*/
public void moveMap(final int x, final int y) {
if (inventoryIsDisplayed) {
return;
}
if (Collision.isInCollision(mapCouches.get(GeneralConstant.COLISION_NUM), player, x, y)) {
return;
}
if (player.getRelativeX() > GeneralConstant.TAILLE_ECRAN_X / 2) {
player.incrementeAbsoluteX(x);
setCamx(getCamx() + x);
} else {
player.incrementeAbsoluteX(x);
player.incrementeRelativeX(x);
}
if (player.getRelativeY() > GeneralConstant.TAILLE_ECRAN_Y / 2) {
player.incrementeAbsoluteY(y);
setCamy(getCamy() + y);
} else {
player.incrementeAbsoluteY(y);
player.incrementeRelativeY(y);
}
if (getCamx() < 0 && player.getRelativeX() > 0) {
setCamx(0);
player.incrementeAbsoluteX(x);
player.incrementeRelativeX(x);
}
if (getCamy() < 0 && player.getRelativeY() > 0) {
setCamy(0);
player.incrementeAbsoluteY(y);
player.incrementeRelativeY(y);
}
setCamx((getCamx() < 0) ? 0 : getCamx());
setCamy((getCamy() < 0) ? 0 : getCamy());
calculeMonster();
final int tempX = (int) ((float) player.getX() / Float.parseFloat(String.valueOf(GeneralConstant.BLOC_WIDTH))) + 1;
final int tempY = (int) ((float) player.getY() / Float.parseFloat(String.valueOf(GeneralConstant.BLOC_HEIGHT))) + 1;
final Point playerPosition = new Point(tempX, tempY);
final Point ancientPosition = player.getAncientBloc();
if (!playerPosition.equals(ancientPosition)) {
executeEvent(autoEvent.get(playerPosition), playerPosition);
}
player.setAncientBloc(playerPosition);
player.walk();
setChanged();
notifyObservers();
}
/**
*
* @param x
* @param y
*/
public void teleport(final int x, final int y) {
if (inventoryIsDisplayed) {
return;
}
player.setAbsoluteX(x);
player.setRelativeX((GeneralConstant.TAILLE_ECRAN_X / 2) + player.getSpeed());
setCamx(x - (GeneralConstant.TAILLE_ECRAN_X / 2));
player.setAbsoluteY(y);
player.setRelativeY((GeneralConstant.TAILLE_ECRAN_Y / 2) + player.getSpeed());
setCamy(y - (GeneralConstant.TAILLE_ECRAN_Y / 2));
if (getCamx() < 0 && player.getRelativeX() > 0) {
setCamx(0);
player.setAbsoluteX(x);
player.setRelativeX(x);
}
if (getCamy() < 0 && player.getRelativeY() > 0) {
setCamy(0);
player.setAbsoluteY(y);
player.setRelativeY(y);
}
setCamx((getCamx() < 0) ? 0 : getCamx());
setCamy((getCamy() < 0) ? 0 : getCamy());
messageBuffer.addAll(MessagePropertie.getMessage("teleport"));
setChanged();
notifyObservers();
}
/**
*
* @param position
*/
public void setPlayerPosition(final int position) {
player.setOrientation(position);
}
/**
*
* @param x
* @param y
*/
public void setPlayerMotion(final int x, final int y) {
player.setMotion(x, y);
}
/**
*
*/
public void stop() {
guiModel.dispose();
}
/**
*
* @return
*/
public boolean isInventory() {
return inventoryIsDisplayed;
}
/**
* Indique si le combat est lancé.
*
* @return
* <code>true<code> si le combat est lancé,
* <code>false</code> sinon.
*/
public boolean isFight() {
return fightIsDisplayed;
}
/**
*
*/
public void EnterRequest() {
boolean nochange = true;
final int tempX = (int) ((float) player.getX() / Float.parseFloat(String.valueOf(GeneralConstant.BLOC_WIDTH))) + 1;
final int tempY = (int) ((float) player.getY() / Float.parseFloat(String.valueOf(GeneralConstant.BLOC_HEIGHT))) + 1;
final Point playerPosition = new Point(tempX, tempY);
final EventBloc event;
final Point eventPosition;
switch (player.getOrientation()) {
case 0:
eventPosition = new Point(tempX, tempY);
event = manualEvent.get(new Point(tempX, tempY));
break;
case 1:
eventPosition = new Point(tempX + 1, tempY);
event = manualEvent.get(new Point(tempX + 1, tempY));
break;
case 2:
eventPosition = new Point(tempX, tempY + 2);
event = manualEvent.get(new Point(tempX, tempY + 2));
break;
case 3:
eventPosition = new Point(tempX - 1, tempY);
event = manualEvent.get(new Point(tempX - 1, tempY));
break;
default:
eventPosition = null;
event = null;
break;
}
if (event != null && event.getCurrentMode() == EventBlocType.ON) {
for (Objet objet : event.getContent()) {
player.addObjet(objet, 1);
}
messageBuffer.addAll(MessagePropertie.getMessage("potion"));
if (event.isColisionOff()) {
addColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
} else {
removeColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
}
nochange = false;
event.setCurrentMode(EventBlocType.OFF);
} else if (event != null && event.getCurrentMode() == EventBlocType.OFF && event.isCyclique()) {
if (event.isColisionOn()) {
addColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
} else {
removeColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
}
event.setCurrentMode(EventBlocType.ON);
}
if (nochange) {
if (!messageBuffer.isEmpty()) {
messageBuffer.remove(0);
}
}
setChanged();
notifyObservers();
}
/**
* Calcule la probabilité de rencontrer un monstre
*/
private void calculeMonster() {
double a = Math.random();
if (a >= 0.2 && a < 0.3) {
//switchFight();
}
}
/**
* Change d'ecran vers l'ecran d'inventaire ou reviens sur l'ecran de jeu
*/
public void switchInventory() {
this.inventoryIsDisplayed = !inventoryIsDisplayed;
if (inventoryIsDisplayed) {
Event.setInventoryEvent(new InventoryEvent(player.getInventory()));
player.getInventory().reset();
} else {
Event.setGameEvent(new GameEvent(this));
}
setChanged();
notifyObservers();
}
/**
* @return the camx
*/
public int getCamx() {
return camx;
}
/**
* @param camx the camx to set
*/
public void setCamx(final int camx) {
this.camx = camx;
}
/**
* @return the camy
*/
public int getCamy() {
return camy;
}
/**
* @param camy the camy to set
*/
public void setCamy(final int camy) {
this.camy = camy;
}
/**
*
* @param couche
*/
public void setCouches(final Map<Integer, BufferedImage> couche) {
mapCouches = couche;
}
/**
*
* @return
*/
public Map<Integer, BufferedImage> getCouches() {
return mapCouches;
}
/**
*
* @return
*/
public int getWidth() {
return mapCouches.get(1).getWidth();
}
/**
*
* @return
*/
public int getHeight() {
return mapCouches.get(1).getHeight();
}
/**
* Retire la transparence de l'image de colision et lui donne la bonne
* taille Afin d'eviter toute anomalies
*/
private void reajustColisionPane() {
final BufferedImage colisionPlan = mapCouches.get(GeneralConstant.COLISION_NUM);
final BufferedImage temp = new BufferedImage(colisionPlan.getWidth(), colisionPlan.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = temp.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, temp.getWidth(), temp.getHeight());
g.drawImage(colisionPlan, 0, 0, null);
g.dispose();
mapCouches.put(GeneralConstant.COLISION_NUM, temp);
}
/**
* Execute l'evenement eventBloc et le desactive Si l'evenement est deja
* desactivé, on verifie si il est cyclique Si l'evenement est cyclique on
* execute les actions en mode OFF et on le reactive
*
* @param eventBloc
*/
private void executeEvent(final EventBloc eventBloc, final Point eventPosition) {
if (eventBloc != null) {
System.out.println("eventBloc : " + eventBloc.getId());
if (eventBloc.isAutomatique()) {
System.out.println("auto");
/**
* etape 1 : si l'evenement contient des objets on donne tout au
* joueur
*/
if (!eventBloc.getContent().isEmpty()) {
System.out.println("!empty");
for (final Objet objet : eventBloc.getContent()) {
//TODO : ajouter le nombre par la suite (map)
player.addObjet(objet, 1);
}
eventBloc.getContent().clear();
}
/**
* etape 2 : si l'evenement doit en activer un autre, on le
* recherche et on l'active
*/
if (eventBloc.getIdActive() != null) {
System.out.println("activation");
final String idAActiver = eventBloc.getIdActive();
for (final Entry<Point, EventBloc> entry : getConfig().getEvent().entrySet()) {
final EventBloc blocCourant = entry.getValue();
if (idAActiver.equals(blocCourant.getId())) {
executeEvent(blocCourant, entry.getKey());
}
}
}
switch (eventBloc.getCurrentMode()) {
case ON:
System.out.println("on");
/**
* etape 3 : si l'evenement doit transporter le joueur,
* on transporte a l'endroit prevu
*/
if (eventBloc.isTransporteurOn()) {
System.out.println("transport : " + eventBloc.getDestinationPointOn());
teleport(eventBloc.getDestinationPointOn().x * GeneralConstant.BLOC_WIDTH, eventBloc.getDestinationPointOn().y * GeneralConstant.BLOC_HEIGHT);
}
if (eventBloc.isColisionOff()) {
addColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
} else {
removeColision(eventPosition, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
}
eventBloc.setCurrentMode(EventBlocType.OFF);
break;
case OFF:
System.out.println("off");
if (eventBloc.isCyclique()) {
System.out.println("cycle");
/**
* etape 3 : si l'evenement doit transporter le
* joueur, on transporte a l'endroit prevu
*/
if (eventBloc.isTransporteurOff()) {
System.out.println("transport : " + eventBloc.getDestinationPointOff());
teleport(eventBloc.getDestinationPointOff().x * GeneralConstant.BLOC_WIDTH, eventBloc.getDestinationPointOff().y * GeneralConstant.BLOC_HEIGHT);
}
eventBloc.setCurrentMode(EventBlocType.ON);
}
break;
default:
break;
}
}
}
}
/**
* @return the config
*/
public MapConfig getConfig() {
return config;
}
/**
* @param config the config to set
*/
public void setConfig(final MapConfig config) {
this.config = config;
}
/**
* Renvoie la position relative de ce point
*
* @param x
* @param y
* @return
*/
public Point getRelatif(final int x, final int y) {
return new Point(x - camx, y - camy);
}
/**
* Renvoie la position relative de ce point
*
* @param point
* @return
*/
public Point getRelatif(final Point point) {
return getRelatif(point.x, point.y);
}
private void addColision(final Point origine, final int w, final int h) {
Graphics2D g = (Graphics2D) mapCouches.get(GeneralConstant.COLISION_NUM).createGraphics();
g.setColor(Color.black);
g.fillRect(origine.x * w, origine.y * h, w, h);
g.dispose();
}
private void removeColision(final Point origine, final int w, final int h) {
final Graphics2D g = (Graphics2D) mapCouches.get(GeneralConstant.COLISION_NUM).createGraphics();
//g.setComposite(AlphaComposite.Clear);
g.setColor(Color.white);
g.fillRect(origine.x * w, origine.y * h, w, h);
g.dispose();
}
/**
*
* @return
*/
public Message getLastMessage() {
if (!messageBuffer.isEmpty()) {
return messageBuffer.get(0);
} else {
return null;
}
}
/**
* Previens la vue que l'inventaire a changé
*/
public void inventoryHasChanged() {
setChanged();
notifyObservers();
}
public void launchFight() {
final FightModel fightModel = new FightModel(player.getEquipe(), new ArrayList(), new ArrayList(), new ArrayList());
final FightView fightView = new FightView(fightModel);
guiModel.setScreen(fightView);
}
}