/*
Source file: SimForestFrame.java
Author: Markus Bautsch
Licence: public domain
Date: 31 October 2022
Version: 1.1
Programming language: Java
*/
/*
Graphische aktualisierte Ausgabe von Rechtecken
*/
public final class SimForestFrame extends javax.swing.JFrame implements java.awt.event.ActionListener
{
// serialVersionUID fuer die Serialisation, die in der Klasse javax.swing.JFrame implementiert ist
private final static long serialVersionUID = 1L;
// Klassenkonstanten
final private static int [] SoilColour = {64, 32, 0};
final private static int [] TreeColour = {0, 255, 0};
final private static int [] FireColour = {255, 0, 0};
final private static int [] WaterColour = {0, 0, 255};
final private static java.lang.String title = "Forest Fire";
final private static int offset = 10;
final private static int offsetTop = 30;
final private static int fireDelay = 1; // Verzögerung während eines Wandbrands in Millisekunden
final private static int annualDelay = 500; // Verzoegerung nach einem simulierten Jahr in Millisekunden
// Instanzvariablen
private int sizeX = 200;
private int sizeY = 200;
private long currentYear = 0;
private long numberOfYears = 1;
private boolean forestIsBurning = false;
private SimForestModel model;
private java.awt.image.BufferedImage bufferedImage;
private java.awt.image.WritableRaster imageRaster;
private javax.swing.Timer timer = new javax.swing.Timer (annualDelay, this); // Fuer die Anzeige des JFrames mit Verzoegerung
/* Konstruktor fuer die Initialisierung von Instanzen der Klasse SimForestFrame
* @param x: Fuer die horizontale Groesse in Pixeln
* @param y: Fuer die vertikale Groesse in Pixeln
* @param count: Fuer die Anzahl der Simulationsdurchlaeufe in Jahren
*/
public SimForestFrame (int x, int y, long count)
{
super (title);
this.model = new SimForestModel (x, y);
this.sizeX = x;
this.sizeY = y;
this.numberOfYears = count;
// Rahmengroesse, Hintergrund und das Layout werden gesetzt
this.setSize (this.sizeX + 2 * offset, this.sizeY + 2 * offset + offsetTop);
this.setBackground (java.awt.Color.BLACK);
this.bufferedImage = new java.awt.image.BufferedImage (this.sizeX, this.sizeY, java.awt.image.BufferedImage.TYPE_INT_RGB);
this.imageRaster = bufferedImage.getWritableTile (0, 0);
this.setDefaultCloseOperation (javax.swing.WindowConstants.EXIT_ON_CLOSE);
}
/*
* Gibt das Simulationsmodell der Klasse SimForestModel vom SimForestFrame zurueck
*/
public SimForestModel getModel ()
{
return model;
}
/*
* Standard-Methode paint zum Zeichnen des Rechtecks mit dem Waldboden
*/
public void paint (java.awt.Graphics graphics)
{
for (int y = 0; y < sizeY; y++)
{
for (int x = 0; x < sizeX; x++)
{
long groundState = model.getGroundState (x, y);
if (groundState == SimForestModel.SOIL)
{
imageRaster.setPixel (x, y, SoilColour);
}
else if (groundState == SimForestModel.TREE)
{
imageRaster.setPixel (x, y, TreeColour);
}
else if (groundState == SimForestModel.WATER)
{
imageRaster.setPixel (x, y, WaterColour);
}
else if (groundState == SimForestModel.FIRE)
{
imageRaster.setPixel (x, y, FireColour);
}
}
}
graphics.drawImage (bufferedImage, offset, offset + offsetTop, null);
java.awt.Toolkit.getDefaultToolkit ().sync (); // Dieser Methodenaufruf stellt sicher, dass die Ausgabe vollständig aktualisiert ist
}
/*
* Methode fuer die Initialisierung einer Instanz von SimForestFrame
*/
public void init ()
{
java.awt.Graphics2D graphics2D = bufferedImage.createGraphics ();
this.timer.start ();
this.paint (graphics2D);
this.setVisible (true);
this.setAlwaysOnTop (true);
}
/*
* Ueberschriebene Standard-Methode actionPerformed fuer die synchronisierte Aktualisierung einer Instanz SimForestFrame
*/
public void actionPerformed (java.awt.event.ActionEvent event)
{
long numberOfTreesBurning = 0;
if (forestIsBurning)
{
numberOfTreesBurning = model.simulateBurning ();
forestIsBurning = (numberOfTreesBurning > 0);
if (forestIsBurning)
{
timer.setDelay (fireDelay);
}
else
{
timer.setDelay (annualDelay);
}
}
else if (currentYear < numberOfYears)
{
currentYear++;
forestIsBurning = model.simulateYear ();
}
else
{
timer.stop ();
}
java.lang.String currentTitel = title + " / year " + currentYear + " / " + " burning trees = " + numberOfTreesBurning;
setTitle (currentTitel);
repaint ();
}
}