From e6fb6cc1ba478d7f89df9f968306e639df2f8df1 Mon Sep 17 00:00:00 2001
From: Nao Pross <naopross@thearcway.org>
Date: Mon, 19 Nov 2018 12:05:03 +0100
Subject: Set up CardLayout for GameWindow and Scene pause/resume

---
 src/BattleScene.java    |  2 +-
 src/GameWindow.java     | 96 +++++++++++++++++++++++++++++++++++--------------
 src/MapEditorScene.java |  2 +-
 src/Scene.java          | 69 +++++++++++++++++++++++++++++------
 4 files changed, 130 insertions(+), 39 deletions(-)

(limited to 'src')

diff --git a/src/BattleScene.java b/src/BattleScene.java
index df691ea..443d452 100644
--- a/src/BattleScene.java
+++ b/src/BattleScene.java
@@ -149,7 +149,7 @@ public class BattleScene extends MapScene {
 	}
 
 	@Override
-	protected void update(int deltaTime) {
+	protected void update(long deltaNanoTime) {
 		ArrayList<Actor> actorsToRemove = new ArrayList<>();
 		int enemyCounter = 0;
 	
diff --git a/src/GameWindow.java b/src/GameWindow.java
index d1afad4..a908a0a 100644
--- a/src/GameWindow.java
+++ b/src/GameWindow.java
@@ -2,6 +2,8 @@
 
 import java.awt.Dimension;
 import java.awt.GridLayout;
+import java.awt.CardLayout;
+import java.awt.BorderLayout;
 
 import javax.swing.JFrame;
 import javax.swing.JPanel;
@@ -10,10 +12,17 @@ import javax.swing.JButton;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
+
 public class GameWindow extends JFrame implements ActionListener {
 	public static final Dimension WINDOW_SIZE = new Dimension(600, 400);
 
-	private JPanel menu;
+	public final String MENU_CARD = "menu";
+	public final String SCENE_CARD = "scene";
+
+	private JPanel root;
+
+	private Scene scene = null;
+	private Thread sceneThread = null;
 
 	// TODO: remove map editor, start directly on Battle mode
 	public GameWindow() {
@@ -24,28 +33,78 @@ public class GameWindow extends JFrame implements ActionListener {
 		this.setPreferredSize(WINDOW_SIZE);
 		this.setLocationRelativeTo(null);
 
+		this.initComponents();
+
+		this.add(this.root, BorderLayout.CENTER);
+		this.pack();
+		this.setVisible(true);
+	}
+
+	private void initComponents() {
+		// set up a cardlayout
+		this.root = new JPanel(new CardLayout());
+
+		// build Menu card
 		JPanel menu = new JPanel();
 		menu.setLayout(new GridLayout(3, 1));
+
 		JButton editor = new JButton("Editor");
 		editor.setActionCommand("btn-editor");
+		editor.addActionListener(this);
+
 		JButton battle = new JButton("Battle");
 		battle.setActionCommand("btn-battle");
+		battle.addActionListener(this);
+
 		JButton exit = new JButton("Exit");
 		exit.setActionCommand("btn-exit");
-
-		editor.addActionListener(this);
-		battle.addActionListener(this);
 		exit.addActionListener(this);
 		
 		menu.add(editor);
 		menu.add(battle);
 		menu.add(exit);
 
-		this.menu = menu;
+		// add cards
+		this.root.add(menu, MENU_CARD);
+	}
 
-		this.add(this.menu);
-		this.pack();
-		this.setVisible(true);
+	public void showScene(Scene scene) {
+		// the current scene is already open
+		if (scene == this.scene) {
+			((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD);
+			scene.updateCanvasSize();
+			scene.resume();
+
+			return;
+		}
+
+		// if there is an old scene
+		if (this.scene != null) {
+			// close old scene
+			this.scene.stop();
+			try {
+				this.sceneThread.join();
+			} catch (InterruptedException ex) {
+				ex.printStackTrace();
+			}
+		}
+
+		// build new thread
+		this.scene = scene;
+		this.sceneThread = new Thread(this.scene);
+
+		// add to layout
+		this.root.add(scene, SCENE_CARD);
+		((CardLayout)this.root.getLayout()).show(this.root, SCENE_CARD);
+
+		this.sceneThread.start();
+		scene.updateCanvasSize();
+		scene.resume();
+	}
+
+	public void showMenu() {
+		this.scene.pause();
+		((CardLayout)this.root.getLayout()).show(this, MENU_CARD);
 	}
 
 	@Override
@@ -65,26 +124,9 @@ public class GameWindow extends JFrame implements ActionListener {
 				scene = new BattleScene();
 			}
 
-			if (scene == null) {
-				return;
+			if (scene != null) {
+				showScene(scene);
 			}
-
-			this.getContentPane().removeAll();
-			this.getContentPane().invalidate();
-			this.getContentPane().add(scene);
-			this.getContentPane().revalidate();
-
-			scene.updateCanvasSize();
-
-			Thread sceneThread = new Thread(scene);
-			sceneThread.start();
 		}
 	}
-
-	public void backToMenu() {
-		this.getContentPane().removeAll();
-		this.getContentPane().invalidate();
-		this.getContentPane().add(this.menu);
-		this.getContentPane().revalidate();
-	}
 }
diff --git a/src/MapEditorScene.java b/src/MapEditorScene.java
index 4a42951..5f6bda5 100644
--- a/src/MapEditorScene.java
+++ b/src/MapEditorScene.java
@@ -69,7 +69,7 @@ public class MapEditorScene extends MapScene {
 	}
 
 	@Override
-	protected void update(int deltaTime) {}
+	protected void update(long deltaNanoTime) {}
 
 	@Override
 	protected void absoluteRender(Graphics2D g2d) {}
diff --git a/src/Scene.java b/src/Scene.java
index d8c826e..0ecf22f 100644
--- a/src/Scene.java
+++ b/src/Scene.java
@@ -15,24 +15,29 @@ import java.awt.image.BufferStrategy;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
 
-// TODO: implement pause (rendering) function
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+
 public abstract class Scene extends JPanel
-	implements Runnable, KeyListener, MouseListener,
-				MouseMotionListener, MouseWheelListener {
+	implements Runnable, KeyListener, MouseListener, MouseMotionListener, 
+				MouseWheelListener, ComponentListener {
 	
 	protected final long DESIRED_FPS = 60;
 	protected final long DESIRED_DELTA_LOOP = (1000*1000*1000)/DESIRED_FPS;
 
-	protected BufferStrategy buffer;
+	protected boolean running;
+	protected boolean paused;
+	protected Object pauseLock;
 
+	protected BufferStrategy buffer;
 	protected Dimension canvasSize;
-	protected boolean running;
 	protected Canvas canvas;
 
 	// TODO: make accessible from user settings
 	protected int guiSize = 2;
 
 	protected Scene() {
+
 		this.canvasSize = GameWindow.WINDOW_SIZE;
 		this.canvas = new Canvas();	
 
@@ -45,7 +50,7 @@ public abstract class Scene extends JPanel
 		this.canvas.addMouseWheelListener(this);
 	}
 
-	public void initCanvasBuffer() {
+	private void initCanvasBuffer() {
 		this.canvas.createBufferStrategy(2);
 		this.buffer = this.canvas.getBufferStrategy();
 
@@ -62,15 +67,29 @@ public abstract class Scene extends JPanel
 		this.initCanvasBuffer();
 
 		this.running = true;
+		this.paused = false;
+		pauseLock = new Object();
 
 		while (running) {
 			beginLoopTime = System.nanoTime();
 
+			synchronized (this.pauseLock) {
+				if (this.paused) {
+					try {
+						this.pauseLock.wait();
+					} catch (InterruptedException ex) {
+						ex.printStackTrace();
+						break;
+					}
+				}
+			}
+
 			this.render();
 
 			lastUpdateTime = currentUpdateTime;
 			currentUpdateTime = System.nanoTime();
-			this.update((int) ((currentUpdateTime - lastUpdateTime)/(1000*1000)));
+
+			this.update(currentUpdateTime - lastUpdateTime);
 
 			endLoopTime = System.nanoTime();
 			deltaLoop = endLoopTime - beginLoopTime;
@@ -87,22 +106,43 @@ public abstract class Scene extends JPanel
 		}
 	}
 
+	public synchronized void stop() {
+		this.running = false;
+
+		// stop thread even if paused
+		this.resume();
+	}
+
+	public synchronized void pause() {
+		this.paused = true;
+	}
+
+	public synchronized void resume() {
+		if (!paused)
+			return;
+		
+		this.paused = false;
+		this.pauseLock.notifyAll();
+	}
+
 	// automagically set the canvas size to the parent's size
-	public void updateCanvasSize() {
+	public synchronized void updateCanvasSize() {
 		this.canvasSize = this.getParent().getSize();
 	}
 
-	public void setCanvasSize(Dimension newSize) {
+	public synchronized void setCanvasSize(Dimension newSize) {
 		this.canvasSize = newSize;
 	}
 
 	protected abstract void render();
-	protected abstract void update(int deltaNanoTime);
+	protected abstract void update(long deltaNanoTime);
 
 	@Override
 	public void keyTyped(KeyEvent e) {}
 	public void keyPressed(KeyEvent e) {}
 	public void keyReleased(KeyEvent e) {}
+
+	@Override
 	public void mouseClicked(MouseEvent e) {}
 	public void mouseEntered(MouseEvent e) {}
 	public void mouseExited(MouseEvent e) {}
@@ -112,4 +152,13 @@ public abstract class Scene extends JPanel
 	public void mouseMoved(MouseEvent e) {}
 	public void mouseWheelMoved(MouseWheelEvent e) {}
 
+	@Override
+	public void componentResized(ComponentEvent e) {
+		this.updateCanvasSize();
+	}
+
+	public void componentMoved(ComponentEvent e) {}
+	public void componentShown(ComponentEvent e) {}
+	public void componentHidden(ComponentEvent e) {}
+
 }
-- 
cgit v1.2.1