Question

I want to have a game where the view will move around as the mouse reaches the outer edge of the window (similar to many RTS games). I have read that there is significant overhead when using the MouseMotionListener.

Is there perhaps a way of having a second transparent component within the game window (JPanel) that does not affect game-play, but will register when the mouse leaves the inner component via MouseAdapter.mouseEntered()/mouseExited()?

boolean mouseOnScreen;
boolean mouseWithinInnerComponent; //is (10 <= mouse.x <= screenWidth - 10) && (10 <= mouse.y <= screenHeight)

if(mouseOnScreen && !mouseWithinInnerComponent)
{
    //do something...
}

I am at a loss for how to determine which screen boundary was crossed without having to have four of the above mentioned components overlapping at the corners to form a border around the screen which can detect if the mouse is at any edge or corner. This I imagine to be fairly expensive (having to check each component while running the game)...

boolean mouseOnScreen;
boolean mouseWithinTopComponent; //is (0 <= mouse.y <= 10)
boolean mouseWithinBottomComponent; //is (screenHeight - 10 <= mouse.y <= screenHeight)
boolean mouseWithinLeftComponent; //is (0 <= mouse.x <= 10)
boolean mouseWithinRightComponent; //is (screenWidth - 10 <= mouse.x <= screenWidth)

if(mouseOnScreen)
{
    if(!mouseWithinBottomComponent)
    {
        //move view up
    }
    if(!mouseWithinTopComponent)
    {
        //move view down
    }
    if(!mouseWithinLeftComponent)
    {
        //move view right
    }
    if(!mouseWithinRightComponent)
    {
        //move view left
    }
}

Exactly how much overhead exists with MouseMotionListener? Would this or a similar method perhaps be more efficient if the detections only need to be made along the borders of a game window?

NOTE: This will be used in windowed mode as well as possible full-screen application.

Was it helpful?

Solution

I have implemented the same thing you need using a MouseMotionListener. I'm not really sure why you think it will add overhead... If you add one and simply ask each of its methods to print to the console (which is slow) and move your mouse around, you will see it is pretty snappy from the user's point of view.

My implementation consists of 4 main pieces: a scroll pane, rectangular regions, a timer, and a MouseMotionListener.

First, I created a panel, called AutoScrollPane, that extends JScollPane. Even though it is a JScrollPane, you can hide the scrollbars. This allows me to leverage functionality for moving a viewport around on a map or similar like in an RTS game as you say.

Second, for the scroll regions, I actually have 8: n, ne, e, se, s, sw, w and nw (i.e. "north", north-east", etc.), with the diagonals allowing diagonal scrolling. I implement them simply as Rectangles. They aren't drawn on the screen or anything - I just instantiate 8 rectangles in my class sized appropriately and with coordinates that match the regions of the window. I actually allow my window to be resized, so I resize the rectangles if necessary.

Third, I have a timer that can be turned on and off. When it is turned on, every "tick" generates a Runnable. This Runnable's job is to scroll the panel's viewport in the appropriate direction a certain distance. Each Runnable is handed to the Swing event queue.

Finally, I have a MouseMotionListener. It's job is to intercept mouse enter, exit, and move events. Each time it receives an event, it checks the current mouse location and whether it intersects one of the rectangles. Based on which rectangle, it chooses a direction to scroll. It keeps track of whether the mouse was in a scroll region on the previous event or not. Based on this information it knows whether it should start scrolling, stop scrolling, or just let whatever is happening continue. I wanted my scrolling to stop if the mouse goes outside the pane, thus the use of the exit/enter events. Anyway, to start scrolling, the listener saves off the direction and distance to scroll and tells the timer to start. When it is time to stop scrolling (such as when the mouse exits a scroll region), it tells the timer to stop.

It took a while to pick the right timer granularity and scroll distance for smooth scrolling, but it does work pretty well. I hope this outline provides some help.

OTHER TIPS

I think it was Martin Fowler that espoused that premature optimisation is the root of all evil in software development. Why not try the MouseMotionListener and only think about optimising if you find that it affects the performance of the game.

There is nothing wrong with a MouseMotionListener When you read about the overhead it was probably one specific exmaple

Anything you can do in any programming language can be done bad or wrong.

If you pay attention to what you do in your listener all should be fine

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top