package core; import java.awt.AlphaComposite; import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.image.BufferStrategy; import static core.VergeEngine.*; import static core.Script.*; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; public class GUI extends JFrame implements ActionListener, ItemListener, ComponentListener { Canvas canvas = new Canvas(); Controls control = new Controls(); static VergeEngine gameThread; static BufferStrategy strategy; private int winwidth, winheight; private static int curwidth; private static int curheight; boolean win_decoration = false; private static float alpha = 1f; public static long cycleTime; private static int frameDelay = 20; // 20ms. implies 50fps (1000/20) = 50 private static boolean showFPS = false; JMenuBar menuBar; private JCheckBoxMenuItem cbMenuItemSound; private JCheckBoxMenuItem cbMenuItemFullScreen; private JCheckBoxMenuItem cbMenuItemDoubleScreen; private JCheckBoxMenuItem cbMenuItemshowFPS; private JMenuItem menuItemIncreaseFPS; private JMenuItem menuItemDecreaseFPS; public GUI(int w, int h) { // build and display your GUI addComponentListener(this); VergeEngine.gui = this; canvas.setBackground(Color.black); control.clearKeymap(); canvas.addMouseListener(control); canvas.addMouseMotionListener(control); canvas.addFocusListener(control); canvas.addKeyListener(control); // Menus menuBar = new JMenuBar(); JMenu menu = new JMenu("Settings"); menuBar.add(menu); cbMenuItemSound = new JCheckBoxMenuItem("Enable Sound", !config.isNosound()); cbMenuItemSound.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, ActionEvent.CTRL_MASK)); cbMenuItemSound.addItemListener(this); menu.add(cbMenuItemSound); cbMenuItemFullScreen = new JCheckBoxMenuItem("Full Screen mode", !config.isWindowmode()); cbMenuItemFullScreen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F6, ActionEvent.CTRL_MASK)); cbMenuItemFullScreen.addItemListener(this); menu.add(cbMenuItemFullScreen); cbMenuItemDoubleScreen = new JCheckBoxMenuItem("Double Screen mode", config.isDoubleWindowmode()); cbMenuItemDoubleScreen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F7, ActionEvent.CTRL_MASK)); cbMenuItemDoubleScreen.addItemListener(this); menu.add(cbMenuItemDoubleScreen); cbMenuItemshowFPS = new JCheckBoxMenuItem("Show FPS", showFPS); cbMenuItemshowFPS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F8, ActionEvent.CTRL_MASK)); cbMenuItemshowFPS.addItemListener(this); menu.add(cbMenuItemshowFPS); menuItemDecreaseFPS = new JMenuItem("Decrease FPS"); menuItemDecreaseFPS.setActionCommand("decreaseFPS"); menuItemDecreaseFPS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F9, ActionEvent.CTRL_MASK)); menuItemDecreaseFPS.addActionListener(this); menu.add(menuItemDecreaseFPS); menuItemIncreaseFPS = new JMenuItem("Increase FPS"); menuItemIncreaseFPS.setActionCommand("increaseFPS"); menuItemIncreaseFPS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10, ActionEvent.CTRL_MASK)); menuItemIncreaseFPS.addActionListener(this); menu.add(menuItemIncreaseFPS); this.setJMenuBar(menuBar); this.add(canvas); if(!config.isDoubleWindowmode()) { setDimensions(this, w, h); } else { setDimensions(this, w*2, h*2); } this.addWindowListener(control); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cycleTime = System.currentTimeMillis(); System.out.println("GUI Initialized."); gameThread = new VergeEngine(); gameThread.setPriority(Thread.MIN_PRIORITY); gameThread.start(); // start Game processing. } void setDimensions(GUI gui, int w, int h) { setVisible(false); dispose(); if (w==0) { // Full screen Dimension scrsize = Toolkit.getDefaultToolkit().getScreenSize(); winwidth = scrsize.width; winheight = scrsize.height; win_decoration=false; menuBar.setPreferredSize(new java.awt.Dimension()); this.setUndecorated(true); this.setResizable(false); this.setSize(winwidth, winheight); //try { GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(gui); //} finally { // GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(null); //} } else { // Window mode winwidth = w; winheight = h; win_decoration=true; menuBar.setPreferredSize(null); // setting the size of the canvas or applet has no effect // we need to add the height of the title bar to the height // We use the insets now. Originally, we used: // 24 is the empirically determined height in WinXP // 48 enables us to have the whole window with title bar on-screen // 8 is the empirically determined width in win and linux //[Rafael, the Esper] Does not work //Insets insets = super.getInsets(); //super.setSize(winwidth+insets.left+insets.right, winheight+insets.top+insets.bottom); //super.setSize(winwidth, winheight); GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(null); this.setUndecorated(false); this.setResizable(true); this.setVisible(true); System.out.println("Winwidth: " + winwidth + ", Winheight: " + winheight + " I: " + super.getInsets()); this.setSize(winwidth+super.getInsets().left+super.getInsets().right, winheight+super.getInsets().top+super.getInsets().bottom+menuBar.getHeight()); System.out.println(super.getBounds()); } this.setVisible(true); canvas.requestFocus(); /*try { this.createBufferStrategy(2, new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), FlipContents.UNDEFINED)); } catch (AWTException e){ // flip is unavailable, create the best you have this.createBufferStrategy(2); }*/ canvas.createBufferStrategy(2); strategy = this.canvas.getBufferStrategy(); } public static void paintFrame() { //GUI.cycleTime = System.currentTimeMillis(); // Keep a steady FPS updateGUI(); synchFramerate(); updateFPS(); } public static void updateGUI() { if(Script.TEST_SIMULATION) { return; } try { Graphics g = strategy.getDrawGraphics(); if(alpha != 1f) { Graphics2D g2d = (Graphics2D) g; g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha)); g2d.drawImage(screen.getImage(), 0, 0, curwidth, curheight, null); } else { g.drawImage(screen.getImage(), 0, 0, curwidth, curheight, null); } /* Do this to rotate 180 Graphics2D g2d = (Graphics2D) g; g2d.rotate(Math.PI, curwidth/2, curheight/2); g2d.drawImage(screen.getImage(), 0, 0, curwidth, curheight, null);*/ // Show FPS if(showFPS) { g.setFont(fps_font); g.setColor(Color.WHITE); g.drawString("FPS: " + Float.toString(frameInLastSecond), 10, 20); } g.dispose(); strategy.show(); } catch(Exception e) { System.err.println("Unable to draw screen"); } } public static void synchFramerate() { cycleTime = cycleTime + frameDelay; long difference = cycleTime - System.currentTimeMillis(); if(difference > 0) { try { Thread.sleep(difference); } catch(InterruptedException e) { e.printStackTrace(); } } } void closeWindow() { super.setVisible(false); System.exit(0); } public Canvas getCanvas() { return this.canvas; } public void componentResized(ComponentEvent e) { Dimension scrsize = Toolkit.getDefaultToolkit().getScreenSize(); winwidth = scrsize.width; winheight = scrsize.height; //System.out.println(getWidth()); updateCanvasSize(); //VergeEngine.scaledBI = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);//this.createVolatileImage(this.getWidth(), this.getHeight()); //VergeEngine.g = VergeEngine.scaledBI.createGraphics(); } public void updateCanvasSize() { this.curwidth = this.getWidth()-super.getInsets().left-super.getInsets().right; this.curheight = this.getHeight()-super.getInsets().top-super.getInsets().bottom-menuBar.getHeight(); //canvas.updateSize( // this.getWidth()-super.getInsets().left-super.getInsets().right, //this.getHeight()-super.getInsets().top-super.getInsets().bottom); } @Override public void componentHidden(ComponentEvent arg0) { } @Override public void componentMoved(ComponentEvent arg0) { } @Override public void componentShown(ComponentEvent arg0) { } public void setAlpha(float f) { this.alpha = f; } public static void incFrameDelay(int i) { if(frameDelay <=1) return; if(frameDelay <= 5) i = -1; frameDelay = frameDelay + i; if(frameDelay > 100) frameDelay = 100; } protected final static Font fps_font = new Font("Monospaced", Font.PLAIN, 12); static long nextSecond = System.currentTimeMillis() + 1000; static int frameInLastSecond = 0; static int framesInCurrentSecond = 0; static void updateFPS() { long currentTime = System.currentTimeMillis(); if (currentTime > nextSecond) { nextSecond += 1000; frameInLastSecond = framesInCurrentSecond; framesInCurrentSecond = 0; } framesInCurrentSecond++; } @Override public void itemStateChanged(ItemEvent e) { Object source = e.getItemSelectable(); if(source==cbMenuItemSound) { config.setNosound(!config.isNosound()); stopmusic(); } else if(source==cbMenuItemFullScreen) { config.setWindowmode(!config.isWindowmode()); if( config.isWindowmode()) { this.setDimensions(this, config.getV3_xres(), config.getV3_yres()); } else { this.setDimensions(this, 0, 0); } } else if(source==cbMenuItemDoubleScreen) { config.setWindowmode(true); config.setDoubleWindowmode(!config.isDoubleWindowmode()); if( config.isDoubleWindowmode()) { this.setDimensions(this, config.getV3_xres()*2, config.getV3_yres()*2); } else { this.setDimensions(this, config.getV3_xres(), config.getV3_yres()); } } else if(source==cbMenuItemshowFPS) { showFPS = cbMenuItemshowFPS.isSelected(); } } @Override public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("increaseFPS")) { GUI.incFrameDelay(-5); } else if(e.getActionCommand().equals("decreaseFPS")) { GUI.incFrameDelay(5); } } }