I've been having problems getting any kind of input from the window (or anything really) after I start the game. Here's my problem:
I start off the game at the menu and add a key listener and a window listener to the window. So long as I stay in the menu, it works, but as soon as I switch to the panel that draws the game, the listeners all become unresponsive.
I thought the window removes the listeners when I remove the menu panel to replace it with the game panel, however, after I made sure to add the listeners again after the switch, it's still no go. On the other hand, if I switch to the game panel, and then make the game switch back immediately to the menu panel, the listeners all work again. I'm out of ideas at this point. I tried implementing key bindings, but that didn't help, the results were still the same.
Here are the four main classes that are involved:
Game class - drives core mechanics
package Core.Game;
import Core.Menu.MainMenu;
import Core.Menu.PauseMenu;
import Entity.EntityFactory;
import Entity.Systems.AnimationSystem;
import Entity.Systems.ControlSystem;
import Entity.Systems.DrawingSystem;
import Entity.Systems.MotionSystem;
import Graphics.GameCanvas;
import Graphics.GameWindow;
import Input.KeyManager;
import Level.Level;
import Level.LevelLoadingScript;
import Level.World;
import Menu.MenuStack;
import Util.GameTimer;
import java.awt.Color;
import java.awt.event.KeyEvent;
public class Game {
private GameWindow mWindow;
private MenuStack mMenuStack;
private boolean mPaused;
private boolean mQuit;
private EntityFactory mEntityFactory;
private Level mLevel;
private World mWorld;
private GameTimer mFrameTimer;
public Game() {
mWindow = new GameWindow("Digestion");
mEntityFactory = new EntityFactory();
mFrameTimer = new GameTimer();
mFrameTimer.setTimeInterval( (1/30)*1000 /* 33 millisecond */ );
mLevel = new Level();
mWorld = new World();
mPaused = true;
setupMenuStack();
}
private void setupMenuStack() {
mMenuStack = new MenuStack();
mWindow.switchTo(mMenuStack);
MainMenu mainMenu = new MainMenu(this, mMenuStack);
mainMenu.setBackground(Color.BLACK);
mMenuStack.pushScreen(mainMenu);
}
public void startLevel(LevelLoadingScript loadingScript) {
loadingScript.loadLevel(mLevel);
loadingScript.createEntities(mEntityFactory, mWorld);
mQuit = false;
GameCanvas canvas = new GameCanvas();
mWindow.switchTo(canvas);
execute(canvas);
}
public void pause() {
mPaused = true;
PauseMenu pauseMenu = new PauseMenu(this, mMenuStack);
pauseMenu.display();
}
public void resume() {
mPaused = false;
}
public void unpause() {
if(mLevel == null)
return;
mPaused = false;
mFrameTimer.reset();
}
private void execute(GameCanvas canvas) {
unpause();
boolean escProcessed = false;
while(!mQuit) {
if(mPaused) {
if(KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && !escProcessed) {
escProcessed = true;
resume();
}
} else {
ControlSystem.manipulate(mWorld);
MotionSystem.move(mWorld);
AnimationSystem.animate(mWorld);
if(mFrameTimer.hasTimeIntervalPassed()) {
DrawingSystem.draw(mWorld, canvas);
canvas.showCanvas();
mWindow.update();
mFrameTimer.reset();
}
if(KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && !escProcessed) {
escProcessed = true;
pause();
}
}
if(!KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && escProcessed)
escProcessed = false;
}
mPaused = true;
mWindow.switchTo(mMenuStack);
}
}
GameWindow
package Graphics;
import Core.Game.GameWindowListener;
import Input.KeyManager;
import Util.ErrorLog;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class GameWindow {
private JFrame mWindow;
private GameWindowListener mWindowListener;
private KeyManager mKeyDispatcher;
private GraphicsDevice mFullscreenDevice;
private BufferStrategy mBackBuffer;
private Component mDisplayedItem;
private boolean mFullscreen;
private int mWidth;
private int mHeight;
public GameWindow(String title) {
setupWindow(title);
loadSettings();
mWindowListener = new GameWindowListener();
mKeyDispatcher = new KeyManager();
}
private void setupWindow(String title) {
mWindow = new JFrame(title);
mWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mWindow.setVisible(true);
setupBackBuffer();
}
private void setupBackBuffer() {
mWindow.createBufferStrategy(2);
mBackBuffer = mWindow.getBufferStrategy();
}
private void loadSettings() {
mFullscreenDevice = null;
mFullscreen = false;
setSize(800, 600);
}
public void switchFullscreen() {
mFullscreen = !mFullscreen;
if(mFullscreen) {
switchToFullscreen();
} else {
switchToWindow();
}
}
private void switchToFullscreen() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
mFullscreenDevice = env.getDefaultScreenDevice();
if(mFullscreenDevice.isFullScreenSupported()) {
mFullscreenDevice.setFullScreenWindow(mWindow);
mFullscreen = true;
}
if(!mFullscreen) {
ErrorLog errorLog = ErrorLog.getInstance();
errorLog.displayMessageDialog("It seems there are no screens that support fullscreen mode.\nRemaining in Windowed mode");
}
}
private void switchToWindow() {
mFullscreenDevice.setFullScreenWindow(null);
mFullscreenDevice = null;
mFullscreen = false;
}
public boolean isFullscreen() {
return mFullscreen;
}
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
public void setSize(int width, int height) {
if(mFullscreen) {
setFullscreenSize(width, height);
} else {
setWindowedSize(width, height);
}
}
private void setFullscreenSize(int width, int height) {
mWidth = width;
mHeight = height;
mWindow.setSize(width, height);
}
private void setWindowedSize(int width, int height) {
Insets insets = mWindow.getInsets();
mWidth = width + insets.left + insets.right;
mHeight = height + insets.top + insets.bottom;
mWindow.setSize(width, height);
}
public void switchTo(Component component) {
if(mDisplayedItem != null)
mWindow.remove(mDisplayedItem);
mWindow.add(component);
mDisplayedItem = component;
updateListeners();
update();
}
private void updateListeners() {
mWindow.addWindowListener(mWindowListener);
KeyboardFocusManager
.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(mKeyDispatcher);
}
public void update() {
Graphics g = mBackBuffer.getDrawGraphics();
mWindow.paintAll(g);
g.dispose();
mBackBuffer.show();
}
}
GameCanvas
package Graphics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class GameCanvas extends JPanel implements CanvasInterface {
private GameViewport mViewport;
private boolean mViewportEnabled;
private ImageQueue mImageQueue;
public GameCanvas() {
mViewport = new GameViewport();
mViewportEnabled = false;
mImageQueue = new ImageQueue();
}
public void setViewport(GameViewport viewport) {
mViewport = viewport;
mViewportEnabled = true;
}
@Override
public ColorMode setGraphicsMode(ColorMode newMode) {
return mImageQueue.setMode(new ColorMode(newMode));
}
@Override
public void drawImage(ImageItem imageItem) {
mImageQueue.addImage(imageItem);
}
@Override
public void drawImage(Image image, int x, int y, int z, int width, int height) {
ImageItem imageItem = new ImageItem();
imageItem.image = image;
imageItem.x = x;
imageItem.y = y;
imageItem.z = z;
imageItem.width = width;
imageItem.height = height;
mImageQueue.addImage(imageItem);
}
@Override
public void showCanvas() {
repaint();
}
private void drawItems(Graphics2D g) {
if(!mViewportEnabled) {
ImageItem imageItem;
while(mImageQueue.hasImages()) {
imageItem = mImageQueue.nextImage(g);
g.drawImage(imageItem.image,
imageItem.x,
imageItem.y,
imageItem.width,
imageItem.height,
null);
}
} else {
mViewport.update();
Rectangle objectRect = new Rectangle();
ImageItem imageItem;
while(mImageQueue.hasImages()) {
imageItem = mImageQueue.nextImage(g);
objectRect.x = imageItem.x;
objectRect.y = imageItem.y;
objectRect.width = imageItem.width;
objectRect.height = imageItem.height;
if(!mViewport.contains(objectRect))
continue;
mViewport.translate(imageItem.x, imageItem.y, imageItem.width, imageItem.height, objectRect);
g.drawImage(imageItem.image,
objectRect.x,
objectRect.y,
objectRect.width,
objectRect.height,
null);
}
}
}
@Override
public void paint(Graphics g) {
mImageQueue.sort();
drawItems((Graphics2D) g);
}
}
MenuStack - Switches between menu screens (this is the menu panel)
package Menu;
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.LinkedList;
import javax.swing.JPanel;
public class MenuStack extends JPanel {
private LinkedList<MenuScreen> mScreenStack;
public MenuStack() {
mScreenStack = new LinkedList<>();
setLayout(new BorderLayout());
}
public void pushScreen(MenuScreen screen) {
if(!mScreenStack.isEmpty())
remove(mScreenStack.getLast());
mScreenStack.add(screen);
add(mScreenStack.getLast(), BorderLayout.CENTER);
revalidate();
repaint();
}
public void popScreen() {
if(mScreenStack.isEmpty())
return;
remove(mScreenStack.getLast());
mScreenStack.removeLast();
add(mScreenStack.getLast(), BorderLayout.CENTER);
repaint();
}
public MenuScreen currentScreen() {
return (MenuScreen)getComponent(getComponentCount()-1);
}
}
Sorry to post so much code. Thanks for any help.
Edit: fixed all the code formatting. That was weird.