Results 1 to 4 of 4
  1. #1
    GrimWinter is offline Member
    Join Date
    Jun 2014
    Posts
    2
    Rep Power
    0

    Default Changing Canvas Returns With NullPointerException

    I'm currently having trouble with a Breakout clone that I'm working on when I want to change the scenes of the game. When I start out with the main menu and I hit play, the main menu calls for the StateManager to remove the MainMenu and then to add the GameState to start playing through the levels. But, whenever this is done it just gives a NullPointerException and freezes the game. I know the code for initially starting a State is fine because that is the same way the MainMenu is loaded but there seems to be an issue with changing from one to another...

    This is the StateManager class that adds and removes the States/Canvases to and from the JFrame/Main class:
    Java Code:
    package com.pathtocreating.Breakout_V2.state;
    
    import java.awt.BorderLayout;
    import java.util.ArrayList;
    import javax.swing.JFrame;
    
    public class StateManager 
    {
    
    	private ArrayList<State> states;
    	private int currentState;
    	
    	private JFrame gameFrame;
    	
    	public StateManager(JFrame gameFrame)
    	{
    		this.gameFrame = gameFrame;
    		states = new ArrayList<State>();
    		initAllStates();
    	}
    	
    	public void initAllStates()
    	{
    		states.add(new MainMenuState());
    		states.add(new GameState());
    		states.add(new OptionState());
    	}
    	
    	public void startCurrentState()
    	{
    		gameFrame.add(states.get(currentState), BorderLayout.CENTER);
    		states.get(currentState).requestFocus();
    		states.get(currentState).start();
    	}
    	
    	public void stopCurrentState()
    	{
    		gameFrame.remove(states.get(currentState));
    		states.get(currentState).stop();
    	}
    	
    	public void setCurrentState(String s)
    	{
    		int stateSize = states.size();
    		for(int i = 0; i < stateSize; i++)
    		{
    			if(s.equals(states.get(i).name))
    			{
    				currentState = i;
    			}
    		}
    		
    		startCurrentState();
    	}
    	
    	public void changeStates(String name)
    	{
    		stopCurrentState();
    		
    		setCurrentState(name);
    	}
    	
    	public State getCurrentState()
    	{
    		return states.get(currentState);
    	}
    	
    }
    It is initialized and runs in the BreakoutMain class:
    Java Code:
    package com.pathtocreating.Breakout_V2;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import javax.swing.JFrame;
    import com.pathtocreating.Breakout_V2.state.StateManager;
    
    @SuppressWarnings("serial")
    public class BreakoutMain extends JFrame
    {
    	
    	// Game events manager
    	public static volatile StateManager sm;
    	
    	public BreakoutMain()
    	{
    		setTitle("Breakout V2");
    		setVisible(true);
    		init();
    		setIgnoreRepaint(true);
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		pack();
    		setResizable(false);
    		setBackground(Color.BLACK);
    		setLocationRelativeTo(null);
    	}
    	
    	public void init()
    	{
    		sm = new StateManager(this);
    		sm.setCurrentState("MainMenuState");
    	}
    	
    	public void paint(Graphics g)
    	{
    	}
    	
    	public static void main(String args[])
    	{
    		new BreakoutMain();
    	}
    	
    }
    This is the State class that all other states extend from (i.e GameState, MenuState, etc.) which in turn extends the Canvas class:
    Java Code:
    package com.pathtocreating.Breakout_V2.state;
    
    import java.awt.Canvas;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.BufferStrategy;
    import java.awt.image.BufferedImage;
    import com.pathtocreating.Breakout_V2.controllers.InputController;
    import com.pathtocreating.Breakout_V2.util.Constants;
    
    @SuppressWarnings("serial")
    abstract class State extends Canvas implements Runnable
    {
    	
    	public InputController inputController;
    	
    	private volatile boolean running = false;
    	
    	private long ticks = 0;
    	
    	// Graphics Variables
    	public BufferedImage screen = new BufferedImage(Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT, BufferedImage.TYPE_INT_RGB);
    	private Graphics2D g = screen.createGraphics();
    	
    	public String name;
    	
    	public State(String name)
    	{
    		setPreferredSize(new Dimension(Constants.SCREEN_WIDTH - 9, Constants.SCREEN_HEIGHT - 9));
    		setFocusTraversalKeysEnabled(false);
    		setFocusable(true);
    		this.name = name;
    		inputController = new InputController(this);
    	}
    	
    	// Start running the state Thread
    	public void start()
    	{
    		if(!running)
    		{
    			running = true;
    			System.out.println("Current thread starting");
    			new Thread(this).start();
    			System.out.println("current thread started successfully");
    		}
    	}
    	
    	// Stop the state from running
    	public void stop()
    	{
    		if(running)
    		{
    			running = !running;
    			
    		}
    	}
    	
    	// Get the 2d graphics from the screen
    	public Graphics2D getGraphics2D()
    	{
    		screen = new BufferedImage(Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT, BufferedImage.TYPE_INT_RGB);
    		g = screen.createGraphics();
    		return g;
    	}
    	
    	// Check if this state is running
    	public boolean isRunning()
    	{
    		return running;
    	}
    	
    	// Get the number of ticks for the state
    	public long getTicks()
    	{
    		return ticks;
    	}
    	
    	// Render the graphics
    	public void render()
    	{
    		BufferStrategy b = this.getBufferStrategy();
    		if(b == null)
    		{
    			this.createBufferStrategy(3); // Look up bufferStrategy and the #
    			return;
    		}
    		
    		Graphics g = b.getDrawGraphics();
    		g.drawImage(screen, 0, 0, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT, this);
    		g.dispose(); // Look up these two methods
    		b.show();
    	}
    	
    	// Subclasses call super.update() to update ticks
    	public void update()
    	{
    		ticks++;
    	}
    	
    	// Run the thread, calling update and render
    	@Override
    	public void run() 
    	{
    		while(running)
    		{
    			update();
    			render();
    		}
    	}
    
    }
    The code that calls the change of state in MainMenuState is called in the update method:
    Java Code:
    if(inputController.isMouseClicked("LeftClick"))
    		{
    			if(playHover)
    			{
    				soundManager.playSound("ButtonClick");
    				BreakoutMain.sm.changeStates("GameState");
    			}
    			
    			else if(optionHover)
    			{
    				soundManager.playSound("ButtonClick");
    				System.out.println("Switching to Options");
    				BreakoutMain.sm.changeStates("OptionState");
    			}
    		}
    Here is the full stack trace when clicking the area to change states:
    Java Code:
    Exception in thread "Thread-2" java.lang.NullPointerException
    	at sun.java2d.SunGraphics2D.validateColor(Unknown Source)
    	at sun.java2d.SunGraphics2D.<init>(Unknown Source)
    	at sun.awt.image.SunVolatileImage.createGraphics(Unknown Source)
    	at java.awt.image.VolatileImage.getGraphics(Unknown Source)
    	at java.awt.Component$BltBufferStrategy.getDrawGraphics(Unknown Source)
    	at com.pathtocreating.Breakout_V2.state.State.render(State.java:89)
    	at com.pathtocreating.Breakout_V2.state.MainMenuState.render(MainMenuState.java:80)
    	at com.pathtocreating.Breakout_V2.state.State.run(State.java:108)
    	at com.pathtocreating.Breakout_V2.state.MainMenuState.run(MainMenuState.java:1)
    	at java.lang.Thread.run(Unknown Source)
    Any help with explaining what exactly is going wrong here would be very much appreciated. I've tried messing around with the order of which things are added/loading from the StateManager but am just failing to see what I did wrong. Thanks in advance.

  2. #2
    jim829 is online now Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    4,019
    Rep Power
    6

    Default Re: Changing Canvas Returns With NullPointerException

    Not certain if your statement numbers line up with your exceptions but it shows that at line 89 in your State class, you get
    a NullPointerException. Try printing out the value of g after you get the graphics context.

    Also, it is not a good idea to mix AWT and Swing classes. I suggest you read the following tutorial.
    Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI With JFC/Swing)

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  3. #3
    GrimWinter is offline Member
    Join Date
    Jun 2014
    Posts
    2
    Rep Power
    0

    Default Re: Changing Canvas Returns With NullPointerException

    Printing g after getting the graphics context gives this:
    Java Code:
    sun.java2d.SunGraphics2D[font=javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12],color=sun.swing.PrintColorUIResource[r=51,g=51,b=51]]
    It gives that same value both before and after clicking on the region. It looks like to me the NPE is coming from accessing b (the BufferStrategy variable) on the line you referenced. Printing out b after the State is changed to GameState gives the following:
    Java Code:
    java.awt.Component$BltSubRegionBufferStrategy@66116674
    I did previously have State extend to JPanel but it was giving me a lot of issues with mouse vs drawing objects coordinates which was fixed after someone suggested I switch to the Canvas.

  4. #4
    jim829 is online now Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    4,019
    Rep Power
    6

    Default Re: Changing Canvas Returns With NullPointerException

    Well, it is difficult for me to diagnose what is wrong since you don't show all your code and I can't run it (and do not post all of your code please).

    The following stack trace.

    Exception in thread "Thread-2" java.lang.NullPointerException
    at sun.java2d.SunGraphics2D.validateColor(Unknown Source)
    at sun.java2d.SunGraphics2D.<init>(Unknown Source)
    at sun.awt.image.SunVolatileImage.createGraphics(Unkn own Source)
    at java.awt.image.VolatileImage.getGraphics(Unknown Source)
    at java.awt.Component$BltBufferStrategy.getDrawGraphi cs(Unknown Source)
    at com.pathtocreating.Breakout_V2.state.State.render( State.java:89)
    at com.pathtocreating.Breakout_V2.state.MainMenuState .render(MainMenuState.java:80)
    at com.pathtocreating.Breakout_V2.state.State.run(Sta te.java:108)
    at com.pathtocreating.Breakout_V2.state.MainMenuState .run(MainMenuState.java:1)
    at java.lang.Thread.run(Unknown Source)

    Shows line by line where the problem occurred. If there are no line numbers then that is because you don't have the
    source code. But the error first occurred in your State.render() method. So start printing out values there, looking for
    a null value. It could be related to your thread and the fact that Swing is not thread safe. Nor do you do any synchronization anywhere. Thus, you could be referencing a value that is null in one thread before another thread has set it. That's the best I can offer at this time.

    And I have done quite a bit of graphics and painting and I never had a problem using JPanel.

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

Similar Threads

  1. HELP programming "tic-tac-toe" with <canvas><canvas/>
    By futbolinis in forum New To Java
    Replies: 1
    Last Post: 12-13-2012, 11:26 AM
  2. Replies: 0
    Last Post: 08-14-2010, 11:09 AM
  3. Replies: 0
    Last Post: 07-05-2009, 01:31 PM
  4. Help with canvas
    By tankhardrive in forum New To Java
    Replies: 13
    Last Post: 10-29-2008, 09:08 PM
  5. Canvas Example
    By Java Tip in forum SWT Tips
    Replies: 0
    Last Post: 07-25-2008, 03:22 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •