diff --git a/Classic.mtp b/Classic.mtp
new file mode 100644
index 0000000..8d7f9c6
Binary files /dev/null and b/Classic.mtp differ
diff --git a/Convertor/src/turtle/editor/TMXTestLevel.java b/Convertor/src/turtle/editor/TMXTestLevel.java
index c8ad9de..0c0f96f 100644
--- a/Convertor/src/turtle/editor/TMXTestLevel.java
+++ b/Convertor/src/turtle/editor/TMXTestLevel.java
@@ -7,6 +7,7 @@
import turtle.ui.MainApp;
import java.io.File;
+import java.util.UUID;
/**
* @author Henry Wang
@@ -36,10 +37,11 @@ public static void main(String args[]) throws Exception {
System.setProperty("user.dir", lvlFile.getParent());
- Launcher.testing = new LevelPack("Testing");
+ LevelPack pack = Launcher.testing = new LevelPack("Testing");
+ pack.setLevelPackID(new UUID(0, 0));
Level lvl = TMXToMTP.loadLevel(lvlFile);
- Launcher.testing.addLevel(lvl);
+ pack.addLevel(lvl);
Application.launch(Launcher.class);
}
diff --git a/Main/Main.iml b/Main/Main.iml
index e5d2daf..4201de2 100644
--- a/Main/Main.iml
+++ b/Main/Main.iml
@@ -5,6 +5,7 @@
+
diff --git a/Main/res/turtle/comp/blowing.wav b/Main/res/turtle/comp/blowing.wav
new file mode 100644
index 0000000..081d75f
Binary files /dev/null and b/Main/res/turtle/comp/blowing.wav differ
diff --git a/Main/res/turtle/comp/click.wav b/Main/res/turtle/comp/click.wav
new file mode 100644
index 0000000..2592c25
Binary files /dev/null and b/Main/res/turtle/comp/click.wav differ
diff --git a/Main/res/turtle/comp/explosion.wav b/Main/res/turtle/comp/explosion.wav
new file mode 100644
index 0000000..665d649
Binary files /dev/null and b/Main/res/turtle/comp/explosion.wav differ
diff --git a/Main/res/turtle/comp/grass.wav b/Main/res/turtle/comp/grass.wav
new file mode 100644
index 0000000..f584003
Binary files /dev/null and b/Main/res/turtle/comp/grass.wav differ
diff --git a/Main/res/turtle/comp/splash.wav b/Main/res/turtle/comp/splash.wav
new file mode 100644
index 0000000..fc38737
Binary files /dev/null and b/Main/res/turtle/comp/splash.wav differ
diff --git a/Main/res/turtle/comp/steam.wav b/Main/res/turtle/comp/steam.wav
new file mode 100644
index 0000000..46fe2cc
Binary files /dev/null and b/Main/res/turtle/comp/steam.wav differ
diff --git a/Main/res/turtle/comp/tap.wav b/Main/res/turtle/comp/tap.wav
new file mode 100644
index 0000000..f686807
Binary files /dev/null and b/Main/res/turtle/comp/tap.wav differ
diff --git a/Main/res/turtle/comp/unlock.wav b/Main/res/turtle/comp/unlock.wav
new file mode 100644
index 0000000..90d2fd4
Binary files /dev/null and b/Main/res/turtle/comp/unlock.wav differ
diff --git a/Main/res/turtle/comp/whip.wav b/Main/res/turtle/comp/whip.wav
new file mode 100644
index 0000000..e89d2cc
Binary files /dev/null and b/Main/res/turtle/comp/whip.wav differ
diff --git a/Main/src/turtle/ui/styles.css b/Main/res/turtle/ui/styles.css
similarity index 100%
rename from Main/src/turtle/ui/styles.css
rename to Main/res/turtle/ui/styles.css
diff --git a/Main/src/turtle/comp/Bucket.java b/Main/src/turtle/comp/Bucket.java
index 9ac69d6..5994bc7 100644
--- a/Main/src/turtle/comp/Bucket.java
+++ b/Main/src/turtle/comp/Bucket.java
@@ -45,6 +45,7 @@ public class Bucket extends Mover {
public boolean die(Component attacker) {
if (attacker instanceof Water) {
if (!isFilled()) {
+ playSound(Sounds.SPLASH);
setFilled(true);
((Water) attacker).transformToSand();
}
diff --git a/Main/src/turtle/comp/Button.java b/Main/src/turtle/comp/Button.java
index 06a8f78..dc88cb9 100644
--- a/Main/src/turtle/comp/Button.java
+++ b/Main/src/turtle/comp/Button.java
@@ -66,6 +66,7 @@ public void setLinked(Location linkedLocation) {
@Override
public boolean interact(Actor other) {
Grid parent = getParentGrid();
+ playSound(Sounds.CLICK);
if (parent != null && parent.isValidLocation(linkedLocation)) {
Cell factory = parent.getCellAt(linkedLocation);
if (factory instanceof Factory) {
diff --git a/Main/src/turtle/comp/Cannon.java b/Main/src/turtle/comp/Cannon.java
index 1ea0cd4..2d80f8e 100644
--- a/Main/src/turtle/comp/Cannon.java
+++ b/Main/src/turtle/comp/Cannon.java
@@ -54,6 +54,8 @@ private void shoot() {
return;
}
+ playSound(Sounds.EXPLOSION);
+
Direction heading = getHeading();
Location loc = new Location(getHeadLocation());
heading.traverse(loc);
diff --git a/Main/src/turtle/comp/Door.java b/Main/src/turtle/comp/Door.java
index bb713a6..6490fe3 100644
--- a/Main/src/turtle/comp/Door.java
+++ b/Main/src/turtle/comp/Door.java
@@ -69,6 +69,7 @@ public boolean checkInteract(Actor other) {
if (other instanceof Player) {
for (Item itm : ((Player) other).getPocket()) {
if (itm instanceof Key && ((Key) itm).getColor() == getColor()) {
+ playSound(Sounds.UNLOCK);
die(this);
return true;
}
diff --git a/Main/src/turtle/comp/Exit.java b/Main/src/turtle/comp/Exit.java
index f54f65c..2d19009 100644
--- a/Main/src/turtle/comp/Exit.java
+++ b/Main/src/turtle/comp/Exit.java
@@ -44,6 +44,7 @@ public void updateFrame(long frame) {
super.updateFrame(frame);
if (winner != null && winner.getTrailingLocation().equals(
getHeadLocation())) {
+ //TODO: sound
winner.win();
}
}
diff --git a/Main/src/turtle/comp/Factory.java b/Main/src/turtle/comp/Factory.java
index 775b296..acc9d1e 100644
--- a/Main/src/turtle/comp/Factory.java
+++ b/Main/src/turtle/comp/Factory.java
@@ -22,7 +22,7 @@ public class Factory extends Cell {
*/
public static final int DEFAULT_IMAGE = 70;
private static final int FACTORY_OFFSET_IMAGE = DEFAULT_IMAGE;
- private static final double RATIO_CLONE_IMG = .8;
+ private static final double RATIO_CLONE_IMG = .7;
private static final long serialVersionUID = -8544196441607182765L;
/**
diff --git a/Main/src/turtle/comp/Fire.java b/Main/src/turtle/comp/Fire.java
index 0060345..e7720db 100644
--- a/Main/src/turtle/comp/Fire.java
+++ b/Main/src/turtle/comp/Fire.java
@@ -69,7 +69,10 @@ public boolean pass(Actor visitor) {
if (smoking) {
return true;
}
- visitor.die(this);
+ if (visitor.die(this)) {
+ playSound(Sounds.STEAM);
+ Sounds.GRASS.play();
+ }
return true;
}
diff --git a/Main/src/turtle/comp/Food.java b/Main/src/turtle/comp/Food.java
index c2aa02d..7a30a17 100644
--- a/Main/src/turtle/comp/Food.java
+++ b/Main/src/turtle/comp/Food.java
@@ -35,7 +35,11 @@ public boolean checkInteract(Actor other) {
*/
@Override
public boolean interact(Actor other) {
- return other instanceof Player && super.interact(other);
+ if (other instanceof Player) {
+ //TODO: sound
+ return super.interact(other);
+ }
+ return false;
}
/**
diff --git a/Main/src/turtle/comp/Grass.java b/Main/src/turtle/comp/Grass.java
index 20d3471..85a74c9 100644
--- a/Main/src/turtle/comp/Grass.java
+++ b/Main/src/turtle/comp/Grass.java
@@ -124,6 +124,8 @@ public void updateFrame(long frame) {
if (dr + dc <= 1) {
fading = 0;
animateFrames(TRANSFORM_FRAMES, false);
+ if (!Sounds.GRASS.isPlaying())
+ playSound(Sounds.GRASS);
}
}
}
diff --git a/Main/src/turtle/comp/Item.java b/Main/src/turtle/comp/Item.java
index 19ba54b..98bae1e 100644
--- a/Main/src/turtle/comp/Item.java
+++ b/Main/src/turtle/comp/Item.java
@@ -23,6 +23,8 @@ public abstract class Item extends Actor {
@Override
public boolean interact(Actor other) {
if (other instanceof Player) {
+ //if (getCurrentClip() == null)
+ playSound(Sounds.TAP);
Player p = (Player) other;
if (p.collectItem(this)) {
getParentGrid().removeActor(this);
diff --git a/Main/src/turtle/comp/Sounds.java b/Main/src/turtle/comp/Sounds.java
new file mode 100644
index 0000000..5f266cd
--- /dev/null
+++ b/Main/src/turtle/comp/Sounds.java
@@ -0,0 +1,32 @@
+package turtle.comp;
+
+import javafx.scene.media.AudioClip;
+
+
+import static java.lang.ClassLoader.getSystemResource;
+
+/**
+ * Contains all the default sounds that can be used for various interactions
+ * @author Henry Wang
+ */
+public interface Sounds {
+ AudioClip BLOWING = loadClip("turtle/comp/blowing.wav");
+ AudioClip CLICK = loadClip("turtle/comp/click.wav");
+ AudioClip EXPLOSION = loadClip("turtle/comp/explosion.wav");
+ AudioClip GRASS = loadClip("turtle/comp/grass.wav");
+ AudioClip SPLASH = loadClip("turtle/comp/splash.wav");
+ AudioClip STEAM = loadClip("turtle/comp/steam.wav");
+ AudioClip TAP = loadClip("turtle/comp/tap.wav");
+ AudioClip UNLOCK = loadClip("turtle/comp/unlock.wav");
+ AudioClip WHIP = loadClip("turtle/comp/whip.wav");
+
+ /**
+ * Loads an audio clip from the classpath
+ * @param res the classpath of the audio clip
+ * @return the loaded audio clip
+ */
+ static AudioClip loadClip(String res) {
+
+ return new AudioClip(getSystemResource(res).toExternalForm());
+ }
+}
diff --git a/Main/src/turtle/comp/Trap.java b/Main/src/turtle/comp/Trap.java
index f03c9a7..769aebf 100644
--- a/Main/src/turtle/comp/Trap.java
+++ b/Main/src/turtle/comp/Trap.java
@@ -40,7 +40,7 @@ public class Trap extends Actor {
*/
@Override
public boolean checkInteract(Actor other) {
- return true;
+ return !(other instanceof Trap);
}
/**
@@ -53,6 +53,7 @@ public boolean checkInteract(Actor other) {
@Override
public boolean interact(Actor other) {
if (other.die(this)) {
+ playSound(Sounds.WHIP);
die(this);
}
return true;
@@ -67,7 +68,7 @@ public boolean interact(Actor other) {
*/
@Override
public DominanceLevel dominanceLevelFor(Actor other) {
- return FIXTURE;
+ return FIXTURE_TRAP;
}
/**
diff --git a/Main/src/turtle/comp/Water.java b/Main/src/turtle/comp/Water.java
index 5e761e4..2d6ab19 100644
--- a/Main/src/turtle/comp/Water.java
+++ b/Main/src/turtle/comp/Water.java
@@ -1,6 +1,8 @@
package turtle.comp;
+import javafx.animation.Transition;
import javafx.scene.image.ImageView;
+import javafx.util.Duration;
import turtle.core.Actor;
import turtle.core.Cell;
import turtle.core.TileSet;
@@ -26,6 +28,7 @@ public class Water extends Cell {
private static final int MAX_TRANSFORM = TRANSFORM_ANIMATION_FRAME.length *
DEF_ANIMATION_FRAME_CHANGE;
private static final long serialVersionUID = 991189208764206004L;
+ private static final Duration SPLASH_DELAY = Duration.millis(100);
/**
* Determines the associated attributes with a tile if the tile is related to this object.
@@ -63,7 +66,9 @@ public Water() {
*/
@Override
public boolean pass(Actor visitor) {
- visitor.die(this);
+ if (visitor.die(this)) {
+ playSound(Sounds.SPLASH);
+ }
return true;
}
diff --git a/Main/src/turtle/core/Actor.java b/Main/src/turtle/core/Actor.java
index 8c1b064..30951f7 100644
--- a/Main/src/turtle/core/Actor.java
+++ b/Main/src/turtle/core/Actor.java
@@ -27,6 +27,7 @@ public abstract class Actor extends Component {
public static final DominanceLevel ENEMY = new DominanceLevel("Enemy", 100);
public static final DominanceLevel MOVER = new DominanceLevel("Mover", 200);
public static final DominanceLevel ITEM = new DominanceLevel("Item", 300);
+ public static final DominanceLevel FIXTURE_TRAP = new DominanceLevel("Fixture_Trap", 350);
public static final DominanceLevel FIXTURE = new DominanceLevel("Fixture", 400);
private static final long serialVersionUID = -8229684437846026366L;
diff --git a/Main/src/turtle/core/Component.java b/Main/src/turtle/core/Component.java
index 4e83c18..1966367 100644
--- a/Main/src/turtle/core/Component.java
+++ b/Main/src/turtle/core/Component.java
@@ -1,13 +1,16 @@
package turtle.core;
+import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
+import javafx.scene.media.AudioClip;
import turtle.attributes.Attributable;
import turtle.attributes.AttributeSet;
import turtle.attributes.NotAttribute;
+import turtle.comp.Sounds;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -26,6 +29,33 @@
*/
public abstract class Component extends Pane implements Attributable,
Serializable {
+ public static final int DEFAULT_IMAGE = -1;
+
+ public static final int DEF_ANIMATION_FRAME_CHANGE = 4;
+ public static final TileSet DEFAULT_SET = new TileSet();
+ public static final int BIG_FRAME = 10;
+
+ private static final int INVALID_IMAGE_FRAME = -2;
+ private static final long serialVersionUID = -65657197093045828L;
+
+ private static final int SHUFFLE = 50;
+ private static AudioClip currentClip = null;
+
+ static {
+ //Initialize all the sounds
+ for (Field fld : Sounds.class.getFields()) {
+ try {
+ Object val = fld.get(null);
+ if (val instanceof AudioClip) {
+ ((AudioClip) val).play(0);
+ ((AudioClip) val).stop();
+ }
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ }
+ }
+ }
+
/**
* Obtains the default image of this class. If this class does not define
* a default image, this will search up the hierarchy until the field is
@@ -55,9 +85,9 @@ public static int getDefaultImage(Class extends Component> comp) {
return DEFAULT_IMAGE;
}
- public static final int DEFAULT_IMAGE = -1;
- private static final int INVALID_IMAGE_FRAME = -2;
- private static final long serialVersionUID = -65657197093045828L;
+ public static AudioClip getCurrentClip() {
+ return (currentClip != null && currentClip.isPlaying()) ? currentClip : null;
+ }
/**
* Utility method used to shuffle an array.
@@ -91,11 +121,6 @@ public static void shuffle(Object[] arr, Random rng) {
}
}
- public static final int DEF_ANIMATION_FRAME_CHANGE = 4;
- public static final TileSet DEFAULT_SET = new TileSet();
- public static final int BIG_FRAME = 10;
- private static final int SHUFFLE = 50;
-
private final Location headLoc;
private final Location trailLoc;
private final AttributeSet attributes;
@@ -128,19 +153,6 @@ protected Component() {
attributes = new AttributeSet<>(this);
}
- /**
- * Initializes the tile-set and image-view. This should ONLY be called
- * exactly once in the component's lifetime.
- *
- * @param ts the tileset to initialize to.
- */
- private void initTileSet(TileSet ts) {
- this.ts = ts;
- currentImage = INVALID_IMAGE_FRAME;
- img = new ImageView(ts.getImageSet());
- this.getChildren().add(img);
- }
-
/**
* Animates component through a series of frames at the default
* change rate (change once per 4 frames).
@@ -291,6 +303,45 @@ protected void layoutChildren() {
VPos.CENTER);
}
+ /**
+ * Plays an audio clip sound, stopping the previous sound effect.
+ * @param sound the sound clip to play
+ */
+ protected void playSound(AudioClip sound) {
+ if (!Platform.isFxApplicationThread()) {
+ throw new IllegalStateException("Must be on Fx thread");
+ }
+
+ if (getParentGrid() == null || !getParentGrid().isPlaying()) {
+ return;
+ }
+
+ //if (currentClip != null && currentClip.isPlaying()) {
+ // currentClip.stop();
+ //}
+ if (sound.isPlaying()) {
+ sound.stop();
+ }
+
+ //TODO: configure volume.
+
+ sound.play();
+ currentClip = sound;
+ }
+
+ /**
+ * Initializes the tile-set and image-view. This should ONLY be called
+ * exactly once in the component's lifetime.
+ *
+ * @param ts the tileset to initialize to.
+ */
+ private void initTileSet(TileSet ts) {
+ this.ts = ts;
+ currentImage = INVALID_IMAGE_FRAME;
+ img = new ImageView(ts.getImageSet());
+ this.getChildren().add(img);
+ }
+
/**
* Obtains next step of incrementing a value
*
diff --git a/Main/src/turtle/core/Grid.java b/Main/src/turtle/core/Grid.java
index 478019c..801975b 100644
--- a/Main/src/turtle/core/Grid.java
+++ b/Main/src/turtle/core/Grid.java
@@ -33,6 +33,7 @@ public class Grid extends Pane implements Serializable {
private int timeLeft;
private Direction lastMove;
private final Recording recording;
+ private boolean playing;
/**
@@ -181,6 +182,14 @@ public int getTimeLeft() {
return timeLeft;
}
+ public boolean isPlaying() {
+ return playing;
+ }
+
+ public void setPlaying(boolean playing) {
+ this.playing = playing;
+ }
+
/**
* Setter method for remaining time
*
diff --git a/Main/src/turtle/ui/GameUI.java b/Main/src/turtle/ui/GameUI.java
index 87c44ab..b2a2157 100644
--- a/Main/src/turtle/ui/GameUI.java
+++ b/Main/src/turtle/ui/GameUI.java
@@ -374,13 +374,8 @@ private void handleLevelDialog(int response) {
* occurred.
*/
private void handleKey(KeyEvent event) {
- if (state == HALTED) {
- return;
- }
- if (event.getEventType() == KeyEvent.KEY_TYPED) {
- return;
- }
- if (!mappedKeys.containsKey(event.getCode())) {
+ if (state == HALTED || event.getEventType() == KeyEvent.KEY_TYPED ||
+ !mappedKeys.containsKey(event.getCode())) {
return;
}
@@ -738,6 +733,7 @@ private void stopGame() {
runner.stop();
if (view.getGrid() != null) {
Recording r = view.getGrid().getRecording();
+ view.getGrid().setPlaying(false);
if (r != null) {
r.stop();
}
@@ -756,6 +752,7 @@ private void pauseGame() {
return;
}
state = PAUSED;
+ view.getGrid().setPlaying(false);
runner.pause();
for (int i = 0; i < moving.length; i++)
@@ -771,6 +768,7 @@ private void resumeGame() {
return;
}
state = RUNNING;
+ view.getGrid().setPlaying(true);
runner.start();
}
@@ -781,6 +779,7 @@ private void resumeGame() {
private void startGame() {
if (state == STOPPED) {
runner.start();
+ view.getGrid().setPlaying(true);
state = RUNNING;
}
}
diff --git a/Main/src/turtle/ui/MainApp.java b/Main/src/turtle/ui/MainApp.java
index e68fac0..ad13aa5 100644
--- a/Main/src/turtle/ui/MainApp.java
+++ b/Main/src/turtle/ui/MainApp.java
@@ -422,8 +422,7 @@ private void loadLevelPacks() {
}
}
if (!success) {
- showDialog(new DialogBoxUI("Unable to load some level packs.",
- "OK"));
+ showDialog(new DialogBoxUI("Unable to load some level packs.", "OK"));
}
}
diff --git a/test.mtp b/test.mtp
deleted file mode 100644
index c30f4f7..0000000
Binary files a/test.mtp and /dev/null differ