package vooga.scroller.view; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.TreeSet; import javax.swing.JComponent; import javax.swing.Timer; import vooga.scroller.scrollingmanager.ScrollingManager; import vooga.scroller.util.Renderable; import vooga.scroller.util.Renderer; import vooga.scroller.util.mvc.Gaming; import vooga.scroller.model.Model; /** * * @author Ross Cahoon */ public class GameView extends JComponent implements Renderer<Gaming>{ // default serialization ID private static final long serialVersionUID = 1L; // animate 25 times per second if possible public static final int FRAMES_PER_SECOND = 25; // better way to think about timed events (in milliseconds) public static final int ONE_SECOND = 1000; public static final int DEFAULT_DELAY = ONE_SECOND / FRAMES_PER_SECOND; // input state public static final int NO_KEY_PRESSED = -1; // drives the animation private Timer myTimer; // game to be animated private Model myGame; // input state private int myLastKeyPressed; private Point myLastMousePosition; // MULTIPLE KEY SUPPORT private Set<Integer> myKeys; private ScrollingManager myScrollManager; /** * Create a panel so that it knows its size */ public GameView (Dimension size, ScrollingManager sm) { // set size (a bit of a pain) setPreferredSize(size); setSize(size); // prepare to receive input setFocusable(true); requestFocus(); setInputListeners(); setScrollManager(sm); } private void setScrollManager (ScrollingManager sm) { myScrollManager = sm; myScrollManager.initView(this); } /** * Paint the contents of the canvas. * * Never called by you directly, instead called by Java runtime * when area of screen covered by this container needs to be * displayed (i.e., creation, uncovering, change in status) * * @param pen used to paint shape on the screen */ @Override public void paintComponent (Graphics pen) { // first time needs to be special cased :( if (myGame != null && myScrollManager != null) { myScrollManager.viewPaint(pen); } } /** * Returns last key pressed by the user or -1 if nothing is pressed. */ public int getLastKeyPressed () { return myLastKeyPressed; } /** * Returns all keys currently pressed by the user. */ // MULTIPLE KEY SUPPORT public Collection<Integer> getKeysPressed () { return Collections.unmodifiableSet(myKeys); } /** * Returns last position of the mouse in the canvas. */ public Point getLastMousePosition () { return myLastMousePosition; } /** * Start the animation. */ public void start () { final int stepTime = DEFAULT_DELAY; // create a timer to animate the canvas Timer timer = new Timer(stepTime, new ActionListener() { public void actionPerformed (ActionEvent e) { myGame.update((double) stepTime / ONE_SECOND); repaint(); } }); // start animation myScrollManager.initModel(myGame); timer.start(); } public void setModel (Model m) { myGame = m; } /** * Stop the animation. */ public void stop () { myTimer.stop(); } /** * Create listeners that will update state based on user input. */ private void setInputListeners () { // initialize input state myLastKeyPressed = NO_KEY_PRESSED; // MULTIPLE KEY SUPPORT myKeys = new TreeSet<Integer>(); addKeyListener(new KeyAdapter() { @Override public void keyPressed (KeyEvent e) { myLastKeyPressed = e.getKeyCode(); // MULTIPLE KEY SUPPORT myKeys.add(e.getKeyCode()); } @Override public void keyReleased (KeyEvent e) { myLastKeyPressed = NO_KEY_PRESSED; // MULTIPLE KEY SUPPORT myKeys.remove((Integer)e.getKeyCode()); } }); myLastMousePosition = new Point(); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved (MouseEvent e) { myLastMousePosition = e.getPoint(); } }); } @Override public void render (Renderable<Gaming> renderable) { setModel((Model) renderable); } @Override public Renderable<Gaming> getRenderable () { return myGame; } @Override public void setRenderable (Renderable<Gaming> renderable) { setModel((Model) renderable); } }