Change screenresolution

Im making a game which i want to be fullscreen. I have searched the forums without finding out how to do.
So i thought i could simulate fullscreen by changing the screen resolution
to for example 800x600 (which would be the size of my frame), and then setUndecorated(true);

So my questions now are.

  1. Is there an easy way to enter fullscreen mode?

  2. If not, how can i change the screenresolution to simulate fullscreen.

Thanks

I figured it out

Looks like you figured it out, but remember if you do this to DoubleBuffer your images, or you will get flickering problems and animations that aren’t smooth. Good job on that, FSEM can be a bitch to understand right away.

Thanks. I wonder if i do it right though.

the way i have it now is.


GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();

DrawingArea drawingarea = new DrawingArea();     //Jpanel

JFrame myFrame = new JFrame(gs.getDefaultConfiguration());

myFrame.setUndecorated(true);
myFrame.getContentPane().add(drawingarea);
myFrame.pack();

Window win = new Window(myFrame);

displayMode = new DisplayMode(800, 600, 16, displayMode.getRefreshRate());

try {
     gs.setFullScreenWindow(win);
     gs.setDisplayMode(displayMode);
}

catch(Exception e) {
     gs.setFullScreenWindow(null);
}

myFrame.setVisible(true);

Is it correct to Add a JPanel to the JFrame which you then put in a window?

Why do you create a JFrame in the first place?

What you did so far is correct, but you aren’t double-buffering. I’ll post the same thing with double buffering when I get back to my computer.

Also, you should test to see if the user’s monitor can switch display modes, and scan through available modes rather than creating a new one. Again, I’ll post this later today.

It’s not correct at all…

You are putting a JFrame inside a Window. I think because the method-parameters tell you it wants a Window. A JFrame is a subclass of Window, so you can just pass the JFrame in setFullScreenWindow(…);

Further you are making a new DisplayMode. That’s just asking for problems… You should iterate over all available DisplayModes and pick the one you prefer most. That will always work. Your current solution might or might not work on other systems than yours. I keep wondering why they made the DisplayMode-constructor public… I can only hope you’ll never use it again :slight_smile:

This is the Driver from a Mario clone I made, which uses FSEM. It has everything you need.


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;

public class Driver extends JFrame
{
	//For full screen mode:
	private GraphicsDevice device;
	private BufferStrategy bufferStrategy;

	//Everything else
    private Timer timer = new Timer(UniversalConstants.GAME_SPEED, null);
    private JPanel panel;
	private TitlePanels titlePanels;
    private GridBagLayout gbl;
    private GridBagConstraints gbc;
	private ImageViewer imageViewer;
	private SoundPlayer soundPlayer;
	
    public static void main(String[] args)
    {
        Driver tpo = new Driver();
		tpo.run();
	}
	
	private void run()
	{
		setResizable(false);
		setIgnoreRepaint(true);
		setUndecorated(true);
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		setSize(dim);
		
		soundPlayer = new SoundPlayer();
		imageViewer = new ImageViewer();
		titlePanels = new TitlePanels(this);
        makePanel();
		
		//Was used for FULL SCREEN MODE
		device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		DisplayMode displayModes[] = device.getDisplayModes();
        DisplayMode originalDisplayMode = device.getDisplayMode();
		
        try
        {
            if (device.isFullScreenSupported())
                device.setFullScreenWindow(this);
				
            int biggestMode = 0;
			for (int i = 0; i < displayModes.length; i++)
				if (displayModes[i].getWidth() + displayModes[i].getHeight() >= displayModes[biggestMode].getWidth() + displayModes[biggestMode].getHeight())
					biggestMode = i;
					
            DisplayMode displayMode = displayModes[biggestMode];
            if (device.isDisplayChangeSupported())
                device.setDisplayMode(displayMode);
        } catch (Exception e) { }

		//Was used for FULL SCREEN MODE
		panel.setDoubleBuffered(true);
		setBufferStrategy();
		addAnimator();
		addKeyListener(new MarioKeyListener());
		
		setVisible(true);
		start();
	}
	
    private void makePanel()
    {
        gbl = new GridBagLayout();
        gbc = new GridBagConstraints();
        getContentPane().setLayout(gbl);
        gbc.weightx = 10.0;
        gbc.weighty = 10.0;
        gbc.fill = GridBagConstraints.BOTH;
        panel = (JPanel) titlePanels.currentPanel();
        
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        getContentPane().add(panel);
        gbl.setConstraints(panel, gbc);
    }
    
	public void changePanel()
	{
		panel.setVisible(false);
		getContentPane().remove(panel);
		makePanel();
	}
	
	//Was used for FULL SCREEN MODE
	private void setBufferStrategy()
	{
		createBufferStrategy(2);
		bufferStrategy = getBufferStrategy();
	}
	
	//Was used for FULL SCREEN MODE
	private void addAnimator()
	{
		new Thread(new Animator()).start();
		//timer.addActionListener(new Animator());
	}
	
    private class MyWindowAdapter extends WindowAdapter
    {
        public void windowClosing (WindowEvent e)
        {
            System.exit(0);
        }
    }
    
	public Timer timer()
	{
		return timer;
	}
	
    public void start()
    {
        timer.start();
    }

    public void stop()
    {
        timer.stop ();
    }
	
	//Used for FULL SCREEN MODE
	private class Animator implements Runnable, ActionListener
	{
		public void run()
		{
			while(true)
			{
				titlePanels.screenUpdate(bufferStrategy);
				try {Thread.sleep(15);} catch(Exception e) {}
			}
		}
	
		public void actionPerformed(ActionEvent a)
		{
			titlePanels.screenUpdate(bufferStrategy);
		}
	}
	
	private class MarioKeyListener extends KeyAdapter
    {
        public void keyPressed(KeyEvent k)
        {
            titlePanels.currentPanel().keyPressed(k);
        }
        public void keyReleased(KeyEvent k)
        {
            titlePanels.currentPanel().keyReleased(k);
        }
		public void keyTyped(KeyEvent k)
		{
			titlePanels.currentPanel().keyTyped(k);
		}
    }
}

The array of titlePanels are basically a group of JPanels that represent different game states, like the title menu, cheat menu, keyboard menu, and network menu. When you actually start the game, it links you up with each panels draw method as needed.


public void screenUpdate(BufferStrategy bufferStrategy)
	{
		Graphics g = bufferStrategy.getDrawGraphics();
		currentPanel.draw(g); // Method to draw to
		bufferStrategy.show();
		g.dispose();
	}

The actual draw method, as you can see, is exactly like in non-FSEM. Basically you just need to worry about getting the graphics from your current buffer strategy.


    public void draw (Graphics g)
    {
        super.paintComponent(g);
		if (gameState == START_GAME)
		{
			g.setColor(Color.BLACK);
			g.fillRect(0,0,getWidth(),getHeight());
			g.setColor(Color.WHITE);
			g.setFont(new Font("Courier New", Font.BOLD, 50));
			
			mario.move(getWidth()/2 - mario.width()*2, getHeight()/2 - mario.height());
			mario.draw(g);
			g.drawString("WORLD " + level.toString(), mario.getX() - 50, mario.getY() - 100);
			g.drawString("x " + mario.lives(), mario.getX() + mario.width() + 25, mario.getY() + mario.height());
		}
		else if (gameState == GAME_OVER)
		{
			g.setColor(Color.BLACK);
			g.fillRect(0,0,getWidth(),getHeight());
			g.setColor(Color.WHITE);
			g.setFont(new Font("Courier New", Font.BOLD, 50));
			
			g.drawString("GAME OVER", getWidth()/2 - 150, getHeight()/2);
		}
		else
		{
			if (!inPipeLevel)
				level.draw(g);
			else
				pipeLevel.draw(g);
		}
		drawScore(g);
    } 
    
	private void drawScore(Graphics g)
	{
		g.setColor(Color.WHITE);
		g.setFont(new Font("Courier New", Font.BOLD, 22));
		g.drawString("MARIO", 10 + getWidth()/4 * 0, 22);
		g.drawString("COINS", 10 + getWidth()/4 * 1, 22);
		g.drawString("WORLD", 10 + getWidth()/4 * 2, 22);
		g.drawString("TIME" , 10 + getWidth()/4 * 3, 22);
		g.drawString("  " + mario.score(), 10 + getWidth()/4 * 0, 40);
		g.drawString("  " + mario.coins(), 10 + getWidth()/4 * 1, 40);
		g.drawString(" " + level.toString(), 10 + getWidth()/4 * 2, 40);
		g.drawString(" " + level.timeLeft(), 10 + getWidth()/4 * 3, 40);
	}
}

As you can see, I address a lot of the things you did wrong, like not creating a new display mode (looking for one instead), double buffering images, extending JFrame instead of having one inside of a Window. This code may not be commented very well – ask me any questions you may have and I’ll answer them asap.

I just noticed that my code looks for the largest screen size available. If you want 800x600, then put if statements in seeing if width == 800 and height == 600.

Thanks for your help, ill look over my code.

Hmm, and another thing I notice is


private void addAnimator()
{
        new Thread(new Animator()).start();
        //timer.addActionListener(new Animator());
}

You can see I had two different methods of animating. One animates everything every timestep with the main game Timer, the other creates a new Thread to do animation separately. Each can be a better choice, depending on what you’re doing. If you have only one layer of animation, then generally adding a new Thread is best, because any slowdowns in animation will not hinder the actual game engine, instead graphics will skip. This is also a much better choice for slow computers. However, if you have multiple layers, you will see some layers of animation jumping while others stay behind. I’d experiment with the two different methods to see what works best for each of your games. If you have no risk of slowdown at all, I highly recommend adding the Animator to the Timer instead of this method.

It’s best to do everything in 1 thread, and do quite advanced timing yourself, so that the ticker will run at a fixed frequency, and the gfx will do a frame when it notices the ticker has some free time.

Yeah I’d say this is generally best. I only included the ability to make a new Thread because sometimes I had so much going on the screen at once that animation would reduce speed. Making the new Thread will remedy that.