diff options
Diffstat (limited to 'src/com')
9 files changed, 199 insertions, 119 deletions
diff --git a/src/com/fourisland/fourpuzzle/PuzzleApplication.java b/src/com/fourisland/fourpuzzle/PuzzleApplication.java index 16de273..36dda19 100755 --- a/src/com/fourisland/fourpuzzle/PuzzleApplication.java +++ b/src/com/fourisland/fourpuzzle/PuzzleApplication.java | |||
@@ -43,9 +43,16 @@ public class PuzzleApplication extends Application { | |||
43 | 43 | ||
44 | private void initGameDialog(boolean undecorated) | 44 | private void initGameDialog(boolean undecorated) |
45 | { | 45 | { |
46 | /* Because the game form is accessed from many places at once, a | ||
47 | * Semaphore is used to control access to it */ | ||
46 | gameDialogHandler.acquireUninterruptibly(); | 48 | gameDialogHandler.acquireUninterruptibly(); |
47 | 49 | ||
50 | /* If the dialog is already visible (for instance, when changing the | ||
51 | * from full screen mode to windowed or vice versa while the program is | ||
52 | * running), it has to be closed so it can be reinitalized */ | ||
48 | gameDialog.setVisible(false); | 53 | gameDialog.setVisible(false); |
54 | |||
55 | // Set up the actual dialog | ||
49 | Container contentPane = gameDialog.getContentPane(); | 56 | Container contentPane = gameDialog.getContentPane(); |
50 | gameDialog = new JDialog(new JFrame(), false); | 57 | gameDialog = new JDialog(new JFrame(), false); |
51 | gameDialog.setContentPane(contentPane); | 58 | gameDialog.setContentPane(contentPane); |
@@ -76,6 +83,9 @@ public class PuzzleApplication extends Application { | |||
76 | { | 83 | { |
77 | if (e.getKeyCode() == KeyEvent.VK_F4) | 84 | if (e.getKeyCode() == KeyEvent.VK_F4) |
78 | { | 85 | { |
86 | /* The user is trying to switch the full screen mode; flip | ||
87 | * the status switch, reinitalize the dialog and then tell | ||
88 | * the GraphicsEnvironment what's happening */ | ||
79 | stretchScreen = !stretchScreen; | 89 | stretchScreen = !stretchScreen; |
80 | 90 | ||
81 | if (stretchScreen) | 91 | if (stretchScreen) |
@@ -88,20 +98,24 @@ public class PuzzleApplication extends Application { | |||
88 | } | 98 | } |
89 | } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) | 99 | } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) |
90 | { | 100 | { |
101 | /* If debug mode is enabled, holding Shift down should put | ||
102 | * the game into hyperactive mode */ | ||
91 | if (INSTANCE.getContext().getResourceMap().getBoolean("debugMode")) | 103 | if (INSTANCE.getContext().getResourceMap().getBoolean("debugMode")) |
92 | { | 104 | { |
93 | debugSpeed = true; | 105 | debugSpeed = true; |
94 | } | 106 | } |
95 | } else { | 107 | } else { |
96 | KeyboardInput.getKey().keyInput(e); | 108 | // If anything else is pressed, let the GameState handle it |
97 | } | 109 | KeyboardInput.getKey().keyInput(e); |
98 | } | 110 | } |
111 | } | ||
99 | 112 | ||
100 | @Override | 113 | @Override |
101 | public void keyReleased(KeyEvent e) | 114 | public void keyReleased(KeyEvent e) |
102 | { | 115 | { |
103 | if (e.getKeyCode() == KeyEvent.VK_SHIFT) | 116 | if (e.getKeyCode() == KeyEvent.VK_SHIFT) |
104 | { | 117 | { |
118 | // If Shift is let go of, hyperactive mode should end | ||
105 | debugSpeed = false; | 119 | debugSpeed = false; |
106 | } else { | 120 | } else { |
107 | KeyboardInput.getKey().letGo(); | 121 | KeyboardInput.getKey().letGo(); |
@@ -110,30 +124,44 @@ public class PuzzleApplication extends Application { | |||
110 | }); | 124 | }); |
111 | gameDialog.setVisible(true); | 125 | gameDialog.setVisible(true); |
112 | 126 | ||
127 | // As we're done with the game dialog, we can release the permit | ||
113 | gameDialogHandler.release(); | 128 | gameDialogHandler.release(); |
114 | } | 129 | } |
115 | 130 | ||
116 | @Override | 131 | @Override |
117 | protected void startup() { | 132 | protected void startup() |
133 | { | ||
118 | INSTANCE = this; | 134 | INSTANCE = this; |
119 | 135 | ||
136 | // Create the game form | ||
120 | initGameDialog(true); | 137 | initGameDialog(true); |
121 | 138 | ||
139 | // The game should start out in full screen mode | ||
122 | GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(gameDialog); | 140 | GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(gameDialog); |
123 | 141 | ||
142 | // Create the game cycle and run it | ||
124 | new Thread(new Runnable() { | 143 | new Thread(new Runnable() { |
125 | public void run() { | 144 | public void run() { |
126 | try { | 145 | try { |
127 | Audio.init(); | 146 | Audio.init(); |
128 | SystemGraphic.initalize(); | 147 | SystemGraphic.initalize(); |
129 | 148 | ||
149 | // The game starts with the Title Screen | ||
130 | Game.setGameState(new TitleScreenGameState()); | 150 | Game.setGameState(new TitleScreenGameState()); |
131 | 151 | ||
152 | /* The game cycle should run every tick (unless hyperactive | ||
153 | * mode is enabled, when it should run constantly */ | ||
132 | Interval in = Interval.createTickInterval(1); | 154 | Interval in = Interval.createTickInterval(1); |
133 | while (true) | 155 | while (true) |
134 | { | 156 | { |
157 | /* If the game window is deactivated, the game should | ||
158 | * pause execution */ | ||
135 | if (in.isElapsed() && !gameSleep) | 159 | if (in.isElapsed() && !gameSleep) |
136 | { | 160 | { |
161 | /* If there is currently a transition running, the | ||
162 | * only necessary function is rendering, otherwise | ||
163 | * process keyboard input and run GameState-specific | ||
164 | * game cycle code too */ | ||
137 | if (!Display.isTransitionRunning()) | 165 | if (!Display.isTransitionRunning()) |
138 | { | 166 | { |
139 | KeyboardInput.processInput(); | 167 | KeyboardInput.processInput(); |
@@ -141,6 +169,9 @@ public class PuzzleApplication extends Application { | |||
141 | Game.getGameState().doGameCycle(); | 169 | Game.getGameState().doGameCycle(); |
142 | } | 170 | } |
143 | 171 | ||
172 | /* Now, render to the game dialog. Note that as it | ||
173 | * is used in many places, a Semaphore permit is | ||
174 | * required before rendering can start */ | ||
144 | gameDialogHandler.acquireUninterruptibly(); | 175 | gameDialogHandler.acquireUninterruptibly(); |
145 | Display.render(gameDialog.getContentPane()); | 176 | Display.render(gameDialog.getContentPane()); |
146 | gameDialogHandler.release(); | 177 | gameDialogHandler.release(); |
diff --git a/src/com/fourisland/fourpuzzle/gamestate/GameOverGameState.java b/src/com/fourisland/fourpuzzle/gamestate/GameOverGameState.java index ed379cc..7466788 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/GameOverGameState.java +++ b/src/com/fourisland/fourpuzzle/gamestate/GameOverGameState.java | |||
@@ -24,11 +24,13 @@ public class GameOverGameState implements GameState { | |||
24 | 24 | ||
25 | public void initalize() | 25 | public void initalize() |
26 | { | 26 | { |
27 | // Play the Database-specifed Game Over music | ||
27 | Audio.playMusic(Database.getMusic(Music.GameOver)); | 28 | Audio.playMusic(Database.getMusic(Music.GameOver)); |
28 | } | 29 | } |
29 | 30 | ||
30 | public void deinitalize() | 31 | public void deinitalize() |
31 | { | 32 | { |
33 | // Stop the music | ||
32 | Audio.stopMusic(); | 34 | Audio.stopMusic(); |
33 | } | 35 | } |
34 | 36 | ||
@@ -36,6 +38,13 @@ public class GameOverGameState implements GameState { | |||
36 | { | 38 | { |
37 | if (key.isActionDown()) | 39 | if (key.isActionDown()) |
38 | { | 40 | { |
41 | /* When the user presses the action key to exit the game over | ||
42 | * screen, clear the save data and transition back to the title | ||
43 | * screen. | ||
44 | * | ||
45 | * NOTE: Clearing the save data may not actually be necessary here | ||
46 | * because TitleScreenGameState clears the save data before starting | ||
47 | * a new file */ | ||
39 | Game.setSaveFile(new SaveFile()); | 48 | Game.setSaveFile(new SaveFile()); |
40 | 49 | ||
41 | try { | 50 | try { |
@@ -53,6 +62,7 @@ public class GameOverGameState implements GameState { | |||
53 | 62 | ||
54 | public void render(Graphics2D g) | 63 | public void render(Graphics2D g) |
55 | { | 64 | { |
65 | // Display the Game Over picture | ||
56 | g.drawImage(ObjectLoader.getImage("Picture", "GameOver"), 0, 0, null); | 66 | g.drawImage(ObjectLoader.getImage("Picture", "GameOver"), 0, 0, null); |
57 | } | 67 | } |
58 | 68 | ||
diff --git a/src/com/fourisland/fourpuzzle/gamestate/TitleScreenGameState.java b/src/com/fourisland/fourpuzzle/gamestate/TitleScreenGameState.java index db6225e..6cfa829 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/TitleScreenGameState.java +++ b/src/com/fourisland/fourpuzzle/gamestate/TitleScreenGameState.java | |||
@@ -30,8 +30,13 @@ public class TitleScreenGameState implements GameState { | |||
30 | 30 | ||
31 | public void initalize() | 31 | public void initalize() |
32 | { | 32 | { |
33 | /* Play the Database-specified Title Screen music, which the client can | ||
34 | * change */ | ||
33 | Audio.playMusic(Database.getMusic(Music.Title)); | 35 | Audio.playMusic(Database.getMusic(Music.Title)); |
34 | 36 | ||
37 | /* Create the choice window, whose options are also taken from the | ||
38 | * Database. Then tell Display to render it and KeyboardInput to send | ||
39 | * keyboard events to it */ | ||
35 | choices = new ChoiceWindow.Builder(Arrays.asList(Database.getVocab(Vocabulary.NewGame), Database.getVocab(Vocabulary.LoadGame), Database.getVocab(Vocabulary.EndGame)), ChoiceWindow.ChoiceWindowLocation.BottomLeft) | 40 | choices = new ChoiceWindow.Builder(Arrays.asList(Database.getVocab(Vocabulary.NewGame), Database.getVocab(Vocabulary.LoadGame), Database.getVocab(Vocabulary.EndGame)), ChoiceWindow.ChoiceWindowLocation.BottomLeft) |
36 | .center(true) | 41 | .center(true) |
37 | .build(); | 42 | .build(); |
@@ -41,8 +46,10 @@ public class TitleScreenGameState implements GameState { | |||
41 | 46 | ||
42 | public void deinitalize() | 47 | public void deinitalize() |
43 | { | 48 | { |
49 | // Stop the music because the title screen is closing | ||
44 | Audio.stopMusic(); | 50 | Audio.stopMusic(); |
45 | 51 | ||
52 | // Also tell Display and KeyboardInput to forget about our ChoiceWindow | ||
46 | Display.unregisterRenderable(choices); | 53 | Display.unregisterRenderable(choices); |
47 | KeyboardInput.unregisterInputable(choices); | 54 | KeyboardInput.unregisterInputable(choices); |
48 | } | 55 | } |
@@ -50,47 +57,57 @@ public class TitleScreenGameState implements GameState { | |||
50 | PauseTimer pt = new PauseTimer(0); | 57 | PauseTimer pt = new PauseTimer(0); |
51 | public void processInput(KeyInput key) | 58 | public void processInput(KeyInput key) |
52 | { | 59 | { |
53 | if (pt.isElapsed()) | 60 | if (key.isActionDown()) |
54 | { | 61 | { |
55 | if (key.isActionDown()) | 62 | /* If the player presses the action key, play the selection sound |
63 | * and act upon the choice they selected */ | ||
64 | Audio.playSound(Database.getSound(Sound.Selection)); | ||
65 | |||
66 | if (choices.getSelected().equals(Database.getVocab(Vocabulary.NewGame))) | ||
56 | { | 67 | { |
57 | Audio.playSound(Database.getSound(Sound.Selection)); | 68 | /* If the player starts a new game, set the save data to a blank |
58 | 69 | * instance */ | |
59 | if (choices.getSelected().equals(Database.getVocab(Vocabulary.NewGame))) | 70 | Game.setSaveFile(new SaveFile()); |
60 | { | 71 | |
61 | Game.setSaveFile(new SaveFile()); | 72 | // Then transition to the map where the game starts |
62 | 73 | try { | |
63 | try { | 74 | Display.transition(Database.getTransition(Transitions.Generic), new MapViewGameState("TestMap", 1, 2), true); |
64 | Display.transition(Database.getTransition(Transitions.Generic), new MapViewGameState("TestMap", 1, 2), true); | 75 | } catch (InterruptedException ex) { |
65 | } catch (InterruptedException ex) { | 76 | Thread.currentThread().interrupt(); |
66 | Thread.currentThread().interrupt(); | ||
67 | } | ||
68 | } else if (choices.getSelected().equals(Database.getVocab(Vocabulary.LoadGame))) | ||
69 | { | ||
70 | // Do nothing, yet | ||
71 | } else if (choices.getSelected().equals(Database.getVocab(Vocabulary.EndGame))) | ||
72 | { | ||
73 | new Thread(new Runnable() { | ||
74 | public void run() { | ||
75 | try { | ||
76 | Display.transition(Database.getTransition(Transitions.Generic).getOutTransition()); | ||
77 | } catch (InterruptedException ex) { | ||
78 | Thread.currentThread().interrupt(); | ||
79 | } | ||
80 | |||
81 | System.exit(0); | ||
82 | } | ||
83 | }).start(); | ||
84 | } | 77 | } |
85 | } else if (key.getKey() == KeyEvent.VK_UP) | 78 | } else if (choices.getSelected().equals(Database.getVocab(Vocabulary.LoadGame))) |
79 | { | ||
80 | // Do nothing, yet | ||
81 | } else if (choices.getSelected().equals(Database.getVocab(Vocabulary.EndGame))) | ||
82 | { | ||
83 | // End the game, but transition out before doing so | ||
84 | new Thread(new Runnable() { | ||
85 | public void run() { | ||
86 | try { | ||
87 | Display.transition(Database.getTransition(Transitions.Generic).getOutTransition()); | ||
88 | } catch (InterruptedException ex) { | ||
89 | Thread.currentThread().interrupt(); | ||
90 | } | ||
91 | |||
92 | System.exit(0); | ||
93 | } | ||
94 | }).start(); | ||
95 | } | ||
96 | } else if (pt.isElapsed()) | ||
97 | { | ||
98 | if (key.getKey() == KeyEvent.VK_UP) | ||
86 | { | 99 | { |
100 | /* Tell ChoiceWindow that the player wants to move up, then | ||
101 | * wait a second before allowing any more vertical movement so | ||
102 | * that the player has a chance to let go of the up key */ | ||
87 | choices.moveUp(); | 103 | choices.moveUp(); |
88 | |||
89 | pt.setTimer(1); | 104 | pt.setTimer(1); |
90 | } else if (key.getKey() == KeyEvent.VK_DOWN) | 105 | } else if (key.getKey() == KeyEvent.VK_DOWN) |
91 | { | 106 | { |
107 | /* Tell ChoiceWindow that the player wants to move down, then | ||
108 | * wait a second before allowing any more vertical movement so | ||
109 | * that the player has a chance to let go of the down key */ | ||
92 | choices.moveDown(); | 110 | choices.moveDown(); |
93 | |||
94 | pt.setTimer(1); | 111 | pt.setTimer(1); |
95 | } | 112 | } |
96 | } | 113 | } |
@@ -103,6 +120,7 @@ public class TitleScreenGameState implements GameState { | |||
103 | 120 | ||
104 | public void render(Graphics2D g) | 121 | public void render(Graphics2D g) |
105 | { | 122 | { |
123 | // Display the title screen picture | ||
106 | g.drawImage(ObjectLoader.getImage("Picture", "Title"), 0, 0, null); | 124 | g.drawImage(ObjectLoader.getImage("Picture", "Title"), 0, 0, null); |
107 | } | 125 | } |
108 | 126 | ||
diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/ChipSet.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/ChipSet.java index ddf7c94..a4d7ac3 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/ChipSet.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/ChipSet.java | |||
@@ -10,11 +10,8 @@ import com.fourisland.fourpuzzle.PuzzleApplication; | |||
10 | import com.fourisland.fourpuzzle.util.ObjectLoader; | 10 | import com.fourisland.fourpuzzle.util.ObjectLoader; |
11 | import com.fourisland.fourpuzzle.util.ResourceNotFoundException; | 11 | import com.fourisland.fourpuzzle.util.ResourceNotFoundException; |
12 | import java.awt.image.BufferedImage; | 12 | import java.awt.image.BufferedImage; |
13 | import java.io.File; | ||
14 | import java.io.IOException; | 13 | import java.io.IOException; |
15 | import java.io.InputStream; | 14 | import java.io.InputStream; |
16 | import java.net.URISyntaxException; | ||
17 | import java.net.URL; | ||
18 | import java.util.HashMap; | 15 | import java.util.HashMap; |
19 | import java.util.logging.Level; | 16 | import java.util.logging.Level; |
20 | import java.util.logging.Logger; | 17 | import java.util.logging.Logger; |
@@ -26,6 +23,11 @@ import org.xml.sax.SAXException; | |||
26 | import org.xml.sax.helpers.DefaultHandler; | 23 | import org.xml.sax.helpers.DefaultHandler; |
27 | 24 | ||
28 | /** | 25 | /** |
26 | * ChipSet stores information about the tilesets for mapview. | ||
27 | * | ||
28 | * I'm not really going to comment this class much yet because it currently | ||
29 | * parses Tiled-created chipset files and this is all going to be rewritten | ||
30 | * once I've written my own map editor. | ||
29 | * | 31 | * |
30 | * @author hatkirby | 32 | * @author hatkirby |
31 | */ | 33 | */ |
diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/Map.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/Map.java index 33a8516..8b262dd 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/Map.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/Map.java | |||
@@ -116,7 +116,8 @@ public class Map { | |||
116 | { | 116 | { |
117 | int x = ev.getLocation().x; | 117 | int x = ev.getLocation().x; |
118 | int y = ev.getLocation().y; | 118 | int y = ev.getLocation().y; |
119 | 119 | ||
120 | // Check if the event is trying to move over the map boundaries | ||
120 | if ((toMove == Direction.North) && (y == 0)) | 121 | if ((toMove == Direction.North) && (y == 0)) |
121 | { | 122 | { |
122 | return true; | 123 | return true; |
@@ -131,11 +132,14 @@ public class Map { | |||
131 | return true; | 132 | return true; |
132 | } | 133 | } |
133 | 134 | ||
135 | /* If the event is the hero and walkthrough is enabled, bypass the rest | ||
136 | * of the collision-checking */ | ||
134 | if ((ev instanceof HeroEvent) && (((MapViewGameState) Game.getGameState()).debugWalkthrough)) | 137 | if ((ev instanceof HeroEvent) && (((MapViewGameState) Game.getGameState()).debugWalkthrough)) |
135 | { | 138 | { |
136 | return false; | 139 | return false; |
137 | } | 140 | } |
138 | 141 | ||
142 | // Check for layer events in the specified direction | ||
139 | if ((toMove == Direction.North) && (checkForEventCollision(x, y-1))) | 143 | if ((toMove == Direction.North) && (checkForEventCollision(x, y-1))) |
140 | { | 144 | { |
141 | return true; | 145 | return true; |
@@ -156,6 +160,7 @@ public class Map { | |||
156 | return true; | 160 | return true; |
157 | } | 161 | } |
158 | 162 | ||
163 | // Check for obstructions on the map itself in the specified direction | ||
159 | ChipSet cSI = ChipSet.getChipSet(chipSet); | 164 | ChipSet cSI = ChipSet.getChipSet(chipSet); |
160 | HashMap<Integer,ChipSetData> cSID = cSI.getChipSetData(); | 165 | HashMap<Integer,ChipSetData> cSID = cSI.getChipSetData(); |
161 | for (HashMap<Integer,Integer> mapArea : getMapData()) | 166 | for (HashMap<Integer,Integer> mapArea : getMapData()) |
diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java index 7635839..ec35db6 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java | |||
@@ -25,7 +25,6 @@ import com.fourisland.fourpuzzle.gamestate.mapview.event.specialmove.MoveEventTh | |||
25 | import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.AutomaticViewpoint; | 25 | import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.AutomaticViewpoint; |
26 | import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.Viewpoint; | 26 | import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.Viewpoint; |
27 | import com.fourisland.fourpuzzle.gamestate.menu.MenuGameState; | 27 | import com.fourisland.fourpuzzle.gamestate.menu.MenuGameState; |
28 | import com.fourisland.fourpuzzle.util.Functions; | ||
29 | import java.awt.Graphics2D; | 28 | import java.awt.Graphics2D; |
30 | import java.awt.event.KeyEvent; | 29 | import java.awt.event.KeyEvent; |
31 | import java.awt.image.BufferedImage; | 30 | import java.awt.image.BufferedImage; |
@@ -44,14 +43,23 @@ public class MapViewGameState implements GameState { | |||
44 | 43 | ||
45 | public MapViewGameState(String map, int x, int y) | 44 | public MapViewGameState(String map, int x, int y) |
46 | { | 45 | { |
46 | // Load the specified map into memory | ||
47 | setCurrentMap(map); | 47 | setCurrentMap(map); |
48 | |||
49 | // Place the Hero at the specified location | ||
48 | Game.getSaveFile().getHero().setLocation(x, y); | 50 | Game.getSaveFile().getHero().setLocation(x, y); |
51 | |||
52 | // Create a new viewpoint for the map | ||
49 | currentViewpoint = new AutomaticViewpoint(currentMap); | 53 | currentViewpoint = new AutomaticViewpoint(currentMap); |
54 | |||
55 | // Tell SpecialEvent about the new map so it can access it | ||
50 | SpecialEvent.setMapView(this); | 56 | SpecialEvent.setMapView(this); |
51 | } | 57 | } |
52 | 58 | ||
53 | public void initalize() | 59 | public void initalize() |
54 | { | 60 | { |
61 | /* Depending on the specified music type, either play music, stop the | ||
62 | * music or let the already playing music continue */ | ||
55 | switch (currentMap.getMusicType()) | 63 | switch (currentMap.getMusicType()) |
56 | { | 64 | { |
57 | case NoMusic: Audio.stopMusic(); break; | 65 | case NoMusic: Audio.stopMusic(); break; |
@@ -67,8 +75,11 @@ public class MapViewGameState implements GameState { | |||
67 | 75 | ||
68 | public void processInput(KeyInput key) | 76 | public void processInput(KeyInput key) |
69 | { | 77 | { |
78 | // Store the hero event in a local variable as it is used often | ||
70 | HeroEvent hero = Game.getSaveFile().getHero(); | 79 | HeroEvent hero = Game.getSaveFile().getHero(); |
71 | 80 | ||
81 | /* If debug mode is enabled and the control key is held down, set the | ||
82 | * walkthrough flag so the Hero can walk through stuff */ | ||
72 | if (key.isCtrlDown() && !debugWalkthrough) | 83 | if (key.isCtrlDown() && !debugWalkthrough) |
73 | { | 84 | { |
74 | if (PuzzleApplication.INSTANCE.getContext().getResourceMap().getBoolean("debugMode")) | 85 | if (PuzzleApplication.INSTANCE.getContext().getResourceMap().getBoolean("debugMode")) |
@@ -79,11 +90,14 @@ public class MapViewGameState implements GameState { | |||
79 | debugWalkthrough = false; | 90 | debugWalkthrough = false; |
80 | } | 91 | } |
81 | 92 | ||
93 | /* If the hero is not moving or the center of a MoveEvent action and no | ||
94 | * blocking special events are running, check the user input */ | ||
82 | if (!hero.isMoving() && !MoveEventThread.isHeroActive() && !EventHandler.isRunningEvent()) | 95 | if (!hero.isMoving() && !MoveEventThread.isHeroActive() && !EventHandler.isRunningEvent()) |
83 | { | 96 | { |
84 | Direction toMove = null; | 97 | Direction toMove = null; |
85 | Boolean letsMove = false; | 98 | Boolean letsMove = false; |
86 | 99 | ||
100 | // Translate the key input into the appropriate direction | ||
87 | switch (key.getKey()) | 101 | switch (key.getKey()) |
88 | { | 102 | { |
89 | case KeyEvent.VK_UP: | 103 | case KeyEvent.VK_UP: |
@@ -104,17 +118,22 @@ public class MapViewGameState implements GameState { | |||
104 | break; | 118 | break; |
105 | } | 119 | } |
106 | 120 | ||
121 | // If a movement key was indeed pressed, process it | ||
107 | if (letsMove) | 122 | if (letsMove) |
108 | { | 123 | { |
124 | // Try to move the hero in the specified direction | ||
109 | if (!hero.startMoving(toMove)) | 125 | if (!hero.startMoving(toMove)) |
110 | { | 126 | { |
127 | /* If the hero is blocked in that direction, check to see | ||
128 | * if a middle-layer OnHeroTouch event is the blocker, if | ||
129 | * so, execute it */ | ||
111 | for (LayerEvent ev : currentMap.getEvents()) | 130 | for (LayerEvent ev : currentMap.getEvents()) |
112 | { | 131 | { |
113 | if (ev.getCalltime() == EventCallTime.OnHeroTouch) | 132 | if (ev.getCalltime() == EventCallTime.OnHeroTouch) |
114 | { | 133 | { |
115 | if (ev.getLayer() == Layer.Middle) | 134 | if (ev.getLayer() == Layer.Middle) |
116 | { | 135 | { |
117 | if (Functions.isFacing(hero, ev)) | 136 | if (hero.getDirection().to(hero.getLocation()).equals(ev.getLocation())) |
118 | { | 137 | { |
119 | ev.getCallback().activate(ev.getCalltime()); | 138 | ev.getCallback().activate(ev.getCalltime()); |
120 | } | 139 | } |
@@ -124,6 +143,8 @@ public class MapViewGameState implements GameState { | |||
124 | } | 143 | } |
125 | } | 144 | } |
126 | 145 | ||
146 | /* If the player presses the action key, check if either of the two | ||
147 | * PushKey conditions are available */ | ||
127 | if (key.isActionDown()) | 148 | if (key.isActionDown()) |
128 | { | 149 | { |
129 | for (LayerEvent ev : currentMap.getEvents()) | 150 | for (LayerEvent ev : currentMap.getEvents()) |
@@ -132,12 +153,16 @@ public class MapViewGameState implements GameState { | |||
132 | { | 153 | { |
133 | if (ev.getLayer() == Layer.Middle) | 154 | if (ev.getLayer() == Layer.Middle) |
134 | { | 155 | { |
135 | if (Functions.isFacing(hero, ev)) | 156 | /* If the event is middle-layered and the hero is |
157 | * facing it, execute it */ | ||
158 | if (hero.getDirection().to(hero.getLocation()).equals(ev.getLocation())) | ||
136 | { | 159 | { |
137 | ev.setDirection(hero.getDirection().opposite()); | 160 | ev.setDirection(hero.getDirection().opposite()); |
138 | ev.getCallback().activate(ev.getCalltime()); | 161 | ev.getCallback().activate(ev.getCalltime()); |
139 | } | 162 | } |
140 | } else { | 163 | } else { |
164 | /* If the event is not middle-layered and the hero | ||
165 | * is on it, execute it */ | ||
141 | if (ev.getLocation().equals(hero.getLocation())) | 166 | if (ev.getLocation().equals(hero.getLocation())) |
142 | { | 167 | { |
143 | ev.getCallback().activate(ev.getCalltime()); | 168 | ev.getCallback().activate(ev.getCalltime()); |
@@ -146,7 +171,8 @@ public class MapViewGameState implements GameState { | |||
146 | } | 171 | } |
147 | } | 172 | } |
148 | } | 173 | } |
149 | 174 | ||
175 | // If the player presses the escape key, open the menu | ||
150 | if (key.getKey() == KeyEvent.VK_ESCAPE) | 176 | if (key.getKey() == KeyEvent.VK_ESCAPE) |
151 | { | 177 | { |
152 | try { | 178 | try { |
@@ -159,6 +185,8 @@ public class MapViewGameState implements GameState { | |||
159 | 185 | ||
160 | if (EventHandler.isRunningEvent()) | 186 | if (EventHandler.isRunningEvent()) |
161 | { | 187 | { |
188 | /* If debug mode is enabled and F11 is pressed, cancel any running | ||
189 | * events */ | ||
162 | if ((key.getKey() == KeyEvent.VK_F11) && (PuzzleApplication.INSTANCE.getContext().getResourceMap().getBoolean("debugMode"))) | 190 | if ((key.getKey() == KeyEvent.VK_F11) && (PuzzleApplication.INSTANCE.getContext().getResourceMap().getBoolean("debugMode"))) |
163 | { | 191 | { |
164 | for (LayerEvent ev : currentMap.getEvents()) | 192 | for (LayerEvent ev : currentMap.getEvents()) |
@@ -171,11 +199,15 @@ public class MapViewGameState implements GameState { | |||
171 | 199 | ||
172 | public void doGameCycle() | 200 | public void doGameCycle() |
173 | { | 201 | { |
202 | // Store the hero event in a local variable as it is used often | ||
174 | HeroEvent hero = Game.getSaveFile().getHero(); | 203 | HeroEvent hero = Game.getSaveFile().getHero(); |
175 | if (hero.isMoving()) | 204 | if (hero.isMoving()) |
176 | { | 205 | { |
206 | // If the player is in the process of moving, continue it | ||
177 | hero.processMoving(); | 207 | hero.processMoving(); |
178 | 208 | ||
209 | /* If the player has just finished moving, check for a non | ||
210 | * middle-layered OnHeroTouch on the Hero and execute it */ | ||
179 | if (!hero.isMoving()) | 211 | if (!hero.isMoving()) |
180 | { | 212 | { |
181 | for (LayerEvent ev : currentMap.getEvents()) | 213 | for (LayerEvent ev : currentMap.getEvents()) |
@@ -198,6 +230,10 @@ public class MapViewGameState implements GameState { | |||
198 | { | 230 | { |
199 | if (!ev.isMoving()) | 231 | if (!ev.isMoving()) |
200 | { | 232 | { |
233 | /* If one of the map's layer events aren't moving or being | ||
234 | * processed by a MoveEvent action and no blocking special | ||
235 | * events are running, start it moving in the direction provided | ||
236 | * by its MovementType */ | ||
201 | if (!MoveEventThread.isOtherActive(ev)) | 237 | if (!MoveEventThread.isOtherActive(ev)) |
202 | { | 238 | { |
203 | if (!EventHandler.isRunningEvent()) | 239 | if (!EventHandler.isRunningEvent()) |
@@ -206,23 +242,28 @@ public class MapViewGameState implements GameState { | |||
206 | } | 242 | } |
207 | } | 243 | } |
208 | } else { | 244 | } else { |
245 | // If the event IS moving, process the movement | ||
209 | ev.processMoving(); | 246 | ev.processMoving(); |
210 | } | 247 | } |
211 | 248 | ||
212 | if (ev.getCalltime() == EventCallTime.ParallelProcess) | 249 | if (ev.getCalltime() == EventCallTime.ParallelProcess) |
213 | { | 250 | { |
251 | // If the event is a ParallelProcess, execute it | ||
214 | ev.getCallback().activate(ev.getCalltime()); | 252 | ev.getCallback().activate(ev.getCalltime()); |
215 | } | 253 | } |
216 | } | 254 | } |
217 | } | 255 | } |
218 | 256 | ||
219 | public void render(Graphics2D g) | 257 | public void render(Graphics2D g) |
220 | { | 258 | { |
259 | // Ask the current viewpoint where to render from | ||
221 | int x = currentViewpoint.getX(); | 260 | int x = currentViewpoint.getX(); |
222 | int y = currentViewpoint.getY(); | 261 | int y = currentViewpoint.getY(); |
223 | 262 | ||
263 | // Render the lower layer of the map | ||
224 | g.drawImage(currentMap.renderLower(), 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); | 264 | g.drawImage(currentMap.renderLower(), 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); |
225 | 265 | ||
266 | // Render each lower and middle layered event onto a seperate canvas | ||
226 | BufferedImage eventLayer = Display.createCanvas(currentMap.getSize().width*16, currentMap.getSize().height*16); | 267 | BufferedImage eventLayer = Display.createCanvas(currentMap.getSize().width*16, currentMap.getSize().height*16); |
227 | Graphics2D g2 = eventLayer.createGraphics(); | 268 | Graphics2D g2 = eventLayer.createGraphics(); |
228 | EventList events = currentMap.getEvents(); | 269 | EventList events = currentMap.getEvents(); |
@@ -235,8 +276,10 @@ public class MapViewGameState implements GameState { | |||
235 | } | 276 | } |
236 | } | 277 | } |
237 | 278 | ||
279 | // Render the hero event onto the event canvas | ||
238 | Game.getHeroEvent().render(g2); | 280 | Game.getHeroEvent().render(g2); |
239 | 281 | ||
282 | // Render each above layered event onto the event canvas | ||
240 | for (LayerEvent event : events) | 283 | for (LayerEvent event : events) |
241 | { | 284 | { |
242 | if (event.getLayer() == Layer.Above) | 285 | if (event.getLayer() == Layer.Above) |
@@ -245,13 +288,19 @@ public class MapViewGameState implements GameState { | |||
245 | } | 288 | } |
246 | } | 289 | } |
247 | 290 | ||
291 | // Render the event canvas | ||
248 | g.drawImage(eventLayer, 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); | 292 | g.drawImage(eventLayer, 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); |
293 | |||
294 | // Render the upper layer of the map | ||
249 | g.drawImage(currentMap.renderUpper(), 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); | 295 | g.drawImage(currentMap.renderUpper(), 0, 0, Game.WIDTH, Game.HEIGHT, x, y, x+Game.WIDTH, y+Game.HEIGHT, null); |
250 | } | 296 | } |
251 | 297 | ||
252 | public void setCurrentMap(String mapName) | 298 | public void setCurrentMap(String mapName) |
253 | { | 299 | { |
300 | // Tell the save data what map is currently loaded | ||
254 | Game.getSaveFile().setCurrentMap(mapName); | 301 | Game.getSaveFile().setCurrentMap(mapName); |
302 | |||
303 | // Load the specified map from the database | ||
255 | currentMap = Database.getMap(mapName); | 304 | currentMap = Database.getMap(mapName); |
256 | } | 305 | } |
257 | 306 | ||
diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/AbstractEvent.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/AbstractEvent.java index f859739..e9482f9 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/AbstractEvent.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/AbstractEvent.java | |||
@@ -7,7 +7,6 @@ package com.fourisland.fourpuzzle.gamestate.mapview.event; | |||
7 | 7 | ||
8 | import com.fourisland.fourpuzzle.Direction; | 8 | import com.fourisland.fourpuzzle.Direction; |
9 | import com.fourisland.fourpuzzle.gamestate.mapview.Map; | 9 | import com.fourisland.fourpuzzle.gamestate.mapview.Map; |
10 | import com.fourisland.fourpuzzle.util.Functions; | ||
11 | import com.fourisland.fourpuzzle.util.Interval; | 10 | import com.fourisland.fourpuzzle.util.Interval; |
12 | import java.awt.Point; | 11 | import java.awt.Point; |
13 | import java.util.ArrayList; | 12 | import java.util.ArrayList; |
@@ -46,22 +45,38 @@ public abstract class AbstractEvent implements Event { | |||
46 | private int moveTimer; | 45 | private int moveTimer; |
47 | public boolean startMoving(Direction toMove) | 46 | public boolean startMoving(Direction toMove) |
48 | { | 47 | { |
48 | /* If the event is already moving (sometimes it manages to slip through | ||
49 | * the other filters), simply return without doing anything */ | ||
49 | if (isMoving()) | 50 | if (isMoving()) |
50 | { | 51 | { |
51 | return false; | 52 | return false; |
52 | } | 53 | } |
53 | 54 | ||
55 | /* Attempt to turn in the correct direction and then check if it was | ||
56 | * done. It could fail in certain cases which would mean the event | ||
57 | * shouldn't move, for instance, if a LayerEvent's AnimationType was | ||
58 | * FixedGraphic. | ||
59 | * | ||
60 | * There is a slight problem with this, however. Currently, if the | ||
61 | * AnimationType is FixedGraphic, but the event is already facing the | ||
62 | * correct direction, the event will move anyway, despite being fixed */ | ||
54 | setDirection(toMove); | 63 | setDirection(toMove); |
55 | |||
56 | if (getDirection() != toMove) | 64 | if (getDirection() != toMove) |
57 | { | 65 | { |
58 | return false; | 66 | return false; |
59 | } | 67 | } |
60 | 68 | ||
69 | /* Make sure that there are no present obstructions on the map in the | ||
70 | * specified direction */ | ||
61 | if (!getParentMap().checkForCollision(this, toMove)) | 71 | if (!getParentMap().checkForCollision(this, toMove)) |
62 | { | 72 | { |
73 | // Start the stepping animation | ||
63 | setAnimationStep(2); | 74 | setAnimationStep(2); |
75 | |||
76 | // Ask the event's MoveSpeed for the length of the animation | ||
64 | moveTimer = getMoveSpeed().getSpeed(); | 77 | moveTimer = getMoveSpeed().getSpeed(); |
78 | |||
79 | // Set the moving flag | ||
65 | setMoving(true); | 80 | setMoving(true); |
66 | 81 | ||
67 | return true; | 82 | return true; |
@@ -75,17 +90,25 @@ public abstract class AbstractEvent implements Event { | |||
75 | { | 90 | { |
76 | if (isMoving()) | 91 | if (isMoving()) |
77 | { | 92 | { |
93 | // Movement should be processed every half tick | ||
78 | if (in.isElapsed()) | 94 | if (in.isElapsed()) |
79 | { | 95 | { |
96 | // Decrement the move timer | ||
80 | moveTimer--; | 97 | moveTimer--; |
98 | |||
81 | if (moveTimer <= 0) | 99 | if (moveTimer <= 0) |
82 | { | 100 | { |
101 | /* If movement has finished, stop the animation and unset | ||
102 | * the moving flag */ | ||
83 | setAnimationStep(1); | 103 | setAnimationStep(1); |
84 | setMoving(false); | 104 | setMoving(false); |
105 | |||
106 | // Move the event to the correct location | ||
85 | setLocation(getDirection().to(getLocation())); | 107 | setLocation(getDirection().to(getLocation())); |
86 | } else if (moveTimer <= (getMoveSpeed().getSpeed() / 2)) | 108 | } else if (moveTimer <= (getMoveSpeed().getSpeed() / 2)) |
87 | { | 109 | { |
88 | setAnimationStep(0); | 110 | // If movement is half-complete, advance its animation |
111 | setAnimationStep(0); | ||
89 | } | 112 | } |
90 | } | 113 | } |
91 | } | 114 | } |
@@ -93,14 +116,22 @@ public abstract class AbstractEvent implements Event { | |||
93 | 116 | ||
94 | public boolean isOccupyingSpace(int x, int y) | 117 | public boolean isOccupyingSpace(int x, int y) |
95 | { | 118 | { |
119 | // Check if the event occupies the given location | ||
96 | if (getLocation().equals(new Point(x,y))) | 120 | if (getLocation().equals(new Point(x,y))) |
97 | { | 121 | { |
98 | return true; | 122 | return true; |
99 | } | 123 | } |
100 | 124 | ||
101 | if (Functions.isMovingTo(this, x, y)) | 125 | /* Because a moving event technically occupies two locations, we also |
126 | * need to check if the given location is where the event is moving to | ||
127 | * (if it's moving at all) */ | ||
128 | if (isMoving()) | ||
102 | { | 129 | { |
103 | return true; | 130 | Point loc = getDirection().to(getLocation()); |
131 | if ((loc.x == x) && (loc.y == y)) | ||
132 | { | ||
133 | return true; | ||
134 | } | ||
104 | } | 135 | } |
105 | 136 | ||
106 | return false; | 137 | return false; |
diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java index 233c415..d05a3d8 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java | |||
@@ -39,7 +39,7 @@ public class MoveEventThread implements Runnable { | |||
39 | 39 | ||
40 | public void start() | 40 | public void start() |
41 | { | 41 | { |
42 | for (Future f : eventThreads) | 42 | for (Future f : new ArrayList<Future>(eventThreads)) |
43 | { | 43 | { |
44 | if (f.isDone()) | 44 | if (f.isDone()) |
45 | { | 45 | { |
diff --git a/src/com/fourisland/fourpuzzle/util/Functions.java b/src/com/fourisland/fourpuzzle/util/Functions.java deleted file mode 100755 index c7c1243..0000000 --- a/src/com/fourisland/fourpuzzle/util/Functions.java +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * To change this template, choose Tools | Templates | ||
3 | * and open the template in the editor. | ||
4 | */ | ||
5 | |||
6 | package com.fourisland.fourpuzzle.util; | ||
7 | |||
8 | import com.fourisland.fourpuzzle.Direction; | ||
9 | import com.fourisland.fourpuzzle.gamestate.mapview.event.Event; | ||
10 | |||
11 | /** | ||
12 | * | ||
13 | * @author hatkirby | ||
14 | */ | ||
15 | public class Functions { | ||
16 | |||
17 | public static boolean isFacing(Event ev1, Event ev2) | ||
18 | { | ||
19 | if ((ev1.getDirection() == Direction.North) && (ev2.getLocation().x == ev1.getLocation().x) && (ev2.getLocation().y == (ev1.getLocation().y - 1))) | ||
20 | { | ||
21 | return true; | ||
22 | } else if ((ev1.getDirection() == Direction.West) && (ev2.getLocation().x == (ev1.getLocation().x - 1)) && (ev2.getLocation().y == ev1.getLocation().y)) | ||
23 | { | ||
24 | return true; | ||
25 | } else if ((ev1.getDirection() == Direction.South) && (ev2.getLocation().x == ev1.getLocation().x) && (ev2.getLocation().y == (ev1.getLocation().y + 1))) | ||
26 | { | ||
27 | return true; | ||
28 | } else if ((ev1.getDirection() == Direction.East) && (ev2.getLocation().x == (ev1.getLocation().x + 1)) && (ev2.getLocation().y == ev1.getLocation().y)) | ||
29 | { | ||
30 | return true; | ||
31 | } | ||
32 | |||
33 | return false; | ||
34 | } | ||
35 | |||
36 | public static boolean isMovingTo(Event ev, int x, int y) | ||
37 | { | ||
38 | if (ev.isMoving() == false) | ||
39 | { | ||
40 | return false; | ||
41 | } | ||
42 | |||
43 | if ((ev.getDirection() == Direction.North) && ((ev.getLocation().y-1) == y) && (ev.getLocation().x == x)) | ||
44 | { | ||
45 | return true; | ||
46 | } | ||
47 | |||
48 | if ((ev.getDirection() == Direction.West) && (ev.getLocation().y == y) && ((ev.getLocation().x-1) == x)) | ||
49 | { | ||
50 | return true; | ||
51 | } | ||
52 | |||
53 | if ((ev.getDirection() == Direction.South) && ((ev.getLocation().y+1) == y) && (ev.getLocation().x == x)) | ||
54 | { | ||
55 | return true; | ||
56 | } | ||
57 | |||
58 | if ((ev.getDirection() == Direction.East) && (ev.getLocation().y == y) && ((ev.getLocation().x+1) == x)) | ||
59 | { | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | return false; | ||
64 | } | ||
65 | |||
66 | } | ||