Commits

Jose Martinez committed d82d1ac

[no commit message]

  • Participants
  • Parent commits 740aada

Comments (0)

Files changed (14)

File defender/src/main/java/com/fxexperience/games/defender/BadGuy.java

-/*
- * Copyright (c) 2012, FX Experience. All rights  reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the author nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.fxexperience.games.defender;
-
-import javafx.animation.*;
-import javafx.collections.ListChangeListener;
-import javafx.collections.ObservableList;
-import javafx.event.ActionEvent;
-import javafx.event.EventHandler;
-import javafx.geometry.Point2D;
-import javafx.scene.paint.Color;
-import javafx.scene.shape.CubicCurveTo;
-import javafx.scene.shape.MoveTo;
-import javafx.scene.shape.Path;
-import javafx.scene.shape.Rectangle;
-import javafx.util.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BadGuy extends Sprite {
-
-    private static final Logger log = LoggerFactory.getLogger(BadGuy.class);
-
-    private Animation movement;
-    private ExitListener exitListener;
-
-    public BadGuy() {
-
-        Rectangle body = new Rectangle(0, 0, 40, 40);
-        body.setArcHeight(6);
-        body.setArcWidth(6);
-        body.setFill(Color.BLUE);
-        getChildren().add(body);
-
-        exitListener = new ExitListener();
-    }
-
-    @Override
-    public void setLevel(Level level) {
-
-        if (movement != null) {
-            movement.stop();
-        }
-        if (this.level != null) {
-            this.level.getExits().removeListener(exitListener);
-        }
-
-        super.setLevel(level);
-
-        if (level != null) {
-            findPathToNearestExit();
-            level.getExits().addListener(exitListener);
-        }
-    }
-
-    protected void findPathToNearestExit() {
-
-        if (movement != null) {
-            movement.stop();
-        }
-
-        // just use the first available exit for now - this whole path selection needs to get smarter
-        ObservableList<Point2D> exits = level.getExits();
-        Point2D exit = exits.get(0);
-        log.debug("BadGuy is now heading for exit at {}", exit);
-
-        Path path = new Path();
-        path.getElements().add(new MoveTo(0, 0));
-        CubicCurveTo curve = new CubicCurveTo();
-        curve.setControlX1(exit.getX() * Math.random());
-        curve.setControlY1(exit.getY() * Math.random());
-        curve.setX(exit.getX());
-        curve.setY(exit.getY());
-        path.getElements().add(curve);
-
-        PathTransition pathTransition = new PathTransition();
-        pathTransition.setDuration(Duration.millis((Math.random() * 20000) + 5000));
-        pathTransition.setPath(path);
-        pathTransition.setNode(BadGuy.this);
-        pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
-
-        pathTransition.setOnFinished(new EventHandler<ActionEvent>() {
-            @Override
-            public void handle(ActionEvent actionEvent) {
-                level.removeBadGuy(BadGuy.this);
-            }
-        });
-
-        movement = pathTransition;
-        movement.play();
-
-    }
-
-    //-------------------------------------------------------------------------
-
-    private class ExitListener implements ListChangeListener<Point2D> {
-
-        @Override
-        public void onChanged(Change<? extends Point2D> change) {
-            findPathToNearestExit();
-        }
-    }
-
-}

File defender/src/main/java/com/fxexperience/games/defender/DefaultLevelFactory.java

-/*
- * Copyright (c) 2012, FX Experience. All rights  reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the author nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.fxexperience.games.defender;
-
-public class DefaultLevelFactory implements LevelFactory {
-
-    @Override
-    public Level createLevel() {
-        return new SimpleLevel();
-    }
-}

File defender/src/main/java/com/fxexperience/games/defender/DefenderApp.java

  */
 package com.fxexperience.games.defender;
 
+import com.fxexperience.games.defender.level.DefaultLevelFactory;
+import com.fxexperience.games.defender.level.LevelFactory;
+import com.fxexperience.games.defender.level.Level;
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;

File defender/src/main/java/com/fxexperience/games/defender/Level.java

-/*
- * Copyright (c) 2012, FX Experience. All rights  reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the author nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.fxexperience.games.defender;
-
-import javafx.application.Platform;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import javafx.concurrent.Task;
-import javafx.geometry.Point2D;
-import javafx.scene.Group;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public abstract class Level extends Group {
-
-    private static final Logger log = LoggerFactory.getLogger(Level.class);
-
-    private ObservableList<BadGuy> badGuys;
-    private ObservableList<Tower> towers;
-    private ObservableList<Point2D> exits;
-
-    public Level() {
-        badGuys = FXCollections.observableArrayList();
-        towers = FXCollections.observableArrayList();
-        exits = FXCollections.observableArrayList();
-    }
-
-    public abstract void start();
-
-    public void addBadGuy(BadGuy badGuy) {
-        badGuy.setLevel(this);
-        badGuys.add(badGuy);
-        // probably could do some clever binding instead of this...
-        getChildren().add(badGuy);
-        log.debug("BadGuy added to level, we now have {} BadGuys on the Level", badGuys.size());
-    }
-
-    public void removeBadGuy(BadGuy badGuy) {
-        badGuy.setLevel(null);
-        badGuys.remove(badGuy);
-        // probably could do some clever binding instead of this...
-        getChildren().remove(badGuy);
-        log.debug("BadGuy removed from level, we now have {} BadGuys on the Level", badGuys.size());
-    }
-
-
-    public void setExits(Point2D... exits) {
-        this.exits.setAll(exits);
-    }
-
-    public ObservableList<Point2D> getExits() {
-        return exits;
-    }
-
-}

File defender/src/main/java/com/fxexperience/games/defender/LevelFactory.java

-/*
-* Copyright (c) 2012, FX Experience. All rights  reserved.
-*
-* Redistribution and use in source and binary forms, with or without modification, are
-* permitted provided that the following conditions are met:
-*
-* Redistributions of source code must retain the above copyright notice, this list of
-* conditions and the following disclaimer. 
-*
-* Redistributions in binary form must reproduce the above copyright notice, this list of 
-* conditions and the following disclaimer in the documentation and/or other materials provided 
-* with the distribution.    
-*
-* Neither the name of the author nor the names of its contributors may be used to endorse or
-* promote products derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
-* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-package com.fxexperience.games.defender;
-
-public interface LevelFactory {
-
-    Level createLevel();
-}

File defender/src/main/java/com/fxexperience/games/defender/SimpleLevel.java

-/*
- * Copyright (c) 2012, FX Experience. All rights  reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the author nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.fxexperience.games.defender;
-
-import javafx.application.Platform;
-import javafx.geometry.Bounds;
-import javafx.geometry.Point2D;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Very simple level just for testing the basics. More interesting levels can be added later.
- */
-public class SimpleLevel extends Level {
-
-    private static final Logger log = LoggerFactory.getLogger(SimpleLevel.class);
-
-    public void start() {
-
-        log.info("Starting SimpleLevel, adding BadGuys at random intervals ");
-
-        // just hard code exit point for now - need to define a level size at some point
-        setExits(new Point2D(800, 500));
-
-        // loop and add BadGuys forever (normally would be for a set amount of BadGuys until level is finished)
-        Thread thread = new Thread() {
-            @Override
-            public void run() {
-
-                while (true) {
-
-                    // need to add the BadGuy in the JFX Thread
-                    Platform.runLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            addBadGuy(new BadGuy());
-                        }
-                    });
-
-                    // create a new BadGuy at random intervals
-                    try {
-                        long delay = (long) (Math.random() * 5000) + 100;
-                        log.debug("Next BadGuy will be added in {} seconds", delay/1000);
-                        Thread.sleep(delay);
-                    } catch (InterruptedException e) {
-                        // shouldn't happen, and if it does we don't care
-                    }
-
-                }
-            }
-        };
-        thread.start();
-    }
-
-}

File defender/src/main/java/com/fxexperience/games/defender/Sprite.java

  */
 package com.fxexperience.games.defender;
 
+import com.fxexperience.games.defender.level.Level;
 import javafx.scene.Group;
 
 public class Sprite extends Group {

File defender/src/main/java/com/fxexperience/games/defender/Tower.java

-/*
- * Copyright (c) 2012, FX Experience. All rights  reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the author nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.fxexperience.games.defender;
-
-public class Tower extends Sprite {
-}

File defender/src/main/java/com/fxexperience/games/defender/level/DefaultLevelFactory.java

+/*
+ * Copyright (c) 2012, FX Experience. All rights  reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.fxexperience.games.defender.level;
+
+import com.fxexperience.games.defender.level.LevelFactory;
+import com.fxexperience.games.defender.level.SimpleLevel;
+import com.fxexperience.games.defender.level.Level;
+
+public class DefaultLevelFactory implements LevelFactory {
+
+    @Override
+    public Level createLevel() {
+        return new SimpleLevel();
+    }
+}

File defender/src/main/java/com/fxexperience/games/defender/level/Level.java

+/*
+ * Copyright (c) 2012, FX Experience. All rights  reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.fxexperience.games.defender.level;
+
+import com.fxexperience.games.defender.unit.BadGuy;
+import com.fxexperience.games.defender.tower.Tower;
+import javafx.application.Platform;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.concurrent.Task;
+import javafx.geometry.Point2D;
+import javafx.scene.Group;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class Level extends Group {
+
+    private static final Logger log = LoggerFactory.getLogger(Level.class);
+
+    private ObservableList<BadGuy> badGuys;
+    private ObservableList<Tower> towers;
+    private ObservableList<Point2D> exits;
+
+    public Level() {
+        badGuys = FXCollections.observableArrayList();
+        towers = FXCollections.observableArrayList();
+        exits = FXCollections.observableArrayList();
+    }
+
+    public abstract void start();
+
+    public void addBadGuy(BadGuy badGuy) {
+        badGuy.setLevel(this);
+        badGuys.add(badGuy);
+        // probably could do some clever binding instead of this...
+        getChildren().add(badGuy);
+        log.debug("BadGuy added to level, we now have {} BadGuys on the Level", badGuys.size());
+    }
+
+    public void removeBadGuy(BadGuy badGuy) {
+        badGuy.setLevel(null);
+        badGuys.remove(badGuy);
+        // probably could do some clever binding instead of this...
+        getChildren().remove(badGuy);
+        log.debug("BadGuy removed from level, we now have {} BadGuys on the Level", badGuys.size());
+    }
+
+
+    public void setExits(Point2D... exits) {
+        this.exits.setAll(exits);
+    }
+
+    public ObservableList<Point2D> getExits() {
+        return exits;
+    }
+
+}

File defender/src/main/java/com/fxexperience/games/defender/level/LevelFactory.java

+/*
+* Copyright (c) 2012, FX Experience. All rights  reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are
+* permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer. 
+*
+* Redistributions in binary form must reproduce the above copyright notice, this list of 
+* conditions and the following disclaimer in the documentation and/or other materials provided 
+* with the distribution.    
+*
+* Neither the name of the author nor the names of its contributors may be used to endorse or
+* promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+package com.fxexperience.games.defender.level;
+
+import com.fxexperience.games.defender.level.Level;
+
+public interface LevelFactory {
+
+    Level createLevel();
+}

File defender/src/main/java/com/fxexperience/games/defender/level/SimpleLevel.java

+/*
+ * Copyright (c) 2012, FX Experience. All rights  reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.fxexperience.games.defender.level;
+
+import com.fxexperience.games.defender.unit.BadGuy;
+import com.fxexperience.games.defender.level.Level;
+import javafx.application.Platform;
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Very simple level just for testing the basics. More interesting levels can be added later.
+ */
+public class SimpleLevel extends Level {
+
+    private static final Logger log = LoggerFactory.getLogger(SimpleLevel.class);
+
+    public void start() {
+
+        log.info("Starting SimpleLevel, adding BadGuys at random intervals ");
+
+        // just hard code exit point for now - need to define a level size at some point
+        setExits(new Point2D(800, 500));
+
+        // loop and add BadGuys forever (normally would be for a set amount of BadGuys until level is finished)
+        Thread thread = new Thread() {
+            @Override
+            public void run() {
+
+                while (true) {
+
+                    // need to add the BadGuy in the JFX Thread
+                    Platform.runLater(new Runnable() {
+                        @Override
+                        public void run() {
+                            addBadGuy(new BadGuy());
+                        }
+                    });
+
+                    // create a new BadGuy at random intervals
+                    try {
+                        long delay = (long) (Math.random() * 5000) + 100;
+                        log.debug("Next BadGuy will be added in {} seconds", delay/1000);
+                        Thread.sleep(delay);
+                    } catch (InterruptedException e) {
+                        // shouldn't happen, and if it does we don't care
+                    }
+
+                }
+            }
+        };
+        thread.start();
+    }
+
+}

File defender/src/main/java/com/fxexperience/games/defender/tower/Tower.java

+/*
+ * Copyright (c) 2012, FX Experience. All rights  reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.fxexperience.games.defender.tower;
+
+import com.fxexperience.games.defender.Sprite;
+
+public class Tower extends Sprite {
+}

File defender/src/main/java/com/fxexperience/games/defender/unit/BadGuy.java

+/*
+ * Copyright (c) 2012, FX Experience. All rights  reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.fxexperience.games.defender.unit;
+
+import com.fxexperience.games.defender.Sprite;
+import com.fxexperience.games.defender.level.Level;
+import javafx.animation.*;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.Point2D;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.CubicCurveTo;
+import javafx.scene.shape.MoveTo;
+import javafx.scene.shape.Path;
+import javafx.scene.shape.Rectangle;
+import javafx.util.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BadGuy extends Sprite {
+
+    private static final Logger log = LoggerFactory.getLogger(BadGuy.class);
+
+    private Animation movement;
+    private ExitListener exitListener;
+
+    public BadGuy() {
+
+        Rectangle body = new Rectangle(0, 0, 40, 40);
+        body.setArcHeight(6);
+        body.setArcWidth(6);
+        body.setFill(Color.BLUE);
+        getChildren().add(body);
+
+        exitListener = new ExitListener();
+    }
+
+    @Override
+    public void setLevel(Level level) {
+
+        if (movement != null) {
+            movement.stop();
+        }
+        if (this.level != null) {
+            this.level.getExits().removeListener(exitListener);
+        }
+
+        super.setLevel(level);
+
+        if (level != null) {
+            findPathToNearestExit();
+            level.getExits().addListener(exitListener);
+        }
+    }
+
+    protected void findPathToNearestExit() {
+
+        if (movement != null) {
+            movement.stop();
+        }
+
+        // just use the first available exit for now - this whole path selection needs to get smarter
+        ObservableList<Point2D> exits = level.getExits();
+        Point2D exit = exits.get(0);
+        log.debug("BadGuy is now heading for exit at {}", exit);
+
+        Path path = new Path();
+        path.getElements().add(new MoveTo(0, 0));
+        CubicCurveTo curve = new CubicCurveTo();
+        curve.setControlX1(exit.getX() * Math.random());
+        curve.setControlY1(exit.getY() * Math.random());
+        curve.setX(exit.getX());
+        curve.setY(exit.getY());
+        path.getElements().add(curve);
+
+        PathTransition pathTransition = new PathTransition();
+        pathTransition.setDuration(Duration.millis((Math.random() * 20000) + 5000));
+        pathTransition.setPath(path);
+        pathTransition.setNode(BadGuy.this);
+        pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
+
+        pathTransition.setOnFinished(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(ActionEvent actionEvent) {
+                level.removeBadGuy(BadGuy.this);
+            }
+        });
+
+        movement = pathTransition;
+        movement.play();
+
+    }
+
+    //-------------------------------------------------------------------------
+
+    private class ExitListener implements ListChangeListener<Point2D> {
+
+        @Override
+        public void onChanged(Change<? extends Point2D> change) {
+            findPathToNearestExit();
+        }
+    }
+
+}