summary refs log tree commit diff stats
path: root/src/com/fourisland
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/fourisland')
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/PuzzleApplication.java43
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/GameOverGameState.java10
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/TitleScreenGameState.java82
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/mapview/ChipSet.java8
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/mapview/Map.java7
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java59
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/mapview/event/AbstractEvent.java41
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java2
-rwxr-xr-xsrc/com/fourisland/fourpuzzle/util/Functions.java66
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;
10import com.fourisland.fourpuzzle.util.ObjectLoader; 10import com.fourisland.fourpuzzle.util.ObjectLoader;
11import com.fourisland.fourpuzzle.util.ResourceNotFoundException; 11import com.fourisland.fourpuzzle.util.ResourceNotFoundException;
12import java.awt.image.BufferedImage; 12import java.awt.image.BufferedImage;
13import java.io.File;
14import java.io.IOException; 13import java.io.IOException;
15import java.io.InputStream; 14import java.io.InputStream;
16import java.net.URISyntaxException;
17import java.net.URL;
18import java.util.HashMap; 15import java.util.HashMap;
19import java.util.logging.Level; 16import java.util.logging.Level;
20import java.util.logging.Logger; 17import java.util.logging.Logger;
@@ -26,6 +23,11 @@ import org.xml.sax.SAXException;
26import org.xml.sax.helpers.DefaultHandler; 23import 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
25import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.AutomaticViewpoint; 25import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.AutomaticViewpoint;
26import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.Viewpoint; 26import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.Viewpoint;
27import com.fourisland.fourpuzzle.gamestate.menu.MenuGameState; 27import com.fourisland.fourpuzzle.gamestate.menu.MenuGameState;
28import com.fourisland.fourpuzzle.util.Functions;
29import java.awt.Graphics2D; 28import java.awt.Graphics2D;
30import java.awt.event.KeyEvent; 29import java.awt.event.KeyEvent;
31import java.awt.image.BufferedImage; 30import 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
8import com.fourisland.fourpuzzle.Direction; 8import com.fourisland.fourpuzzle.Direction;
9import com.fourisland.fourpuzzle.gamestate.mapview.Map; 9import com.fourisland.fourpuzzle.gamestate.mapview.Map;
10import com.fourisland.fourpuzzle.util.Functions;
11import com.fourisland.fourpuzzle.util.Interval; 10import com.fourisland.fourpuzzle.util.Interval;
12import java.awt.Point; 11import java.awt.Point;
13import java.util.ArrayList; 12import 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
6package com.fourisland.fourpuzzle.util;
7
8import com.fourisland.fourpuzzle.Direction;
9import com.fourisland.fourpuzzle.gamestate.mapview.event.Event;
10
11/**
12 *
13 * @author hatkirby
14 */
15public 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}