Browse Source

added snuvi text for text rendering, menu for level choosing, starting of levels over the menu, refactoring (code moved from WorldRenderer to Level)

Kajetan Johannes Hammerle 6 years ago
parent
commit
1ec3d181cf

+ 1 - 1
test.map → levels/00.map

@@ -26,4 +26,4 @@
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/01.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/02.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/03.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/04.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/05.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/06.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/07.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/08.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/09.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/10.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/11.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/12.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/13.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 29 - 0
levels/14.map

@@ -0,0 +1,29 @@
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#
+2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
+2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1
+2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1
+#
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

+ 3 - 3
src/me/hammerle/supersnuvi/entity/AnimatedEntity.java

@@ -2,7 +2,7 @@ package me.hammerle.supersnuvi.entity;
 
 import javafx.scene.image.Image;
 import javafx.scene.paint.Color;
-import me.hammerle.supersnuvi.rendering.WorldRenderer;
+import me.hammerle.supersnuvi.gamelogic.Level;
 import me.hammerle.supersnuvi.util.Utils;
 
 public class AnimatedEntity extends Entity
@@ -17,9 +17,9 @@ public class AnimatedEntity extends Entity
     private Image[] leftAir;
     private Image[] rightAir;
     
-    public AnimatedEntity(WorldRenderer map, double x, double y, double width, double height) 
+    public AnimatedEntity(Level level, double x, double y, double width, double height) 
     {
-        super(map, x, y, width, height);
+        super(level, x, y, width, height);
         counter = 0;
         frame = 0;
         left = new Image[3];

+ 9 - 8
src/me/hammerle/supersnuvi/entity/Entity.java

@@ -3,9 +3,10 @@ package me.hammerle.supersnuvi.entity;
 import java.util.LinkedList;
 import javafx.scene.image.Image;
 import javafx.scene.paint.Color;
+import me.hammerle.supersnuvi.gamelogic.Level;
 import me.hammerle.supersnuvi.input.IKeyHandler;
 import me.hammerle.supersnuvi.rendering.GameRenderer;
-import me.hammerle.supersnuvi.rendering.WorldRenderer;
+import me.hammerle.supersnuvi.gamelogic.StateRenderer;
 import me.hammerle.supersnuvi.tiles.Location;
 import me.hammerle.supersnuvi.util.CollisionBox;
 import me.hammerle.supersnuvi.util.Face;
@@ -37,11 +38,11 @@ public class Entity
     
     private Image image;
     
-    private WorldRenderer world;
+    private Level level;
     
-    public Entity(WorldRenderer map, double x, double y, double width, double height)
+    public Entity(Level level, double x, double y, double width, double height)
     {
-        this.world = map;
+        this.level = level;
         this.posX = x;
         this.posY = y;
         this.prevPosX = x;
@@ -96,7 +97,7 @@ public class Entity
             motionX *= 0.7;
         }
         
-        LinkedList<CollisionBox> list = world.getCollisionBoxesAt(this, getBox());
+        LinkedList<CollisionBox> list = level.getCollisionBoxesAt(this, getBox());
         if(!list.isEmpty())
         {
             System.out.println(getBox());
@@ -173,7 +174,7 @@ public class Entity
         // expanding area by the size of the entity
         CollisionBox expandedBox = eBox.copy().expand(motionX, motionY);
         
-        LinkedList<CollisionBox> allBoxes = world.getCollisionBoxesAt(this, expandedBox);
+        LinkedList<CollisionBox> allBoxes = level.getCollisionBoxesAt(this, expandedBox);
         if(allBoxes.isEmpty())
         {
             return;
@@ -453,8 +454,8 @@ public class Entity
         {
             box.reset();
             box.expand(f.getCollisionOffsetX(), f.getCollisionOffsetY());
-            world.getEntitiesCollidingWith(this, box).forEach(ent -> this.onCollideWithEntity(ent, f));
-            world.getTilesCollidingWith(box).forEach(loc -> 
+            level.getEntitiesCollidingWith(this, box).forEach(ent -> this.onCollideWithEntity(ent, f));
+            level.getTilesCollidingWith(box).forEach(loc -> 
             {
                 this.onCollideWithTile(loc, f);
                 loc.getTile().onEntityCollide(this, loc.getX(), loc.getY(), f);

+ 3 - 3
src/me/hammerle/supersnuvi/entity/Hero.java

@@ -1,14 +1,14 @@
 package me.hammerle.supersnuvi.entity;
 
 import javafx.scene.input.KeyCode;
+import me.hammerle.supersnuvi.gamelogic.Level;
 import me.hammerle.supersnuvi.input.IKeyHandler;
-import me.hammerle.supersnuvi.rendering.WorldRenderer;
 
 public class Hero extends AnimatedEntity
 {
-    public Hero(WorldRenderer map, double x, double y, double width, double height) 
+    public Hero(Level level,  double x, double y, double width, double height) 
     {
-        super(map, x, y, width, height);
+        super(level, x, y, width, height);
     }
 
     @Override

+ 359 - 0
src/me/hammerle/supersnuvi/gamelogic/Level.java

@@ -0,0 +1,359 @@
+package me.hammerle.supersnuvi.gamelogic;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import me.hammerle.supersnuvi.entity.Entity;
+import me.hammerle.supersnuvi.entity.Hero;
+import me.hammerle.supersnuvi.input.IKeyHandler;
+import me.hammerle.supersnuvi.rendering.IGameRenderer;
+import me.hammerle.supersnuvi.tiles.Location;
+import me.hammerle.supersnuvi.tiles.Tile;
+import me.hammerle.supersnuvi.util.CollisionBox;
+
+public class Level 
+{
+    private final StateRenderer state;
+    private final IGameRenderer renderer;
+    
+    private final String name;
+    
+    private boolean worldLoaded;
+    
+    private int width;
+    private int height;
+    private int[][] background;
+    private int[][] background2;
+    private int[][] foreground;
+    
+    private final HashMap<Integer, Entity> entities;
+    private int entityCounter;
+    
+    public Level(StateRenderer state, File f)
+    {
+        this.state = state;
+        this.renderer = state.getRenderer();
+        this.name = getNiceName(f.getName());
+        this.worldLoaded = loadMap(f);
+        this.entities = new HashMap<>();
+        this.entityCounter = 0;
+        
+        // test spawning
+        Entity ent = new Entity(this, 80, 340, 32, 64);
+        Hero hero = new Hero(this, 32, 100, 32, 48);
+        entities.put(entityCounter++, ent);
+        entities.put(entityCounter++, hero);
+    }
+    
+    private String getNiceName(String badName)
+    {
+        int i = badName.indexOf('.');
+        if(i != -1)
+        {
+            badName = badName.substring(0, i);
+        }
+        return badName.replace("_", " ");
+    }
+    
+    // -------------------------------------------------------------------------
+    // basic stuff
+    // -------------------------------------------------------------------------
+
+    public String getName() 
+    {
+        return name;
+    }
+    
+    // -------------------------------------------------------------------------
+    // map loading
+    // -------------------------------------------------------------------------
+    
+    private void printError(File f, String message)
+    {
+        System.err.println("level error '" + f + "' - " + message);
+        width = 0;
+        height = 0;
+        background = null;
+        background2 = null;
+        foreground = null;
+        worldLoaded = false;
+    }
+    
+    private boolean loadMap(File f)
+    {
+        if(!f.exists())
+        {
+            printError(f, "level does not exist");
+            return false;
+        }
+        List<String> strings;
+        try
+        {
+            strings = Files.readAllLines(f.toPath());
+        } 
+        catch(IOException ex) 
+        {
+            printError(f, "IOException on load");
+            return false;
+        }
+        if(strings.isEmpty())
+        {
+            printError(f, "level is empty");
+            return false;
+        }
+        // assuming we have the following format
+        // X, X, X
+        // X, X, X
+        // #
+        // X, X, X
+        // X, X, X
+        // #
+        // X, X, X
+        // X, X, X
+        int size = strings.size();
+        
+        int first = 0;
+        while(true)
+        {
+            if(first >= size)
+            {
+                printError(f, "missing first #");
+                return false;
+            }
+            if(strings.get(first).equals("#"))
+            {
+                break;
+            }
+            first++;
+        }
+        int second = first + 1;
+        while(true)
+        {
+            if(second >= size)
+            {
+                printError(f, "missing second #");
+                return false;
+            }
+            if(strings.get(second).equals("#"))
+            {
+                break;
+            }
+            second++;
+        }
+        
+        if(first == 0 || first != second - first - 1 || second - first - 1 != size - second - 1)
+        {
+            printError(f, "invalid number of lines");
+            return false;
+        }
+        
+        height = first;
+        int i = 0;
+        int mod = first - 1;
+        try
+        {
+            // background 1
+            String[] parts = strings.get(i).split("[ ]*,[ ]*");
+            width = parts.length;
+            background = new int[width][height];
+            for(int j = 0; j < parts.length; j++)
+            {
+                background[j][mod - i] = Integer.parseInt(parts[j]);
+            }
+            i++;
+            while(i < first)
+            {
+                parts = strings.get(i).split("[ ]*,[ ]*");
+                if(parts.length != width)
+                {
+                    printError(f, "invalid number of line entries");
+                    return false;
+                }
+                for(int j = 0; j < parts.length; j++)
+                {
+                    background[j][mod - i] = Integer.parseInt(parts[j]);
+                }
+                i++;
+            }
+
+            // background 2
+            i++;
+            mod = second - 1;
+            background2 = new int[width][height];
+            while(i < second)
+            {
+                parts = strings.get(i).split("[ ]*,[ ]*");
+                if(parts.length != width)
+                {
+                    printError(f, "invalid number of line entries");
+                    return false;
+                }
+                for(int j = 0; j < parts.length; j++)
+                {
+                    background2[j][mod - i] = Integer.parseInt(parts[j]);
+                }
+                i++;
+            }
+
+            // foreground
+            i++;
+            mod = size - 1;
+            foreground = new int[width][height];
+            while(i < size)
+            {
+                parts = strings.get(i).split("[ ]*,[ ]*");
+                if(parts.length != width)
+                {
+                    printError(f, "invalid number of line entries");
+                    return false;
+                }
+                for(int j = 0; j < parts.length; j++)
+                {
+                    foreground[j][mod - i] = Integer.parseInt(parts[j]);
+                }
+                i++;
+            }
+            return true;
+        }
+        catch(NumberFormatException ex)
+        {
+            printError(f, "invalid number format on line " + (i + 1));
+            return false;
+        }
+    }
+    
+    // -------------------------------------------------------------------------
+    // tick
+    // -------------------------------------------------------------------------
+    
+    public void tick(long delta, IKeyHandler keys)
+    {
+        if(worldLoaded)
+        {
+            // doing entity logic first
+            entities.values().forEach(entity -> 
+            {
+                entity.controlTick(keys);
+                entity.tick(delta);
+            });
+
+            int startX = renderer.getFirstVisibleBlockX();
+            int startY = renderer.getFirstVisibleBlockY();
+            int endX = Math.min(renderer.getLastVisibleBlockX() + 1, width);
+            int endY = Math.min(renderer.getLastVisibleBlockY() + 1, height);
+            
+            int id;
+            for(int x = startX; x < endX; x++)
+            {
+                for(int y = startY; y < endY; y++)
+                {
+                    id = background[x][y];
+                    if(id != -1)
+                    {
+                        renderer.drawBlockImage(state.getTile(id), x, y);
+                    }
+                    id = background2[x][y];
+                    if(id != -1)
+                    {
+                        renderer.drawBlockImage(state.getTile(id), x, y);
+                    }
+                }
+            }
+            
+            // render entities here
+            entities.values().forEach(en -> renderer.drawImage(en.getImage(), en.getRenderX(), en.getRenderY()));
+            // end entity rendering
+            
+            for(int x = startX; x < endX; x++)
+            {
+                for(int y = startY; y < endY; y++)
+                {
+                    id = foreground[x][y];
+                    if(id != -1)
+                    {
+                        renderer.drawBlockImage(state.getTile(id), x, y);
+                    }
+                }
+            }
+        }
+    }   
+    
+    // -------------------------------------------------------------------------
+    // collision box, interaction layer
+    // -------------------------------------------------------------------------
+    
+    public Tile getInteractionTile(int x, int y)
+    {
+        if(x < 0 || y < 0 || x >= width || y >= height)
+        {
+            return Tile.FALLBACK_TILE;
+        }
+        return state.getInteractionTile(background2[x][y]);
+    }
+    
+    public CollisionBox getTileCollisionBox(int x, int y)
+    {
+        if(x < 0 || y < 0 || x >= width || y >= height)
+        {
+            return CollisionBox.NULL_BOX;
+        }
+        Tile tile = state.getInteractionTile(background2[x][y]);
+        return tile.getCollisionBox().reset().offset(renderer.toCoord(x), renderer.toCoord(y));
+    }
+    
+    public LinkedList<Location> getTilesCollidingWith(CollisionBox cb)
+    {
+        LinkedList<Location> boxes = new LinkedList<>();
+        int startX = renderer.toBlock(cb.getMinX());
+        int endX = renderer.toBlock(cb.getMaxX());
+        int startY = renderer.toBlock(cb.getMinY());
+        int endY = renderer.toBlock(cb.getMaxY());
+        
+        for(int x = startX; x <= endX; x++)
+        {
+            for(int y = startY; y <= endY; y++)
+            {
+                if(getTileCollisionBox(x, y).intersects(cb))
+                {
+                    boxes.add(new Location(getInteractionTile(x, y), x, y));
+                }
+            }
+        }
+        return boxes;
+    }
+    
+    public List<Entity> getEntitiesCollidingWith(Entity not, CollisionBox cb)
+    {
+        return entities.values().stream().filter(ent -> ent != not && ent.getBox().intersects(cb)).collect(Collectors.toList());
+    }
+    
+    public LinkedList<CollisionBox> getCollisionBoxesAt(Entity not, CollisionBox cb)
+    {
+        LinkedList<CollisionBox> boxes = new LinkedList<>(entities.values().stream()
+                        .filter(ent -> ent != not && ent.getBox().intersects(cb))
+                        .map(ent -> ent.getBox())
+                        .collect(Collectors.toList()));
+        int startX = renderer.toBlock(cb.getMinX());
+        int endX = renderer.toBlock(cb.getMaxX());
+        int startY = renderer.toBlock(cb.getMinY());
+        int endY = renderer.toBlock(cb.getMaxY());
+        
+        CollisionBox box;
+        for(int x = startX; x <= endX; x++)
+        {
+            for(int y = startY; y <= endY; y++)
+            {
+                box = getTileCollisionBox(x, y);
+                if(box.intersects(cb))
+                {
+                    boxes.add(box.copy());
+                }
+            }
+        }
+        return boxes;
+    }
+}

+ 260 - 0
src/me/hammerle/supersnuvi/gamelogic/StateRenderer.java

@@ -0,0 +1,260 @@
+package me.hammerle.supersnuvi.gamelogic;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+import javafx.scene.image.Image;
+import javafx.scene.image.WritableImage;
+import javafx.scene.input.KeyCode;
+import javafx.scene.paint.Color;
+import me.hammerle.supersnuvi.input.IKeyHandler;
+import me.hammerle.supersnuvi.rendering.IGameRenderer;
+import me.hammerle.supersnuvi.tiles.Ice;
+import me.hammerle.supersnuvi.tiles.TrampolinTile;
+import me.hammerle.supersnuvi.tiles.Tile;
+
+public class StateRenderer
+{
+    // constants
+    private static final Image FALLBACK_IMAGE = new WritableImage(1, 1);
+    
+    // rendering
+    private IGameRenderer renderer;   
+    
+    // tiles
+    private HashMap<Integer, Tile> registeredTiles;
+    
+    // levels
+    private Level currentLevel;
+    private Level[] levels;
+    private int levelIndex;
+    
+    public StateRenderer(IGameRenderer renderer)
+    {
+        this.renderer = renderer;
+        this.registeredTiles = new HashMap<>();
+        
+        File[] files = new File("./levels").listFiles();
+        Arrays.sort(files, (o1, o2) -> o1.compareTo(o2));
+        levels = new Level[files.length];
+        for(int i = 0; i < levels.length; i++)
+        {
+            levels[i] = new Level(this, files[i]);
+        }
+        currentLevel = null;
+        levelIndex = 0;
+        
+        registerTiles();
+    }    
+
+    // -------------------------------------------------------------------------
+    // tile stuff
+    // -------------------------------------------------------------------------
+    
+    private void registerTile(int id, int r, int g, int b, int opacity)
+    {
+        registeredTiles.put(id, new Tile(new Color(r / 255d, g / 255d, b / 255d, opacity / 255d)));
+    }
+    
+    private void registerTiles()
+    {
+        registeredTiles.put(1, new Tile("air"));
+        registeredTiles.put(2, new Tile("dirt").setDefaultCollisionBox());
+        registeredTiles.put(3, new Tile("grass").setDefaultCollisionBox());
+        
+        registeredTiles.put(4, new TrampolinTile().setDefaultCollisionBox());
+        registeredTiles.put(5, new Ice().setDefaultCollisionBox());
+        registerTile(6, 255, 255, 0, 255);
+        registerTile(7, 255, 255, 255, 255);
+    }
+    
+    public Image getTile(int id)
+    {
+        Tile tile = registeredTiles.get(id);
+        if(tile == null)
+        {
+            return FALLBACK_IMAGE;
+        }
+        return tile.getImage();
+    }
+    
+    public Tile getInteractionTile(int id)
+    {
+        return registeredTiles.getOrDefault(id, Tile.FALLBACK_TILE);
+    }
+    
+    // -------------------------------------------------------------------------
+    // tick, rendering
+    // -------------------------------------------------------------------------
+
+    public IGameRenderer getRenderer() 
+    {
+        return renderer;
+    }
+    
+    private static final int MENU_WIDTH = 26;
+    private static final int MENU_X = 12;
+    private static final int MENU_Y = 5;
+    private static final int MENU_MAX = 11;
+    private static final char[] TABLE_TOP = getCharLine((char) 131, (char) 136, MENU_WIDTH - 2, (char) 133);
+    private static final char[] TABLE_HEADING = getCharLine((char) 134, "Wähle ein Level ...", (char) 134);
+    private static final char[] TABLE_MID = getCharLine((char) 130, (char) 136, MENU_WIDTH - 2, (char) 132);
+    private static final char[] TABLE_BOTTOM = getCharLine((char) 137, (char) 136, MENU_WIDTH - 2, (char) 138);
+    private static final char[] TABLE_MORE = getCharLine((char) 134, "...", (char) 134);
+            
+    private static char[] getCharLine(char start, char mid, int times, char end)
+    {
+        char[] c = new char[times + 2];
+        Arrays.fill(c, 1, c.length - 1, mid);
+        c[0] = start;
+        c[c.length - 1] = end;
+        return c;
+    }
+    
+    private static char[] getCharLine(char start, String s, char end)
+    {
+        char[] chars = new char[MENU_WIDTH];
+        chars[0] = start;
+        chars[chars.length - 1] = end;
+        int border = Math.min(MENU_WIDTH - 2, s.length());
+        for(int i = 0; i < border; i++)
+        {
+            chars[i + 1] = s.charAt(i);
+        }
+        return chars;
+    }
+    
+    public void tick(long delta, IKeyHandler keys)
+    {
+        if(currentLevel != null)
+        {
+            currentLevel.tick(delta, keys);
+            
+            if(keys.isKeyJustReleased(KeyCode.ESCAPE) > 0)
+            {
+                currentLevel = null;
+            }
+        }
+        else
+        {
+            if(keys.isKeyJustReleased(KeyCode.ENTER) > 0)
+            {
+                currentLevel = levels[levelIndex];
+                return;
+            }
+
+            if(keys.getKeyDownTime(KeyCode.DOWN) > 12)
+            {
+                keys.resetKeyTime(KeyCode.DOWN);
+                levelIndex++;
+            }
+            else if(keys.getKeyDownTime(KeyCode.UP) > 12)
+            {
+                keys.resetKeyTime(KeyCode.UP);
+                levelIndex--;
+            }
+            else if(keys.isKeyJustReleased(KeyCode.DOWN) > 0)
+            {
+                levelIndex++;
+            }
+            else if(keys.isKeyJustReleased(KeyCode.UP) > 0)
+            {
+                levelIndex--;
+            }
+            if(levelIndex < 0)
+            {
+                levelIndex = 0;
+            }
+            else if(levelIndex >= levels.length)
+            {
+                levelIndex = levels.length - 1;
+            }
+
+            renderer.prepareStringDrawing(Color.WHITE);
+
+            double lineHeight = renderer.getLineHeight();
+            double x = renderer.getStringOffsetX(MENU_X);
+            double y = renderer.getStringOffsetY(MENU_Y);
+            renderer.drawChars(TABLE_TOP, x, y);
+            y += lineHeight;
+            renderer.drawChars(TABLE_HEADING, x, y);
+            y += lineHeight;
+            renderer.drawChars(TABLE_MID, x, y);
+            y += lineHeight;
+
+            if(levels.length > MENU_MAX)
+            {
+                int upperHalf = MENU_MAX / 2;
+                int downHalf = levels.length - upperHalf;
+                if(levelIndex < upperHalf)
+                {
+                    paintStringMarking(lineHeight, x, y, levelIndex);
+                    y = paintLevelName(x, y, 0, MENU_MAX - 1);
+                    renderer.drawChars(TABLE_MORE, x, y);
+                    y += lineHeight;
+                }
+                else if(levelIndex >= downHalf)
+                {
+                    paintStringMarking(lineHeight, x, y, levelIndex - downHalf + upperHalf + ((MENU_MAX & 1) != 0 ? 1 : 0));
+                    renderer.drawChars(TABLE_MORE, x, y);
+                    y += lineHeight;
+                    y = paintLevelName(x, y, levels.length - MENU_MAX + 1, MENU_MAX - 1);
+                }
+                else
+                {
+                    paintStringMarking(lineHeight, x, y, upperHalf);
+                    renderer.drawChars(TABLE_MORE, x, y);
+                    y += lineHeight;
+                    y = paintLevelName(x, y, levelIndex - upperHalf + 1, MENU_MAX - 2);
+                    renderer.drawChars(TABLE_MORE, x, y);
+                    y += lineHeight;
+                }
+            }
+            else
+            {
+                paintStringMarking(lineHeight, x, y, levelIndex);
+                y = paintLevelName(x, y, 0, levels.length);
+            }
+
+            renderer.drawChars(TABLE_BOTTOM, x, y);
+
+            renderer.stopStringDrawing();
+        }
+    }
+    
+    private double paintLevelName(double x, double y, int from, int length)
+    {
+        double lineHeight = renderer.getLineHeight();
+        
+        char[] chars = new char[MENU_WIDTH];
+        chars[0] = 134;
+        chars[MENU_WIDTH - 1] = 134;
+        String s;
+        int border;
+        length += from;
+        length = Math.min(length, levels.length);
+        for(int j = from; j < length; j++)
+        {
+            s = levels[j].getName();
+            border = Math.min(MENU_WIDTH - 2, s.length());
+            for(int i = 0; i < border; i++)
+            {
+                chars[i + 1] = s.charAt(i);
+            }
+            Arrays.fill(chars, border + 1, MENU_WIDTH - 1, (char) 0);
+            renderer.drawChars(chars, x, y);
+            y += lineHeight;
+        }
+        return y;
+    }
+    
+    private void paintStringMarking(double lineHeight, double x, double y, int pos)
+    {
+        renderer.fillRec(
+                x + renderer.getStringWidth(1),
+                y + pos * lineHeight - 1, 
+                renderer.getStringWidth(MENU_WIDTH - 2), 
+                lineHeight + 1, 
+                Color.GRAY);
+    }
+}

+ 1 - 0
src/me/hammerle/supersnuvi/input/IKeyHandler.java

@@ -5,6 +5,7 @@ import javafx.scene.input.KeyCode;
 public interface IKeyHandler 
 {
     public int getKeyDownTime(KeyCode key);
+    public void resetKeyTime(KeyCode key);
     public int isKeyJustReleased(KeyCode key);
     public boolean isKeyDown(KeyCode key);
 }

+ 6 - 0
src/me/hammerle/supersnuvi/input/KeyHandler.java

@@ -34,6 +34,12 @@ public class KeyHandler implements IKeyHandler
         return i != null ? i : 0;
     }
     
+    @Override
+    public void resetKeyTime(KeyCode key)
+    {
+        keys.replace(key, 0);
+    }
+    
     @Override
     public int isKeyJustReleased(KeyCode key)
     {

+ 104 - 4
src/me/hammerle/supersnuvi/rendering/GameRenderer.java

@@ -1,12 +1,16 @@
 package me.hammerle.supersnuvi.rendering;
 
+import me.hammerle.supersnuvi.gamelogic.StateRenderer;
 import javafx.animation.AnimationTimer;
 import javafx.scene.Scene;
 import javafx.scene.canvas.Canvas;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 import javafx.scene.input.KeyEvent;
+import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
 import me.hammerle.supersnuvi.input.KeyHandler;
+import me.hammerle.text.SnuviTextPainter;
 
 public class GameRenderer extends AnimationTimer implements IGameRenderer
 {
@@ -30,8 +34,11 @@ public class GameRenderer extends AnimationTimer implements IGameRenderer
     private double offsetY;
     private GraphicsContext context;
     
+    // text rendering
+    private SnuviTextPainter textPainter;
+    
     // world rendering
-    private WorldRenderer world;
+    private StateRenderer state;
     
     public GameRenderer(Scene scene, Canvas canvas)
     {
@@ -48,12 +55,12 @@ public class GameRenderer extends AnimationTimer implements IGameRenderer
         this.offsetX = 0;
         this.offsetY = 0;
         this.context = null;
+        this.textPainter = new SnuviTextPainter(canvas);
         
         // events
         registerEvents();
         
-        this.world = new WorldRenderer(this);
-        world.loadWorld("test");
+        this.state = new StateRenderer(this);
     }
     
     private void registerEvents()
@@ -93,7 +100,7 @@ public class GameRenderer extends AnimationTimer implements IGameRenderer
         keys.tick(delta);
         
         prepareRendering();
-        world.tick(delta, keys);
+        state.tick(delta, keys);
     }
     
     private void prepareRendering()
@@ -101,9 +108,81 @@ public class GameRenderer extends AnimationTimer implements IGameRenderer
         offsetX = -cameraX;
         offsetY = canvas.getHeight() + cameraY;
         context = canvas.getGraphicsContext2D();
+        context.setFill(Color.BLACK);
         context.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
     }
     
+    @Override
+    public void prepareStringDrawing(Color c)
+    {
+        textPainter.prepareStringDrawing(c, 
+                Math.min
+                (
+                    canvas.getHeight() / (textPainter.getBaseHeight() * LINES),
+                    canvas.getWidth() / (textPainter.getBaseWidth() * CHARS_PER_LINE))
+                );
+    }
+    
+    @Override
+    public void stopStringDrawing()
+    {
+        textPainter.stopStringDrawing();
+    }
+    
+    @Override
+    public double getStringOffsetX(int x)
+    {
+        double width = canvas.getWidth();
+        width -= textPainter.getWidth(CHARS_PER_LINE);
+        width /= 2;
+        return width + textPainter.getWidth(x);
+    }
+    
+    @Override
+    public double getStringOffsetY(int y)
+    {
+        double height = canvas.getHeight();
+        height -= textPainter.getHeight() * LINES;
+        height /= 2;
+        return height + textPainter.getHeight() * y;
+    }
+
+    @Override
+    public double getLineHeight()
+    {
+        return textPainter.getHeight();
+    }
+    
+    @Override
+    public double getStringWidth(int length)
+    {
+        return textPainter.getWidth(length);
+    }
+    
+    @Override
+    public double getStringWidth(String s)
+    {
+        return textPainter.getWidth(s);
+    }
+    
+    @Override
+    public double getCharsWidth(char[] chars)
+    {
+        return textPainter.getWidth(chars);
+    }
+    
+    @Override
+    public void drawString(String s, double x, double y)
+    {
+        textPainter.paintString(s, x, y);
+    }
+    
+    @Override
+    public void drawChars(char[] chars, double x, double y)
+    { 
+        textPainter.paintString(chars, x, y);
+    }
+    
     @Override
     public void drawImage(Image image, double x, double y)
     {
@@ -116,6 +195,27 @@ public class GameRenderer extends AnimationTimer implements IGameRenderer
         context.drawImage(image, offsetX + x * TILE_SIZE, offsetY - (y + 1) * TILE_SIZE);
     }
     
+    @Override
+    public void setStrokeColor(Color c)
+    {
+        context.setStroke(c);
+    }
+    
+    @Override
+    public void setFillColor(Color c)
+    {
+        context.setFill(c);
+    }
+    
+    @Override
+    public void fillRec(double x, double y, double width, double height, Color c)
+    {
+        Paint paint = context.getFill();
+        context.setFill(c);
+        context.fillRect(x, y, width, height);
+        context.setFill(paint);
+    }
+    
     @Override
     public int getFirstVisibleBlockX()
     {

+ 1 - 1
src/me/hammerle/supersnuvi/rendering/GameWindow.java

@@ -29,7 +29,7 @@ public class GameWindow extends Application
 
         stage.setScene(scene);
         
-        Canvas canvas = new Canvas(640, 400);     
+        Canvas canvas = new Canvas(800, 600);     
         root.getChildren().add(canvas);
               
         GameRenderer timer = new GameRenderer(scene, canvas);

+ 94 - 0
src/me/hammerle/supersnuvi/rendering/IGameRenderer.java

@@ -1,9 +1,81 @@
 package me.hammerle.supersnuvi.rendering;
 
 import javafx.scene.image.Image;
+import javafx.scene.paint.Color;
 
 public interface IGameRenderer 
 {
+    public static final int LINES = 25;
+    public static final int CHARS_PER_LINE = 50;
+    
+    /** This should be called before any String drawing
+     *
+     * @param c the color of the text
+     */
+    public void prepareStringDrawing(Color c);
+    
+    /** This should be called after the last String in a frame was drawn
+     *
+     */
+    public void stopStringDrawing();
+    
+    /** Returns the x offset of a char at x
+     *
+     * @param x the x position
+     * @return the offset
+     */
+    public double getStringOffsetX(int x);
+    
+    /** Returns the y offset of a char at y
+     *
+     * @param y the position
+     * @return the offset
+     */
+    public double getStringOffsetY(int y);
+    
+    /** Returns the height of a text line
+     *
+     * @return the hight of a text line
+     */
+    public double getLineHeight();
+    
+    /** Returns the width of a String
+     *
+     * @param length the length of the String
+     * @return the width
+     */
+    public double getStringWidth(int length);
+    
+    /** Returns the width of a String
+     *
+     * @param s a String
+     * @return the width
+     */
+    public double getStringWidth(String s);
+    
+    /** Returns the width of a char array
+     *
+     * @param chars a char array
+     * @return the width
+     */
+    public double getCharsWidth(char[] chars);
+    
+    /** Draws a String at the desired position
+     *
+     * @param s a String
+     * @param x the x coord of the position
+     * @param y the y coord of the position
+     */
+    public void drawString(String s, double x, double y);
+    
+    /** Draws a char array at the desired position
+     *
+     * @param chars a char array
+     * @param x the x coord of the position
+     * @param y the y coord of the position
+     */
+    public void drawChars(char[] chars, double x, double y);
+    
     /** Draws an image at the desired position
      *
      * @param image the image
@@ -20,6 +92,28 @@ public interface IGameRenderer
      */
     public void drawBlockImage(Image image, int x, int y);
     
+    /** Sets the stroke color
+     *
+     * @param c the color
+     */
+    public void setStrokeColor(Color c);
+    
+    /** Sets the fill color
+     *
+     * @param c the color
+     */
+    public void setFillColor(Color c);
+    
+    /** Fills a rectangle at the desired position
+     *
+     * @param x the x coord of the position
+     * @param y the y coord of the position
+     * @param width the width
+     * @param height the height
+     * @param c the fill color
+     */
+    public void fillRec(double x, double y, double width, double height, Color c);
+    
     /** Gets the x coord of the first visible block
      *
      * @return the x coord

+ 0 - 263
src/me/hammerle/supersnuvi/rendering/WorldRenderer.java

@@ -1,263 +0,0 @@
-package me.hammerle.supersnuvi.rendering;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-import javafx.scene.image.Image;
-import javafx.scene.image.WritableImage;
-import javafx.scene.paint.Color;
-import me.hammerle.supersnuvi.entity.Entity;
-import me.hammerle.supersnuvi.entity.Hero;
-import me.hammerle.supersnuvi.input.IKeyHandler;
-import me.hammerle.supersnuvi.tiles.Ice;
-import me.hammerle.supersnuvi.tiles.TrampolinTile;
-import me.hammerle.supersnuvi.tiles.Location;
-import me.hammerle.supersnuvi.tiles.Tile;
-import me.hammerle.supersnuvi.util.CollisionBox;
-import me.hammerle.supersnuvi.util.Utils;
-
-public class WorldRenderer
-{
-    // constants
-    private static final Image FALLBACK_IMAGE = new WritableImage(1, 1);
-    
-    // rendering
-    private IGameRenderer renderer;
-    
-    // world tiles
-    private boolean worldLoaded;
-    private int width;
-    private int height;
-    private int[][] background;
-    private int[][] background2;
-    private int[][] foreground;
-    
-    private HashMap<Integer, Entity> entities;
-    
-    private HashMap<Integer, Tile> registeredTiles;
-    
-    public WorldRenderer(IGameRenderer renderer)
-    {
-        this.renderer = renderer;
-        
-        this.worldLoaded = false;
-        this.width = 0;
-        this.height = 0;
-        this.background = null;
-        this.background2 = null;
-        this.foreground = null;
-        
-        this.registeredTiles = new HashMap<>();
-        this.entities = new HashMap<>();
-        
-        Entity ent = new Entity(this, 80, 340, 32, 64);
-        Hero hero = new Hero(this, 32, 100, 32, 48);
-        
-        entities.put(1, ent);
-        entities.put(2, hero);
-        
-        registerTiles();
-    }    
-
-    private void registerTile(int id, int r, int g, int b, int opacity)
-    {
-        registeredTiles.put(id, new Tile(new Color(r / 255d, g / 255d, b / 255d, opacity / 255d)));
-    }
-    
-    private void registerTiles()
-    {
-        registeredTiles.put(1, new Tile("air"));
-        registeredTiles.put(2, new Tile("dirt").setDefaultCollisionBox());
-        registeredTiles.put(3, new Tile("grass").setDefaultCollisionBox());
-        
-        registeredTiles.put(4, new TrampolinTile().setDefaultCollisionBox());
-        registeredTiles.put(5, new Ice().setDefaultCollisionBox());
-        registerTile(6, 255, 255, 0, 255);
-        registerTile(7, 255, 255, 255, 255);
-    }
-    
-    private Image getTile(int id)
-    {
-        Tile tile = registeredTiles.get(id);
-        if(tile == null)
-        {
-            return FALLBACK_IMAGE;
-        }
-        return tile.getImage();
-    }
-
-    public void tick(long delta, IKeyHandler keys)
-    {
-        if(worldLoaded)
-        {
-            // doing entity logic first
-            entities.values().forEach(entity -> 
-            {
-                entity.controlTick(keys);
-                entity.tick(delta);
-            });
-
-            int startX = renderer.getFirstVisibleBlockX();
-            int startY = renderer.getFirstVisibleBlockY();
-            int endX = Math.min(renderer.getLastVisibleBlockX() + 1, width);
-            int endY = Math.min(renderer.getLastVisibleBlockY() + 1, height);
-            
-            int id;
-            for(int x = startX; x < endX; x++)
-            {
-                for(int y = startY; y < endY; y++)
-                {
-                    id = background[x][y];
-                    if(id != -1)
-                    {
-                        renderer.drawBlockImage(getTile(id), x, y);
-                    }
-                    id = background2[x][y];
-                    if(id != -1)
-                    {
-                        renderer.drawBlockImage(getTile(id), x, y);
-                    }
-                }
-            }
-            
-            // render entities here
-            entities.values().forEach(en -> renderer.drawImage(en.getImage(), en.getRenderX(), en.getRenderY()));
-            // end entity rendering
-            
-            for(int x = startX; x < endX; x++)
-            {
-                for(int y = startY; y < endY; y++)
-                {
-                    id = foreground[x][y];
-                    if(id != -1)
-                    {
-                        renderer.drawBlockImage(getTile(id), x, y);
-                    }
-                }
-            }
-        }
-    }
-    
-    public Tile getInteractionTile(int x, int y)
-    {
-        if(x < 0 || y < 0 || x >= width || y >= height)
-        {
-            return Tile.FALLBACK_TILE;
-        }
-        return registeredTiles.get(background2[x][y]);
-    }
-    
-    private void throwSameLayerSizeException()
-    {
-        throw new IllegalArgumentException("world layers must be of same size");
-    }
-    
-    private void validateArraySize(int[][] layer, int h)
-    {
-        for(int[] he : layer)
-        {
-            if(he.length != h)
-            {
-                throwSameLayerSizeException();
-            }
-        }
-    }
-    
-    public void loadWorld(String path)
-    {
-        int[][][] layers = Utils.loadMap(path);
-        int[][] back = layers[0];
-        int[][] back2 = layers[1];
-        int[][] fore = layers[2];
-        if(back.length > 0)
-        {
-            width = back.length;
-            if(back2.length != width || fore.length != width)
-            {
-                throwSameLayerSizeException();
-            }
-            height = back2[0].length;
-            validateArraySize(back, height);
-            validateArraySize(back2, height);
-            validateArraySize(fore, height);
-            
-            this.background = back;
-            this.background2 = back2;
-            this.foreground = fore;
-        }
-        else
-        {
-            this.background = new int[0][0];
-            this.background2 = new int[0][0];
-            this.foreground = new int[0][0];
-        }
-        worldLoaded = true;
-    }
-       
-    // -------------------------------------------------------------------------
-    // collision box
-    // -------------------------------------------------------------------------
-    
-    public CollisionBox getTileCollisionBox(int x, int y)
-    {
-        if(x < 0 || y < 0 || x >= width || y >= height)
-        {
-            return CollisionBox.NULL_BOX;
-        }
-        Tile tile = registeredTiles.get(background2[x][y]);
-        return tile.getCollisionBox().reset().offset(renderer.toCoord(x), renderer.toCoord(y));
-    }
-    
-    public LinkedList<Location> getTilesCollidingWith(CollisionBox cb)
-    {
-        LinkedList<Location> boxes = new LinkedList<>();
-        int startX = renderer.toBlock(cb.getMinX());
-        int endX = renderer.toBlock(cb.getMaxX());
-        int startY = renderer.toBlock(cb.getMinY());
-        int endY = renderer.toBlock(cb.getMaxY());
-        
-        for(int x = startX; x <= endX; x++)
-        {
-            for(int y = startY; y <= endY; y++)
-            {
-                if(getTileCollisionBox(x, y).intersects(cb))
-                {
-                    boxes.add(new Location(getInteractionTile(x, y), x, y));
-                }
-            }
-        }
-        return boxes;
-    }
-    
-    public List<Entity> getEntitiesCollidingWith(Entity not, CollisionBox cb)
-    {
-        return entities.values().stream().filter(ent -> ent != not && ent.getBox().intersects(cb)).collect(Collectors.toList());
-    }
-    
-    public LinkedList<CollisionBox> getCollisionBoxesAt(Entity not, CollisionBox cb)
-    {
-        LinkedList<CollisionBox> boxes = new LinkedList<>(entities.values().stream()
-                        .filter(ent -> ent != not && ent.getBox().intersects(cb))
-                        .map(ent -> ent.getBox())
-                        .collect(Collectors.toList()));
-        int startX = renderer.toBlock(cb.getMinX());
-        int endX = renderer.toBlock(cb.getMaxX());
-        int startY = renderer.toBlock(cb.getMinY());
-        int endY = renderer.toBlock(cb.getMaxY());
-        
-        CollisionBox box;
-        for(int x = startX; x <= endX; x++)
-        {
-            for(int y = startY; y <= endY; y++)
-            {
-                box = getTileCollisionBox(x, y);
-                if(box.intersects(cb))
-                {
-                    boxes.add(box.copy());
-                }
-            }
-        }
-        return boxes;
-    }
-}

+ 0 - 72
src/me/hammerle/supersnuvi/util/Utils.java

@@ -31,78 +31,6 @@ public class Utils
         return (y3 - y1) * k + x1;
     }
     
-    public static int[][][] loadMap(String path)
-    {
-        try
-        {
-            File map = new File(path + ".map");  
-            if(!map.exists())
-            {
-                return new int[3][0][0];
-            }
-            List<String> strings;
-            try
-            {
-                strings = Files.readAllLines(map.toPath());
-            } 
-            catch(IOException ex) 
-            {
-                return new int[3][0][0];
-            }
-            if(strings.isEmpty())
-            {
-                return new int[3][0][0];
-            }
-
-            LinkedList<LinkedList<List<Integer>>> list = new LinkedList<>();
-            LinkedList<List<Integer>> active = new LinkedList<>();
-            list.add(active);
-            for(String s : strings)
-            {
-                if(s.equals("#"))
-                {
-                    active = new LinkedList<>();
-                    list.add(active);
-                    continue;
-                }
-                active.add(Arrays.stream(s.split(",")).map(st -> Integer.parseInt(st.trim())).collect(Collectors.toList()));
-            }
-
-            if(list.size() != 3)
-            {
-                return new int[3][0][0];
-            }
-
-            int height = list.getFirst().size();
-            int[][][] layers = new int[3][list.getFirst().getFirst().size()][height];
-            int x = 0;
-            int y;
-            int z = 0;
-            for(LinkedList<List<Integer>> layerXY : list)
-            {
-                y = height - 1;
-                for(List<Integer> layerY : layerXY)
-                {
-                    for(Integer i : layerY)
-                    {
-                        //System.out.println(x + " " + z + " " + y);
-                        layers[x][z][y] = i;
-                        z++;
-                    }
-                    z = 0;
-                    y--;
-                }
-                x++;
-            }
-            return layers;
-        }
-        catch(Exception ex)
-        {
-            ex.printStackTrace();
-            return new int[3][0][0];
-        } 
-    }
-    
     public static Image getColoredImage(Color c, int width, int height)
     {
         WritableImage image = new WritableImage(width, height);