Proper positioning of Listeners.

Hey everyone, I’m sorry to bother you but this is a subject that’s been bothering me a lot. I learned in University about Model View Control architecture, and we always had listener classes as separate classes. Every time I see listeners anywhere else though, they are part of the class that they are attached to.

In my game, I have several separate screens all with different buttons, features and controls. Currently I have it so that each Screen is it’s own object and there is one listener to deal with everything. I was thinking though that maybe I should have one listener in each Screen class that is specifically programmed to handle that one screen’s reactions.

Thoughts?

You use as many listeners as you have to, e.g. one per button(ActionListener) or one per game (KeyListener, there’s only one keyboard).
Since you have different buttons and stuff on each screen you obviously want different listeners, otherwise you can’t distinguish between buttons. However, for something like mouse/keylistener I would suggest only using it once.

Any code samples to post that explain it more in detail what you mean?

and wow that was a pathetically protracted time period for my response. Apologies.

public class DMToolGame extends JPanel implements ActionListener{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 3711700171154644204L;	
	private Screen mCurrentScreen;
	private MouseListener mListener;
	private KeyListener mKeyListener;
	private double mCurrentFrame, mLastFrame;
	private Timer mTimer;

	public DMToolGame(int width, int height){
		//Screen setup
		setFocusable(true);
		setDoubleBuffered(true);
		
		init();
	}
	
	public void init(){
		mCurrentScreen = new TitleScreen();
		mListener = new MouseListener(this);
		
		mLastFrame = 0;
		mCurrentFrame = 0;
		
		mTimer = new Timer(5, this);
		mTimer.start();
		
		addMouseListener(mListener);
		
		addKeyListener(mKeyListener);
	}

This class does the painting to the canvas and is itself the window. However, all of the objects that you can interact with are stored on various Screens, a character select screen, a battle Screen etc. This class just represents the window, stores which Screen we are currently on and tells it to draw itself.

Currently I have one single MouseListener called mListener as explained

public class MouseListener extends MouseAdapter{
	private DMToolGame mTool;
	private Screen mCurrentScreen;
	
	public MouseListener(DMToolGame tool){
		mTool = tool;
		mCurrentScreen = mTool.getCurrentScreen();
	}
		
	public void mousePressed(MouseEvent e){
		Point p = e.getPoint();
			
		ScreenItem intersectObject = mCurrentScreen.objectIntersects(p);
		if(intersectObject != null){
			if(intersectObject.getClass() == Button.class){
				if(intersectObject.getName().equals("Battle")){
					mTool.setCurrentScreen(new BattleScreen());
					mCurrentScreen = mTool.getCurrentScreen();
				}
				else if(intersectObject.getName().equals("Load Campaign")){
					mTool.setCurrentScreen(new CampaignScreen());
					mCurrentScreen = mTool.getCurrentScreen();
				}
				else if(intersectObject.getName().equals("Next Turn")){
					((BattleScreen)mCurrentScreen).NextTurn();
				}
				else if(intersectObject.getName().equals("Add Character")){
					((BattleScreen)mCurrentScreen).AddCharacterDialog();
				}
			}
		}
	}
}

Since I’m making this listener generic and do all the work for the various screens, I’m requiring it to do various abstract hurdles to figure out what to do.

I’ve been trying to make Screen extend JPanel, and then add custom MouseListeners to each of the subScreens *BattleScreen, CampaignScreen etc, but they don’t seem to trigger…

public class TitleScreen extends Screen{
	/**
	 * 
	 */
	private static final long serialVersionUID = 4838620713526543945L;
	private Image mBackground;
	private Button mLoadButton;

	public TitleScreen(){
		mBackground = managers.ImageManager.getInstance().getImage("TitleScreen.png");
		mLoadButton = new Button("Load Campaign", 100, 100);
		
		addMouseListener(new MouseListener());
	}
	
	public void draw(Graphics2D g2d, DMToolGame window) {
		g2d.drawImage(mBackground, 0, 0, window);
		mLoadButton.draw(g2d,  window);
	}
	
	public ScreenItem objectIntersects(Point p) {
		if(mLoadButton.contains(p)){
			return mLoadButton;
		}
		return null;
	}
	
	public class MouseListener extends MouseAdapter{
		public MouseListener(){
			System.out.println("Mcreated!");
		}
		@Override
		public void mouseClicked(MouseEvent e){
            System.out.println("Mouse was clicked");
        }
		@Override
        public void mouseEntered(MouseEvent arg0) {}
		@Override
        public void mouseExited(MouseEvent arg0) {}
		@Override
        public void mousePressed(MouseEvent arg0) {}
		@Override
        public void mouseReleased(MouseEvent arg0) {}
	}
}

It should be noted that I’m not using JButtons or any other Java Objects except for the Canvas so I cant just add listeners to the buttons in question.

Yes, you can just add listeners to the JPanel (you don’t need a JButton) and it should work fine. Anyhow, generally, your code looks it should work, but maybe there is another panel overlapping that’s why mouse clicks aren’t registering?

[quote]Currently I have it so that each Screen is it’s own object and there is one listener to deal with everything. I was thinking though that maybe I should have one listener in each Screen class that is specifically programmed to handle that one screen’s reactions.
[/quote]
I would suggest add one listener to each JPanel/JComponent you want to receive mouse events from. Very hard to maintain if you try to squeeze everything into 1 listener.

[quote]I learned in University about Model View Control architecture, and we always had listener classes as separate classes.
[/quote]
If you consider listeners in the “Control” part that’s correct. In my opinion listeners are part of the “View” but not the “Control”. The listener calls the “Control” element, e.g. your b.NextTurn()[/b].

Academically speaking, considering the listener a control element is probably correct. I generally found the following works a lot easier for me:

  • Model (model of your world): your game elements, e.g. World, Bullet, Entities, Player
  • Control (to update the model): your game update loop, your screens, loading/saving games etc.
  • View (inputs+outputs): GUI, OpenGL, Listeners, Mouse, Joystick, Sound