diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..dd7e86184cb7ae5719d9c962b11695dff38f1d4d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,72 @@
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+ .idea/artifacts
+ .idea/compiler.xml
+ .idea/jarRepositories.xml
+ .idea/modules.xml
+ .idea/*.iml
+ .idea/modules
+ *.iml
+ *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+target/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b0cd2d25b79649727a635f8910f50af91eb71428
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="ShadowDefend" />
+      </profile>
+    </annotationProcessing>
+    <bytecodeTargetLevel>
+      <module name="ShadowDefend" target="8" />
+    </bytecodeTargetLevel>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e289ef7b9995f4f64b5b69a8a322f44b4065c8b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73014cc22f76a442c58c5aac1f9ad5a849e598f0
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/ShadowDefend.iml" filepath="$PROJECT_DIR$/ShadowDefend.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94a25f7f4cb416c083d265558da75d457237d671
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/ShadowDefend.iml b/ShadowDefend.iml
new file mode 100644
index 0000000000000000000000000000000000000000..9a1ca0aa7dc327e07cd895e29fda9746a941e804
--- /dev/null
+++ b/ShadowDefend.iml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="bagel" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" />
+    <orderEntry type="library" name="bagel" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/lib/bagel.jar b/lib/bagel.jar
new file mode 100644
index 0000000000000000000000000000000000000000..ef0e60d3fac80814fdb3bb67fd7bfe3c6d0fcdfe
Binary files /dev/null and b/lib/bagel.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..578b8e1bdf48b60ca8a26277faf1eb28ae6d2d96
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>unimelb</groupId>
+  <artifactId>bagel</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>8</source>
+          <target>8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+    <sourceDirectory>${project.basedir}/src</sourceDirectory>
+    <resources>
+      <resource>
+        <directory>${project.basedir}/res</directory>
+      </resource>
+    </resources>
+  </build>
+
+  <properties>
+    <lwjgl.version>3.2.2</lwjgl.version>
+    <maven.compiler.source>8</maven.compiler.source>
+    <maven.compiler.target>8</maven.compiler.target>
+  </properties>
+
+  <profiles>
+    <profile>
+      <id>lwjgl-natives-linux</id>
+      <activation>
+        <os><family>unix</family></os>
+      </activation>
+      <properties>
+        <lwjgl.natives>natives-linux</lwjgl.natives>
+      </properties>
+    </profile>
+    <profile>
+      <id>lwjgl-natives-macos</id>
+      <activation>
+        <os><family>mac</family></os>
+      </activation>
+      <properties>
+        <lwjgl.natives>natives-macos</lwjgl.natives>
+      </properties>
+    </profile>
+    <profile>
+      <id>lwjgl-natives-windows</id>
+      <activation>
+        <os><family>windows</family></os>
+      </activation>
+      <properties>
+        <lwjgl.natives>natives-windows</lwjgl.natives>
+      </properties>
+    </profile>
+  </profiles>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-assimp</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-glfw</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-openal</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-opengl</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-stb</artifactId>
+      <version>${lwjgl.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-assimp</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-glfw</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-openal</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-opengl</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.lwjgl</groupId>
+      <artifactId>lwjgl-stb</artifactId>
+      <version>${lwjgl.version}</version>
+      <classifier>${lwjgl.natives}</classifier>
+    </dependency>
+  </dependencies>
+</project>
+
diff --git a/res/fonts/DejaVuSans-Bold.ttf b/res/fonts/DejaVuSans-Bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..c0d8e5e462df7f268efba09f6931e37daad151e1
Binary files /dev/null and b/res/fonts/DejaVuSans-Bold.ttf differ
diff --git a/res/images/airsupport.png b/res/images/airsupport.png
new file mode 100644
index 0000000000000000000000000000000000000000..d39258d6f8091223dee3b788676d44080e45951d
Binary files /dev/null and b/res/images/airsupport.png differ
diff --git a/res/images/apexslicer.png b/res/images/apexslicer.png
new file mode 100644
index 0000000000000000000000000000000000000000..eed1f6aab38f324ee412614f5871f44c3ef4c4ef
Binary files /dev/null and b/res/images/apexslicer.png differ
diff --git a/res/images/buypanel.png b/res/images/buypanel.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa91f718c832d88bb9dcc82ed59bfd93593d49ab
Binary files /dev/null and b/res/images/buypanel.png differ
diff --git a/res/images/explosive.png b/res/images/explosive.png
new file mode 100644
index 0000000000000000000000000000000000000000..8aee988de7127b0127bcad599e52af228f4cd84e
Binary files /dev/null and b/res/images/explosive.png differ
diff --git a/res/images/megaslicer.png b/res/images/megaslicer.png
new file mode 100644
index 0000000000000000000000000000000000000000..f07563e8b695ec3f862734bc7808814aae7f9325
Binary files /dev/null and b/res/images/megaslicer.png differ
diff --git a/res/images/slicer.png b/res/images/slicer.png
new file mode 100644
index 0000000000000000000000000000000000000000..71ab74fcbf4cffcccfb1c102f321bcc230c4fa30
Binary files /dev/null and b/res/images/slicer.png differ
diff --git a/res/images/statuspanel.png b/res/images/statuspanel.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ec7bd50783f604f3a4d2db4879b0a2da6b54696
Binary files /dev/null and b/res/images/statuspanel.png differ
diff --git a/res/images/superslicer.png b/res/images/superslicer.png
new file mode 100644
index 0000000000000000000000000000000000000000..9bd6b8e4229c195535839a520dbae62e5afa36aa
Binary files /dev/null and b/res/images/superslicer.png differ
diff --git a/res/images/supertank.png b/res/images/supertank.png
new file mode 100644
index 0000000000000000000000000000000000000000..09d6891d46d6cd20f379a8ec2c03849b6d934e3e
Binary files /dev/null and b/res/images/supertank.png differ
diff --git a/res/images/supertank_projectile.png b/res/images/supertank_projectile.png
new file mode 100644
index 0000000000000000000000000000000000000000..048e41525ef8f8ec0721861e5e3f1709cc9650ff
Binary files /dev/null and b/res/images/supertank_projectile.png differ
diff --git a/res/images/tank.png b/res/images/tank.png
new file mode 100644
index 0000000000000000000000000000000000000000..97a0495fd09545905b99a523562736a41a4704bc
Binary files /dev/null and b/res/images/tank.png differ
diff --git a/res/images/tank_projectile.png b/res/images/tank_projectile.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7adc3acaa822434acb4fb0e8f20e3ff53ae16f4
Binary files /dev/null and b/res/images/tank_projectile.png differ
diff --git a/res/levels/1.png b/res/levels/1.png
new file mode 100644
index 0000000000000000000000000000000000000000..db79e0791c1dcf252656aa34e7086ffa78b28596
Binary files /dev/null and b/res/levels/1.png differ
diff --git a/res/levels/1.tmx b/res/levels/1.tmx
new file mode 100644
index 0000000000000000000000000000000000000000..a3617a19d59c06fd7f53f4e69fc1fc0b0de6b299
--- /dev/null
+++ b/res/levels/1.tmx
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.2" tiledversion="1.3.3" orientation="orthogonal" renderorder="right-down" width="32" height="24" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="7">
+ <tileset firstgid="1" source="sheet.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="32" height="24">
+  <data encoding="csv">
+14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,1,2,2,2,2,2,2,2,3,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,7,7,7,7,7,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,4,12,12,12,5,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+2,2,2,2,2,2,2,10,7,9,2,2,2,10,7,8,14,14,1,2,2,2,2,2,2,2,3,14,14,14,14,14,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,14,14,6,7,7,7,7,7,7,7,8,14,14,14,14,14,
+12,12,12,12,12,12,12,5,7,4,12,12,12,12,12,13,14,14,6,7,4,12,12,12,5,7,8,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,14,14,14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,1,2,2,2,2,2,10,7,9,2,2,2,2,2,2,2,2,10,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,14,14,14,6,7,8,14,14,14,14,14,
+14,6,7,4,12,12,12,5,7,4,12,12,12,12,12,12,12,12,12,12,13,14,14,14,6,7,8,14,14,14,14,14,
+14,6,7,8,14,14,14,6,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,
+14,6,7,9,2,2,2,10,7,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,
+14,6,7,7,7,7,7,7,7,8,14,14,14,14,14,14,14,14,14,1,2,2,2,2,10,7,8,14,14,14,14,14,
+14,11,12,12,12,12,12,12,12,13,14,14,14,14,14,14,14,14,14,6,7,7,7,7,7,7,8,14,14,14,14,14,
+14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,6,7,4,12,12,12,12,13,14,14,14,14,14,
+14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,6,7,8,14,14,14,14,14,14,14,14,14,14
+</data>
+ </layer>
+ <objectgroup id="2" name="Object Layer 1">
+  <object id="6" x="1.33333" y="304">
+   <polyline points="-78.6667,1.33333 412,0 429.333,-1.33333 441.333,-6.66667 452,-14.6667 462.667,-28 464,-42.6667 464,-132 462.667,-144 453.333,-154.667 444,-160 288,-160 282.667,-160 274.667,-152 269.333,-142.667 266.667,-129.333 270.667,332 268,346.667 262.667,356 256,357.333 98.6667,357.333 90.6667,354.667 82.6667,353.333 78.6667,349.333 76,338.667 76,242.667 76,238.667 80,225.333 86.6667,221.333 572,224 588,222.667 600,222.667 605.333,218.667 617.333,208 625.333,200 624,49.3333 624,37.3333 625.333,26.6667 632,14.6667 646.667,2.66667 660,-1.33333 777.333,0 786.667,4 794.667,12 802.667,26.6667 808,34.6667 810.667,58.6667 816,338.667 813.333,353.333 808,370.667 797.333,380 778.667,386.667 705.333,386.667 693.333,384 677.333,386.667 666.667,394.667 658.667,408 654.667,425.333 650.667,445.333 652,462.667 652,500"/>
+  </object>
+ </objectgroup>
+</map>
diff --git a/res/levels/2.tmx b/res/levels/2.tmx
new file mode 100644
index 0000000000000000000000000000000000000000..44ed4c371e03e78612bf0e35bd7c3f0288d1b622
--- /dev/null
+++ b/res/levels/2.tmx
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.2" tiledversion="1.3.3" orientation="orthogonal" renderorder="right-down" width="32" height="24" tilewidth="32" tileheight="32" infinite="0" nextlayerid="1" nextobjectid="1">
+ <tileset firstgid="1" source="sheet2.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="32" height="24">
+  <data encoding="csv">
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+15,15,15,15,15,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+15,15,15,15,15,6,7,4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+15,15,15,15,15,6,7,9,3,15,15,15,15,15,15,1,2,2,2,2,2,2,2,2,2,3,15,15,15,15,15,15,
+15,15,15,15,15,11,5,7,9,3,15,15,15,15,15,6,7,7,7,7,7,7,7,7,7,8,15,15,15,15,15,15,
+15,15,15,15,15,15,11,5,7,9,3,15,15,15,15,6,7,4,12,12,12,12,12,5,7,8,15,15,15,15,15,15,
+15,15,15,15,15,15,15,11,5,7,9,3,15,15,15,6,7,8,15,15,15,15,1,10,7,8,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,11,5,7,9,3,15,15,6,7,8,15,15,15,1,10,7,4,13,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,11,5,7,9,3,15,6,7,8,15,15,1,10,7,4,13,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,11,5,7,9,3,6,7,8,15,1,10,7,4,13,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,11,5,7,9,10,7,8,15,6,7,4,13,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,11,5,7,7,7,8,15,6,7,8,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,11,12,12,12,13,15,6,7,8,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,6,7,8,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,6,7,8,15,15,15,15,15,15,15,15,15,15,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,10,7,8,15,15,15,15,15,15,15,15,15,15,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,15,15,15,15,15,15,15,15,15,15,
+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
+</data>
+ </layer>
+ <objectgroup id="5" name="polyline">
+  <object id="7" x="1064" y="176">
+   <polyline points="10.6667,0 -808,-1.33333 -828,1.33333 -842.662,12 -848,25.3333 -852,42.6667 -852,56 -842.662,78.6667 -610.662,310.667 -600,318.667 -588,320 -570.662,320 -558.662,318.667 -552,317.333 -542.662,310.667 -536,302.667 -536,133.333 -533.333,121.333 -526.662,112 -520,104 -506.661,100 -494.661,97.3333 -488,96 -308,97.3333 -301.333,98.6667 -296,105.333 -289.333,114.667 -284,130.667 -281.333,140 -282.661,154.667 -398.661,272 -405.333,280 -408,290.667 -408,301.333 -408,448.667 -414,474 -432.661,482 -1126.67,481.333"/>
+  </object>
+ </objectgroup>
+</map>
diff --git a/res/levels/sheet.png b/res/levels/sheet.png
new file mode 100644
index 0000000000000000000000000000000000000000..a52a0f3e898c69851b1a542ea3cf0b3d37033575
Binary files /dev/null and b/res/levels/sheet.png differ
diff --git a/res/levels/sheet.tsx b/res/levels/sheet.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4c476adf48a35cbff7fc8f74d2d8c22df9c1b4b8
--- /dev/null
+++ b/res/levels/sheet.tsx
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset version="1.2" tiledversion="1.3.3" name="sheet" tilewidth="32" tileheight="32" tilecount="20" columns="5">
+ <image source="sheet.png" width="160" height="128"/>
+ <tile id="0">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="1">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="2">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="3">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="4">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="5">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="6">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="7">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="8">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="9">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="10">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="11">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="12">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+ <tile id="15">
+  <properties>
+   <property name="blocked" value="true"/>
+  </properties>
+ </tile>
+</tileset>
diff --git a/res/levels/sheet2.png b/res/levels/sheet2.png
new file mode 100644
index 0000000000000000000000000000000000000000..911f59f762641f08cf3a265eb456544a1fa41708
Binary files /dev/null and b/res/levels/sheet2.png differ
diff --git a/res/levels/sheet2.tsx b/res/levels/sheet2.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f03daf8597f55a111a26c72bd15d1e71ba791034
--- /dev/null
+++ b/res/levels/sheet2.tsx
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset version="1.2" tiledversion="1.3.3" name="sheet2" tilewidth="32" tileheight="32" tilecount="15" columns="5">
+ <image source="sheet2.png" width="161" height="96"/>
+ <tile id="0">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="1">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="2">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="3">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="4">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="5">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="6">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="7">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="8">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="9">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="10">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="11">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="12">
+  <properties>
+   <property name="blocked" type="bool" value="true"/>
+  </properties>
+ </tile>
+</tileset>
diff --git a/res/levels/waves.txt b/res/levels/waves.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f38c84a611ead90df7029747ec12b83b0304a225
--- /dev/null
+++ b/res/levels/waves.txt
@@ -0,0 +1,21 @@
+1,spawn,20,slicer,1000
+2,spawn,5,slicer,1000
+2,delay,2500
+2,spawn,20,slicer,750
+3,spawn,5,superslicer,1000
+4,spawn,5,slicer,500
+4,delay,1000
+4,spawn,5,superslicer,500
+5,spawn,50,slicer,500
+5,delay,1000
+5,spawn,5,megaslicer,1000
+6,spawn,25,superslicer,500
+6,spawn,10,megaslicer,100
+6,delay,5000
+6,spawn,3,apexslicer,3000
+6,spawn,3,apexslicer,3000
+7,spawn,20,superslicer,250
+7,delay,1750
+7,spawn,10,megaslicer,2000
+7,delay,500
+7,spawn,5,apexslicer,1500
\ No newline at end of file
diff --git a/src/lists/ShadowDefend.java b/src/lists/ShadowDefend.java
new file mode 100644
index 0000000000000000000000000000000000000000..51cc58c57d43fd402737e97e8e18f6458d953e07
--- /dev/null
+++ b/src/lists/ShadowDefend.java
@@ -0,0 +1,132 @@
+package lists;
+
+import bagel.AbstractGame;
+import bagel.Input;
+import bagel.Keys;
+import bagel.Window;
+import bagel.map.TiledMap;
+import bagel.util.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+/**
+ * ShadowDefend, a tower defence game.
+ */
+public class ShadowDefend extends AbstractGame {
+
+    private static final int HEIGHT = 768;
+    private static final int WIDTH = 1024;
+    private static final String MAP_FILE = "res/levels/1.tmx";
+    // Change to suit system specifications. This could be
+    // dynamically determined but that is out of scope.
+    public static final double FPS = 60;
+    // The spawn delay (in seconds) to spawn slicers
+    private static final int SPAWN_DELAY = 5;
+    private static final int INTIAL_TIMESCALE = 1;
+    private static final int MAX_SLICERS = 5;
+    // Timescale is made static because it is a universal property of the game and the specification
+    // says everything in the game is affected by this
+    private static int timescale = INTIAL_TIMESCALE;
+    private final TiledMap map;
+    private final List<Point> polyline;
+    private final List<Slicer> slicers;
+    private double frameCount;
+    private int spawnedSlicers;
+    private boolean waveStarted;
+
+    /**
+     * Creates a new instance of the ShadowDefend game
+     */
+    public ShadowDefend() {
+        super(WIDTH, HEIGHT, "ShadowDefend");
+        this.map = new TiledMap(MAP_FILE);
+        this.polyline = map.getAllPolylines().get(0);
+        this.slicers = new ArrayList<>();
+        this.spawnedSlicers = 0;
+        this.waveStarted = false;
+        this.frameCount = Integer.MAX_VALUE;
+        // Temporary fix for the weird slicer map glitch (might have to do with caching textures)
+        // This fix is entirely optional
+        new Slicer(polyline);
+    }
+
+    /**
+     * The entry-point for the game
+     *
+     * @param args Optional command-line arguments
+     */
+    public static void main(String[] args) {
+        new ShadowDefend().run();
+    }
+
+    public static int getTimescale() {
+        return timescale;
+    }
+
+    /**
+     * Increases the timescale
+     */
+    private void increaseTimescale() {
+        timescale++;
+    }
+
+    /**
+     * Decreases the timescale but doesn't go below the base timescale
+     */
+    private void decreaseTimescale() {
+        if (timescale > INTIAL_TIMESCALE) {
+            timescale--;
+        }
+    }
+
+    /**
+     * Update the state of the game, potentially reading from input
+     *
+     * @param input The current mouse/keyboard state
+     */
+    @Override
+    protected void update(Input input) {
+        // Increase the frame counter by the current timescale
+        frameCount += getTimescale();
+
+        // Draw map from the top left of the window
+        map.draw(0, 0, 0, 0, WIDTH, HEIGHT);
+
+        // Handle key presses
+        if (input.wasPressed(Keys.S)) {
+            waveStarted = true;
+        }
+
+        if (input.wasPressed(Keys.L)) {
+            increaseTimescale();
+        }
+
+        if (input.wasPressed(Keys.K)) {
+            decreaseTimescale();
+        }
+
+        // Check if it is time to spawn a new slicer (and we have some left to spawn)
+        if (waveStarted && frameCount / FPS >= SPAWN_DELAY && spawnedSlicers != MAX_SLICERS) {
+            slicers.add(new Slicer(polyline));
+            spawnedSlicers += 1;
+            // Reset frame counter
+            frameCount = 0;
+        }
+
+        // Close game if all slicers have finished traversing the polyline
+        if (spawnedSlicers == MAX_SLICERS && slicers.isEmpty()) {
+            Window.close();
+        }
+
+        // Update all sprites, and remove them if they've finished
+        for (int i = slicers.size() - 1; i >= 0; i--) {
+            Slicer s = slicers.get(i);
+            s.update(input);
+            if (s.isFinished()) {
+                slicers.remove(i);
+            }
+        }
+    }
+}
diff --git a/src/lists/Slicer.java b/src/lists/Slicer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d89a7161b5cce107c528200c5566024faa29e7e
--- /dev/null
+++ b/src/lists/Slicer.java
@@ -0,0 +1,73 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+
+/**
+ * A regular slicer.
+ */
+public class Slicer extends Sprite {
+
+    private static final String IMAGE_FILE = "res/images/slicer.png";
+    private static final double SPEED = 1;
+
+    private final List<Point> polyline;
+    private int targetPointIndex;
+    private boolean finished;
+
+    /**
+     * Creates a new Slicer
+     *
+     * @param polyline The polyline that the slicer must traverse (must have at least 1 point)
+     */
+    public Slicer(List<Point> polyline) {
+        super(polyline.get(0), IMAGE_FILE);
+        this.polyline = polyline;
+        this.targetPointIndex = 1;
+        this.finished = false;
+    }
+
+    /**
+     * Updates the current state of the slicer. The slicer moves towards its next target point in
+     * the polyline at its specified movement rate.
+     */
+    @Override
+    public void update(Input input) {
+        if (finished) {
+            return;
+        }
+        // Obtain where we currently are, and where we want to be
+        Point currentPoint = getCenter();
+        Point targetPoint = polyline.get(targetPointIndex);
+        // Convert them to vectors to perform some very basic vector math
+        Vector2 target = targetPoint.asVector();
+        Vector2 current = currentPoint.asVector();
+        Vector2 distance = target.sub(current);
+        // Distance we are (in pixels) away from our target point
+        double magnitude = distance.length();
+        // Check if we are close to the target point
+        if (magnitude < SPEED * ShadowDefend.getTimescale()) {
+            // Check if we have reached the end
+            if (targetPointIndex == polyline.size() - 1) {
+                finished = true;
+                return;
+            } else {
+                // Make our focus the next point in the polyline
+                targetPointIndex += 1;
+            }
+        }
+        // Move towards the target point
+        // We do this by getting a unit vector in the direction of our target, and multiplying it
+        // by the speed of the slicer (accounting for the timescale)
+        super.move(distance.normalised().mul(SPEED * ShadowDefend.getTimescale()));
+        // Update current rotation angle to face target point
+        setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+    public boolean isFinished() {
+        return finished;
+    }
+}
diff --git a/src/lists/Sprite.java b/src/lists/Sprite.java
new file mode 100644
index 0000000000000000000000000000000000000000..88a7029bc8fdb83f98c1dd058d0f3d5c8dda18f4
--- /dev/null
+++ b/src/lists/Sprite.java
@@ -0,0 +1,59 @@
+package lists;
+
+import bagel.DrawOptions;
+import bagel.Image;
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Rectangle;
+import bagel.util.Vector2;
+
+/**
+ * Represents a game entity
+ */
+public abstract class Sprite {
+
+    private final Image image;
+    private final Rectangle rect;
+    private double angle;
+
+    /**
+     * Creates a new Sprite (game entity)
+     *
+     * @param point    The starting point for the entity
+     * @param imageSrc The image which will be rendered at the entity's point
+     */
+    public Sprite(Point point, String imageSrc) {
+        this.image = new Image(imageSrc);
+        this.rect = image.getBoundingBoxAt(point);
+        this.angle = 0;
+    }
+
+
+    public Rectangle getRect() {
+        return new Rectangle(rect);
+    }
+
+    /**
+     * Moves the Sprite by a specified delta
+     *
+     * @param dx The move delta vector
+     */
+    public void move(Vector2 dx) {
+        rect.moveTo(rect.topLeft().asVector().add(dx).asPoint());
+    }
+
+    public Point getCenter() {
+        return getRect().centre();
+    }
+
+    public void setAngle(double angle) {
+        this.angle = angle;
+    }
+
+    /**
+     * Updates the Sprite. Default behaviour is to render the Sprite at its current position.
+     */
+    public void update(Input input) {
+        image.draw(getCenter().x, getCenter().y, new DrawOptions().setRotation(angle));
+    }
+}
\ No newline at end of file
diff --git a/src/lists/UserInterface.java b/src/lists/UserInterface.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac0ea54c76b60e58395ccc0407b305b168b1d29b
--- /dev/null
+++ b/src/lists/UserInterface.java
@@ -0,0 +1,7 @@
+package lists;
+import javax.swing.*;
+
+public class UserInterface {
+
+    
+}