001package vooga.platformer.core;
002
003import java.awt.Color;
004import java.awt.Component;
005import java.awt.Dimension;
006import java.awt.Graphics;
007import java.awt.Point;
008import java.awt.geom.Rectangle2D;
009import java.util.HashMap;
010import java.util.Map;
011import javax.swing.JPanel;
012import vooga.platformer.core.inputinitializer.InputInitializer;
013import vooga.platformer.level.Level;
014import vooga.platformer.level.LevelFactory;
015import vooga.platformer.util.enums.PlayState;
016
017
018@SuppressWarnings("serial")
019public class PlatformerController extends JPanel implements Runnable {
020    private final int SLEEP_DELAY = 25;
021
022    private Level myCurrentLevel;
023    private String myCurrentLevelName;
024
025    // TODO: Make this variable hold a LevelFactory
026    private Map<String, Point> myStringMap = new HashMap<String, Point>();
027    private Dimension mySize;
028
029    private Thread animator;
030    private InputInitializer myInputInitializer;
031
032    public PlatformerController (String firstLevelName, InputInitializer ii) {
033
034        this.setFocusable(true);
035
036        setupLevel(firstLevelName);
037
038        myInputInitializer = ii;
039        myInputInitializer.setUpInput(myCurrentLevel.getObjectList(), this);
040
041        animator = new Thread(this);
042        animator.start();
043    }
044
045    /**
046     * The main update cycle method.
047     * 
048     * @param elapsedTime
049     */
050    public void update (long elapsedTime) {
051        myCurrentLevel.update(elapsedTime);
052        PlayState currentState = myCurrentLevel.getLevelStatus();
053
054        if (currentState == PlayState.NEXT_LEVEL || currentState == PlayState.GAME_OVER) {
055            String nextLevelName = myCurrentLevel.getNextLevelName();
056            setupLevel(nextLevelName);
057            myInputInitializer.setUpInput(myCurrentLevel.getObjectList(), this);
058        }
059    }
060
061    private void setupLevel (String lvlName) {
062        myCurrentLevelName = lvlName;
063        myCurrentLevel = LevelFactory.loadLevel(lvlName);
064        Rectangle2D cameraBounds = myCurrentLevel.getCamera().getBounds();
065        mySize = new Dimension((int) cameraBounds.getWidth(), (int) cameraBounds.getHeight());
066        setPreferredSize(mySize);
067    }
068
069    @Override
070    public Dimension getSize () {
071        return mySize;
072    }
073
074    /**
075     * Return the current level of this controller
076     * 
077     * @return
078     */
079    public Level getLevel () {
080        return myCurrentLevel;
081    }
082
083    @Override
084    public void paint (Graphics pen) {
085        paintBlankScreen(pen);
086        myCurrentLevel.paint(pen);
087        pen.setColor(Color.BLACK);
088        paintString(pen);
089        for (Component c : getComponents()) {
090            c.paint(pen);
091        }
092    }
093
094    /**
095     * Paint the background of game canvas
096     * 
097     * @param pen
098     */
099    public void paintBlankScreen (Graphics pen) {
100        pen.setColor(Color.WHITE);
101        pen.fillRect(0, 0, getWidth(), getHeight());
102
103        /*
104         * if (myBackground != null) {
105         * pen.drawImage(myBackground.getScaledInstance((int) getWidth(),
106         * (int) getHeight(), Image.SCALE_DEFAULT), 0, 0, null);
107         * }
108         */
109    }
110
111    private void paintString (Graphics pen) {
112        for (String s : myStringMap.keySet()) {
113            Point p = myStringMap.get(s);
114            pen.drawString(s, p.x, p.y);
115        }
116    }
117
118    /**
119     * Paint string at (x,y)
120     * 
121     * @param str
122     * @param x coordinate on canvas
123     * @param y coordinate on canvas
124     */
125    public void paintString (String str, int x, int y) {
126        Point location = new Point(x, y);
127        myStringMap.put(str, location);
128    }
129
130    /**
131     * The main game loop
132     */
133    @Override
134    public void run () {
135        long beforeTime, timeDiff, sleepTime;
136
137        beforeTime = System.currentTimeMillis();
138
139        while (true) {
140            timeDiff = System.currentTimeMillis() - beforeTime;
141
142            update(timeDiff);
143            repaint();
144
145            timeDiff = System.currentTimeMillis() - beforeTime;
146            sleepTime = SLEEP_DELAY - timeDiff;
147
148            if (sleepTime < 0) {
149                sleepTime = 2;
150            }
151
152            try {
153                Thread.sleep(sleepTime);
154            }
155            catch (InterruptedException e) {
156                System.out.println("interrupted!");
157            }
158            beforeTime = System.currentTimeMillis();
159        }
160    }
161    
162    /**
163     * Pause game;
164     */
165    public void pause(){
166        myCurrentLevel.pause();
167    }
168    
169    /**
170     * Unpause current Level
171     */
172    public void upause(){
173        myCurrentLevel.unpause();
174    }
175    
176    /**
177     * Replay current level
178     */
179    public void replayCurrentLevel(){
180        setupLevel(myCurrentLevelName);
181    }
182}