Ver Fonte

run length encoding of levels, entity spawning, londoner textures moved to texture atlas, londoner ai and rendering, small collision tweaks, trampolin tweaks

Kajetan Johannes Hammerle há 6 anos atrás
pai
commit
6f1cce6686
59 ficheiros alterados com 266 adições e 428 exclusões
  1. BIN
      levels/00-Tech_Demo.map
  2. BIN
      levels/01-Parabola.map
  3. BIN
      levels/02-Out_of_Reach.map
  4. BIN
      levels/03-Higher_Ground.map
  5. BIN
      levels/04-Like_Ice.map
  6. BIN
      levels_uncompressed/00-Tech_Demo.map
  7. BIN
      levels_uncompressed/01-Parabola.map
  8. BIN
      levels_uncompressed/02-Out_of_Reach.map
  9. BIN
      levels_uncompressed/03-Higher_Ground.map
  10. BIN
      levels_uncompressed/04-Like_Ice.map
  11. BIN
      resources/londoner.png
  12. BIN
      resources/londoner.xcf
  13. BIN
      resources/londoner/KnC1_a_f1.png
  14. BIN
      resources/londoner/KnC1_a_f2.png
  15. BIN
      resources/londoner/KnC1_a_f3.png
  16. BIN
      resources/londoner/KnC1_a_f4.png
  17. BIN
      resources/londoner/KnC1_a_f5.png
  18. BIN
      resources/londoner/KnC1_d_f1.png
  19. BIN
      resources/londoner/KnC1_d_f2.png
  20. BIN
      resources/londoner/KnC1_d_f3.png
  21. BIN
      resources/londoner/KnC1_d_f4.png
  22. BIN
      resources/londoner/KnC1_d_f5.png
  23. BIN
      resources/londoner/KnC1_d_f6.png
  24. BIN
      resources/londoner/KnC1_d_f7.png
  25. BIN
      resources/londoner/KnC1_dodge.png
  26. BIN
      resources/londoner/KnC1_idle.png
  27. BIN
      resources/londoner/KnC1_s_f1.png
  28. BIN
      resources/londoner/KnC1_s_f2.png
  29. BIN
      resources/londoner/KnC1_s_f3.png
  30. BIN
      resources/londoner/KnC1_w_f1.png
  31. BIN
      resources/londoner/KnC1_w_f2.png
  32. BIN
      resources/londoner/KnC1_w_f3.png
  33. BIN
      resources/londoner/KnC1_w_f4.png
  34. BIN
      resources/londoner/KnC1_w_f5.png
  35. BIN
      resources/londoner/KnC1_w_f6.png
  36. BIN
      resources/londoner/londoner1_d_f1.png
  37. BIN
      resources/londoner/londoner1_d_f2.png
  38. BIN
      resources/londoner/londoner1_d_f3.png
  39. BIN
      resources/londoner/londoner1_d_f4.png
  40. BIN
      resources/londoner/londoner1_d_f5.png
  41. BIN
      resources/londoner/londoner1_d_f6.png
  42. BIN
      resources/londoner/londoner1_d_f7.png
  43. BIN
      resources/londoner/londoner1_idle.png
  44. BIN
      resources/londoner/londoner1_w_f1.png
  45. BIN
      resources/londoner/londoner1_w_f2.png
  46. BIN
      resources/londoner/londoner1_w_f3.png
  47. BIN
      resources/londoner/londoner1_w_f4.png
  48. BIN
      resources/londoner/londoner1_w_f5.png
  49. BIN
      resources/londoner/londoner1_w_f6.png
  50. 12 7
      src/me/hammerle/supersnuvi/entity/Entity.java
  51. 8 13
      src/me/hammerle/supersnuvi/entity/EntityBuilder.java
  52. 1 1
      src/me/hammerle/supersnuvi/entity/components/DefaultMovement.java
  53. 5 5
      src/me/hammerle/supersnuvi/entity/components/ai/HumanController.java
  54. 147 130
      src/me/hammerle/supersnuvi/entity/components/ai/LondonerController.java
  55. 0 238
      src/me/hammerle/supersnuvi/entity/components/animator/LondonerAnimator.java
  56. 22 23
      src/me/hammerle/supersnuvi/gamelogic/Level.java
  57. 64 10
      src/me/hammerle/supersnuvi/gamelogic/LevelData.java
  58. 6 0
      src/me/hammerle/supersnuvi/tiles/NullTile.java
  59. 1 1
      src/me/hammerle/supersnuvi/tiles/TrampolinTile.java

BIN
levels/00-Tech_Demo.map


BIN
levels/01-Parabola.map


BIN
levels/02-Out_of_Reach.map


BIN
levels/03-Higher_Ground.map


BIN
levels/04-Like_Ice.map


BIN
levels_uncompressed/00-Tech_Demo.map


BIN
levels_uncompressed/01-Parabola.map


BIN
levels_uncompressed/02-Out_of_Reach.map


BIN
levels_uncompressed/03-Higher_Ground.map


BIN
levels_uncompressed/04-Like_Ice.map


BIN
resources/londoner.png


BIN
resources/londoner.xcf


BIN
resources/londoner/KnC1_a_f1.png


BIN
resources/londoner/KnC1_a_f2.png


BIN
resources/londoner/KnC1_a_f3.png


BIN
resources/londoner/KnC1_a_f4.png


BIN
resources/londoner/KnC1_a_f5.png


BIN
resources/londoner/KnC1_d_f1.png


BIN
resources/londoner/KnC1_d_f2.png


BIN
resources/londoner/KnC1_d_f3.png


BIN
resources/londoner/KnC1_d_f4.png


BIN
resources/londoner/KnC1_d_f5.png


BIN
resources/londoner/KnC1_d_f6.png


BIN
resources/londoner/KnC1_d_f7.png


BIN
resources/londoner/KnC1_dodge.png


BIN
resources/londoner/KnC1_idle.png


BIN
resources/londoner/KnC1_s_f1.png


BIN
resources/londoner/KnC1_s_f2.png


BIN
resources/londoner/KnC1_s_f3.png


BIN
resources/londoner/KnC1_w_f1.png


BIN
resources/londoner/KnC1_w_f2.png


BIN
resources/londoner/KnC1_w_f3.png


BIN
resources/londoner/KnC1_w_f4.png


BIN
resources/londoner/KnC1_w_f5.png


BIN
resources/londoner/KnC1_w_f6.png


BIN
resources/londoner/londoner1_d_f1.png


BIN
resources/londoner/londoner1_d_f2.png


BIN
resources/londoner/londoner1_d_f3.png


BIN
resources/londoner/londoner1_d_f4.png


BIN
resources/londoner/londoner1_d_f5.png


BIN
resources/londoner/londoner1_d_f6.png


BIN
resources/londoner/londoner1_d_f7.png


BIN
resources/londoner/londoner1_idle.png


BIN
resources/londoner/londoner1_w_f1.png


BIN
resources/londoner/londoner1_w_f2.png


BIN
resources/londoner/londoner1_w_f3.png


BIN
resources/londoner/londoner1_w_f4.png


BIN
resources/londoner/londoner1_w_f5.png


BIN
resources/londoner/londoner1_w_f6.png


+ 12 - 7
src/me/hammerle/supersnuvi/entity/Entity.java

@@ -50,7 +50,7 @@ public final class Entity
     protected ItemCollector itemCollector;
     
     // face
-    private Face face;
+    private Face face = Face.RIGHT;
     
     protected Entity(Level level, float x, float y, CollisionObject box)
     {
@@ -159,9 +159,19 @@ public final class Entity
     
     public Face getFace()
     {
+        if(motionX == 0.0f)
+        {
+            return face;
+        }
+        face = motionX < 0.0f ? Face.LEFT : Face.RIGHT;
         return face;
     }
     
+    public void updateFace()
+    {
+        
+    }
+    
     public float getMotionX()
     {
         return motionX;
@@ -207,11 +217,6 @@ public final class Entity
         preMotionX = motionX;
         preMotionY = motionY;
         
-        if(preMotionX != 0.0f)
-        {
-            face = preMotionX > 0.0f ? Face.RIGHT : Face.LEFT;
-        }
-        
         if(move.hasGravity())
         {
             preMotionY += GRAVITY * move.getGravityFactor();
@@ -352,7 +357,7 @@ public final class Entity
             {
                 cb.reset();
                 cb.expand(f.getCollisionOffsetX(), f.getCollisionOffsetY());
-                level.getEntitiesCollidingWith(this, box).forEach(ent -> ent.controller.onCollideWithEntity(ent, f));
+                level.getEntitiesCollidingWith(this, cb).forEach(ent -> this.controller.onCollideWithEntity(ent, f));
                 level.getCollisionBoxesAt(cb).forEach(loc -> 
                 {
                     controller.onCollideWithTile(loc, f);

+ 8 - 13
src/me/hammerle/supersnuvi/entity/EntityBuilder.java

@@ -18,7 +18,7 @@ public final class EntityBuilder
 {
     public static Entity buildHero(Level level, float x, float y)
     {
-        Entity hero = new Entity(level, x, y, new CollisionBox(0.0f, 5.0f, 29.0f, 64.0f));
+        Entity hero = new Entity(level, x, y, new CollisionBox(0.0f, 5.0f, 27.0f, 64.0f));
         hero.controller = new HumanController(hero);
         hero.health = new DefaultHealth(hero, (ent) -> ent.getLevel().scheduleReset(), 100.0f, null, null, null);
         hero.energy = new DefaultEnergy(hero, 100.0f);
@@ -29,22 +29,17 @@ public final class EntityBuilder
     
     public static Entity buildLondoner(Level level, float x, float y, boolean evil)
     {
-        float w = Tile.SIZE;
-        float h = Tile.SIZE * 2;
-
-        Entity hero = new Entity(level, x, y, new CollisionBox(0.0f, 0.0f, w * 0.4375f, h * 0.703125f));
-        //hero.controller = new FollowHeroController(hero, 2);
-        hero.controller = new LondonerController(hero, evil);
-        hero.health = new DefaultHealth(hero, IDeath.NULL, 100.0f, null, null, null);
-        hero.energy = new DefaultEnergy(hero, 100.0f);
-        hero.move = new DefaultMovement(hero, 3f, 3f, 24.0f);
-        //hero.itemCollector = new HeroItemCollector(hero);
-        return hero;
+        Entity londoner = new Entity(level, x, y, new CollisionBox(7.0f, 19.0f, 21.0f, 64.0f));
+        londoner.controller = new LondonerController(londoner, evil);
+        londoner.health = new DefaultHealth(londoner, IDeath.NULL, 100.0f, null, null, null);
+        londoner.energy = new DefaultEnergy(londoner, 100.0f);
+        londoner.move = new DefaultMovement(londoner, 3.0f, 0.0f, 50.0f);
+        return londoner;
     }
     
     public static Entity buildCrumblingStone(Level level, float x, float y)
     {
-        Entity stone = new Entity(level, x, y, new CollisionBox(0.0f, 0.0f, Tile.SIZE, Tile.SIZE * 10f));
+        Entity stone = new Entity(level, x, y, new CollisionBox(0.0f, 0.0f, Tile.SIZE, Tile.SIZE));
         stone.controller = new StoneController(stone);
         stone.move = new StoneMovement(stone);
         stone.health = new NoHealth(stone);

+ 1 - 1
src/me/hammerle/supersnuvi/entity/components/DefaultMovement.java

@@ -46,7 +46,7 @@ public class DefaultMovement extends Movement
     {
         if(ent.isOnGround())
         {
-            ent.setMotionY(-getJumpPower());
+            ent.setMotionY(ent.getMotionY() - getJumpPower());
             return true;
         }
         return false;

+ 5 - 5
src/me/hammerle/supersnuvi/entity/components/ai/HumanController.java

@@ -73,7 +73,7 @@ public class HumanController extends Controller
     {
         if(ent.getHealth().isDead())
         {
-            ox = ent.getFace() == Face.RIGHT ? 0.0f: -32.0f;
+            ox = ent.getFace() == Face.RIGHT ? 0.0f: -37.0f;
             oy = 0.0f;
             h = 64.0f;
             w = 64.0f;
@@ -117,7 +117,7 @@ public class HumanController extends Controller
             }
         }
         
-        ox = 0.0f;
+        ox = ent.getFace() == Face.RIGHT ? 0.0f: -5.0f;
         oy = 0.0f;
         h = 64.0f;
         w = 32.0f;
@@ -126,15 +126,15 @@ public class HumanController extends Controller
         {
             if(ent.getMotionX() == 0.0f)
             {
-                nextIdleFrame();
                 tx = (idleFrame * 32.0f) / SIZE;
                 ty = 128.0f / SIZE;
+                nextIdleFrame();
             }
             else
-            {
-                nextWalkFrame();
+            {               
                 tx = (96.0f + walkFrame * 32.0f) / SIZE;
                 ty = 0.0f;
+                nextWalkFrame();
             }
         }
         else

+ 147 - 130
src/me/hammerle/supersnuvi/entity/components/ai/LondonerController.java

@@ -1,208 +1,225 @@
 package me.hammerle.supersnuvi.entity.components.ai;
 
+import me.hammerle.snuviengine.api.Shader;
+import me.hammerle.snuviengine.api.Texture;
 import me.hammerle.supersnuvi.entity.Entity;
 import me.hammerle.supersnuvi.tiles.Location;
-import me.hammerle.supersnuvi.tiles.Tile;
 import me.hammerle.supersnuvi.util.Face;
-import me.hammerle.supersnuvi.util.SoundUtils;
+import me.hammerle.supersnuvi.util.Utils;
 
 public class LondonerController extends Controller
 {
-    private boolean combatMode = false;
-    private int combatTimer = 0;
-    private int attackTimer = -1;
-    private int attackCooldown = -1;
-    private int dashTimer = -1;
-    
-    private final float motion = 1.5f;
+    private final static Texture LONDONER = new Texture("resources/londoner.png");
     
     private final boolean evil;
     
-    private boolean jump = false;  
+    private float ox = 0.0f;
+    private float tx = 0.0f;
+    private float ty = 0.0f;
+    
+    private int walkFrame = 0;
+    private int transformFrame = -1;
+    private int deathCounter = 0;
+    private int deathFrame = 0;
     
+    private Face direction = Face.LEFT;
+
     public LondonerController(Entity ent, boolean evil) 
     {
         super(ent);
         this.evil = evil;
     }
-    /*
-    @Override
-    public boolean isInCombatMode() 
-    {
-        return combatMode || combatTimer < 0;
-    }
-
-    @Override
-    public boolean isEvil() 
-    {
-        return isInCombatMode();
-    }
-
-    @Override
-    public int getCombatTimer() 
-    {
-        return combatTimer;
-    }
-
-    @Override
-    public boolean isAttacking() 
+    
+    private boolean hasRedEyes()
     {
-        return attackTimer >= 0;
+        return transformFrame >= 3;
     }
-
+    
     @Override
-    public boolean isDashing() 
+    public boolean isAnimated()
     {
-        return dashTimer != -1;
+        return deathFrame < 7;
     }
-
+    
     @Override
     public void tick() 
     {
-        if(ent.getHealth().isDead())
+        if(evil)
         {
-            return;
-        }
-        
-        if(!combatMode)
-        {
-            if(evil)
+            if(transformFrame != -1)
             {
-                Entity hero = ent.getLevel().getHero();
-                if(hero.squaredDistance(ent) <= 65536)
+                if(transformFrame < 3)
                 {
-                    ent.setMotionX(0.0f);
-                    combatMode = true;
-                    combatTimer = ent.getAnimator().getCombatStartTicks() - 1;
+                    ox = ent.getFace() == Face.RIGHT ? 0.0f: -36.0f;
+                    tx = transformFrame * 0.125f + 0.125f;
+                    ty = 0.375f;
+                    transformFrame++;
                     return;
                 }
             }
-            applyMotion();
-            return;
-        }
-            
-        if(combatTimer > 0)
-        {
-            combatTimer--;
-            return;
+            else if(ent.getLevel().getHero().getSquaredDistance(ent) <= 16384) // 4 Tiles
+            {
+                transformFrame = 0;
+            }
         }
         
-        if(attackCooldown > 0)
+        if(ent.getHealth().isDead())
         {
-            attackCooldown--;
+            ox = ent.getFace() == Face.RIGHT ? -32.0f: -4.0f;
+            
+            tx = deathFrame * 0.125f;
+            ty = hasRedEyes() ? 0.125f : 0.25f;
+            
+            walkFrame = 0;
+            deathCounter++;
+            if(deathCounter >= 3)
+            {
+                deathCounter = 0;
+                deathFrame++;
+            }
+            return;
         }
         
-        if(attackTimer != -1)
+        if(hasRedEyes())
         {
-            attackTimer++;
-            if(attackTimer >= ent.getAnimator().getAttackTicks())
+            float hx = ent.getLevel().getHero().getCenterX();
+            if(hx < ent.getCenterX())
             {
-                attackTimer = -1;
-                float sign = ent.getAnimator().drawImageFlipped() ? -1 : 1;
-                float extend = sign * Tile.SIZE;
-                boolean once = true;
-                for(Entity e : ent.getLevel().getEntitiesCollidingWith(ent, ent.getBox().expand(extend, 0)))
-                {
-                    if(e.getController().isAttacking() && once)
-                    {
-                        once = false;
-                        ent.setMotionX(-sign * 7);
-                        e.setMotionX(sign * 7);
-                    }
-                    else if(!e.getController().isBlocking())
-                    {
-                        e.getHealth().addHealth(-14.2857);
-                    }
-                }
+                ent.setMotionX(-ent.getMovement().getVelocityX());
+            }
+            else
+            {
+                ent.setMotionX(ent.getMovement().getVelocityX());
             }
-            return;
         }
         else
         {
-            Entity hero = ent.getLevel().getHero();
-            float distance = hero.signedDistanceX(ent);
-            if(Math.abs(distance) < (Tile.SIZE >> 1))
+            if(direction == Face.LEFT)
             {
-                if(attackCooldown > 0)
-                {
-                    return;
-                }
-                attackTimer = 0;
-                attackCooldown = ent.getAnimator().getAttackTicks() * 4;
-                ent.getAnimator().setFlipped(distance < 0);
-                return;
+                ent.setMotionX(-ent.getMovement().getVelocityX());
+            }
+            else
+            {
+                ent.setMotionX(ent.getMovement().getVelocityX());
             }
         }
         
-        if(dashTimer != -1)
+        ox = ent.getFace() == Face.RIGHT ? 0.0f: -36.0f;
+        
+        if(ent.isOnGround())
         {
-            dashTimer++;
-            if(dashTimer > 15)
+            if(ent.getMotionX() == 0.0f)
             {
-                dashTimer = -1;
-                ent.setMotionX(0.0f);
+                tx = 0.875f;
+                ty = hasRedEyes() ? 0.25f : 0.375f;
             }
             else
             {
-                ent.setMotionX(ent.getAnimator().drawImageFlipped() ? -15 : 15);
+                deathFrame = 0;
+                walkFrame = (walkFrame + 1) % 6;
+                tx = walkFrame * 0.125f;
+                ty = hasRedEyes() ? 0.5f : 0.625f;
             }
-            return;
-        }
-         
-        applyMotion();
-    }
-    
-    private void applyMotion()
-    {
-        if(motion > Math.abs(ent.getMotionX()))
-        {
-            ent.setMotionX(ent.getAnimator().drawImageFlipped() ? -motion : motion);
         }
-        if(jump)
+        else
         {
-            SoundUtils.playSound(SoundUtils.Sound.LONDONER_JUMP);
-            ent.getMovement().jump();
-            jump = false;
+            deathFrame = 0;
+            walkFrame = 0;
+            tx = 0.125f;
+            ty = hasRedEyes() ? 0.5f : 0.625f;
         }
     }
 
     @Override
-    public void onCollideWithEntity(Entity ent, Face face) 
+    public void renderTick(float lag)
     {
-        if(ent.getMovement().useCollisionBox())
+        if(ent.getHealth().wasHurt())
         {
-            switchDirection(face);
+            Shader.setColorEnabled(true);
+            Shader.setMixColorEnabled(true);
+            Shader.setMixColor(1.0f, 0.0f, 0.0f, 1.0f);
         }
-    }
-
-    @Override
-    public void onCollideWithTile(Location loc, Face face) 
-    {
-        if(loc.getTile().shouldAiUseCollisionBox(loc.getX(), loc.getY()))
+        if(ent.getHealth().wasHealed())
+        {
+            Shader.setColorEnabled(true);
+            Shader.setMixColorEnabled(true);
+            Shader.setMixColor(0.0f, 1.0f, 0.0f, 1.0f);
+        }
+        
+        LONDONER.bind();
+        float x = Utils.interpolate(ent.getLastX(), ent.getX(), lag);
+        float y = Utils.interpolate(ent.getLastY(), ent.getY(), lag);
+        
+        float m1;
+        float m2;
+        if(ent.getFace() == Face.LEFT)
+        {
+            m1 = 64.0f;
+            m2 = 0.0f;
+        }
+        else
         {
-            switchDirection(face);
+            m1 = 0.0f;
+            m2 = 64.0f;
+        }
+        Shader.getTextureRenderer().drawRectangle(
+                x + ox + m1, y,
+                x + ox + m2, y + 64.0f, 
+                tx, ty, 
+                tx + 0.125f, ty + 0.125f);
+        
+        if(ent.getHealth().wasHurt() || ent.getHealth().wasHealed())
+        {
+            Shader.setColorEnabled(false);
+            Shader.setMixColorEnabled(false);
         }
     }
     
-    private void switchDirection(Face face)
+    @Override
+    public void onCollideWithTile(Location loc, Face face)
     {
-        if(isEvil())
+        if(hasRedEyes())
         {
-            if(face == Face.LEFT || face == Face.RIGHT)
+            if(face.getOpposite() == ent.getFace() && ent.getMotionX() == 0.0f)
             {
-                jump = true;
+                ent.getMovement().jump();
             }
         }
         else
         {
-            if(face == Face.LEFT)
+            if(loc.getTile().shouldAiUseCollisionBox(loc.getX(), loc.getY()))
+            {
+                switch(face)
+                {
+                    case LEFT:
+                        direction = Face.LEFT;
+                        break;
+                    case RIGHT:
+                        direction = Face.RIGHT;
+                        break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onCollideWithEntity(Entity ent, Face face)
+    {
+        if(ent.getItemCollector().isHero() && hasRedEyes())
+        {
+            ent.getHealth().addHealthPercent(-0.1f);
+            
+            ent.setMotionY(ent.getMotionY() - 20.0f);
+            
+            float hx = ent.getLevel().getHero().getCenterX();
+            if(hx < ent.getCenterX())
             {
-                ent.getAnimator().setFlipped(true);
+                ent.setMotionX(ent.getMotionX() - 10.0f);
             }
-            else if(face == Face.RIGHT)
+            else
             {
-                ent.getAnimator().setFlipped(false);
+                ent.setMotionX(ent.getMotionX() + 10.0f);
             }
         }
-    }*/
+    }
 }

+ 0 - 238
src/me/hammerle/supersnuvi/entity/components/animator/LondonerAnimator.java

@@ -1,238 +0,0 @@
-package me.hammerle.supersnuvi.entity.components.animator;
-
-import me.hammerle.supersnuvi.entity.Entity;
-import me.hammerle.supersnuvi.entity.components.Health;
-import me.hammerle.supersnuvi.util.Utils;
-
-public class LondonerAnimator
-{
-    /*private final static Image[] EVIL_ATTACK = new Image[]
-    {
-        Utils.getImage("londoner/KnC1_a_f1", true),
-        Utils.getImage("londoner/KnC1_a_f2", true),
-        Utils.getImage("londoner/KnC1_a_f3", true),
-        Utils.getImage("londoner/KnC1_a_f4", true),
-        Utils.getImage("londoner/KnC1_a_f5", true)
-    };
-    
-    private final static Image[] EVIL_DEATH = new Image[]
-    {
-        Utils.getImage("londoner/KnC1_d_f1"),
-        Utils.getImage("londoner/KnC1_d_f2"),
-        Utils.getImage("londoner/KnC1_d_f3"),
-        Utils.getImage("londoner/KnC1_d_f4"),
-        Utils.getImage("londoner/KnC1_d_f5"),
-        Utils.getImage("londoner/KnC1_d_f6"),
-        Utils.getImage("londoner/KnC1_d_f7")
-    };
-    
-    private final static Image EVIL_DODGE = Utils.getImage("londoner/KnC1_dodge", true);
-    
-    private final static Image EVIL_IDLE = Utils.getImage("londoner/KnC1_idle", true);
-    
-    private final static Image[] TRANSFORM = new Image[]
-    {
-        Utils.getImage("londoner/KnC1_s_f1", true),
-        Utils.getImage("londoner/KnC1_s_f2", true),
-        Utils.getImage("londoner/KnC1_s_f3", true)
-    };
-    
-    private final static Image[] EVIL_WALK = new Image[]
-    {
-        Utils.getImage("londoner/KnC1_w_f1", true),
-        Utils.getImage("londoner/KnC1_w_f2", true),
-        Utils.getImage("londoner/KnC1_w_f3", true),
-        Utils.getImage("londoner/KnC1_w_f4", true),
-        Utils.getImage("londoner/KnC1_w_f5", true),
-        Utils.getImage("londoner/KnC1_w_f6", true)
-    };
-     
-    private final static Image[] DEATH = new Image[]
-    {
-        Utils.getImage("londoner/londoner1_d_f1"),
-        Utils.getImage("londoner/londoner1_d_f2"),
-        Utils.getImage("londoner/londoner1_d_f3"),
-        Utils.getImage("londoner/londoner1_d_f4"),
-        Utils.getImage("londoner/londoner1_d_f5"),
-        Utils.getImage("londoner/londoner1_d_f6"),
-        Utils.getImage("londoner/londoner1_d_f7")
-    };
-    
-    private final static Image IDLE = Utils.getImage("londoner/londoner1_idle", true);   
-    
-    private final static Image[] WALK = new Image[]
-    {
-        Utils.getImage("londoner/londoner1_w_f1", true),
-        Utils.getImage("londoner/londoner1_w_f2", true),
-        Utils.getImage("londoner/londoner1_w_f3", true),
-        Utils.getImage("londoner/londoner1_w_f4", true),
-        Utils.getImage("londoner/londoner1_w_f5", true),
-        Utils.getImage("londoner/londoner1_w_f6", true)
-    };
-    
-    private int counter = 0;
-    private int frame = 0;
-    
-    private boolean flipped = false;
-    */
-    public LondonerAnimator(Entity ent) 
-    {
-    }
-    /*
-    @Override
-    public int getCombatStartTicks() 
-    {
-        return TRANSFORM.length * 5;
-    }
-    
-    @Override
-    public int getAttackTicks() 
-    {
-        return EVIL_ATTACK.length * 5;
-    }
-    
-    @Override
-    public int getDeathTicks() 
-    {
-        return DEATH.length * 5;
-    }
-    
-    @Override
-    public void resetDefaultFrames()
-    {
-        counter = 0;
-        frame = 0;
-    }
-
-    @Override
-    public void render(IRenderer renderer) 
-    {
-        boolean flip = drawImageFlipped();
-        double x = ent.getX() - 9;
-        double y = ent.getY() + ent.getHeight() - 2;
-        double w = ent.getWidth() * 2;
-        double h = ent.getHeight();
-        
-        if(ent.getHealth().isDead())
-        {
-            Image[] death = ent.getController().isEvil() ? EVIL_DEATH : DEATH;
-            if(frame >= death.length)
-            {
-                frame = 0;
-            }
-            renderer.drawImage(death[frame], x - (flip ? 0 : ent.getWidth()), y, w, h, flip);
-            return;
-        }
-        
-        x -= flip ? ent.getWidth() : 0;
-        
-        if(ent.getController().isInCombatMode())
-        {
-            int combatStart = ent.getController().getCombatTimer();
-            if(combatStart > 0)
-            {
-                combatStart /= 5;
-                bindSlot(TRANSFORM[combatStart]);
-                renderer.drawImage(TRANSFORM[combatStart], x, y, w, h, flip);
-                return;
-            }
-            else if(ent.getController().isDodging())
-            {
-                bindSlot(EVIL_DODGE);
-                renderer.drawImage(EVIL_DODGE, x, y, w, h, flip);
-                return;
-            }
-            else if(ent.getController().isAttacking())
-            {
-                if(frame >= EVIL_ATTACK.length)
-                {
-                    frame = 0;
-                }
-                bindSlot(EVIL_ATTACK[frame]);
-                renderer.drawImage(EVIL_ATTACK[frame], x, y, w, h, flip);
-                return;
-            }
-        }
-        
-        if(ent.getPreviousMotionX() != 0)
-        {
-            Image[] walk = ent.getController().isEvil() ? EVIL_WALK : WALK;
-            if(frame >= walk.length)
-            {
-                frame = 0;
-            }
-            bindSlot(walk[frame]);
-            renderer.drawImage(walk[frame], x, y, w, h, flip);
-        }
-        else
-        {
-            Image idle = ent.getController().isEvil() ? EVIL_IDLE : IDLE;
-            bindSlot(idle);
-            renderer.drawImage(idle, x, y, w, h, flip);
-        }
-    }
-    
-    @Override
-    public boolean drawImageFlipped() 
-    {
-        return flipped;
-    }
-
-    @Override
-    public void tick() 
-    {   
-        counter++;
-        if(counter >= 6) 
-        {
-            counter = 0;
-            frame++;
-        }
-        
-        if(frame < 0)
-        {
-            frame = 0;
-        }       
-        
-        if(ent.getController().isEvil())
-        {
-            flipped = ent.getLevel().getHero().signedDistanceX(ent) < 0;
-        }
-        else
-        {
-            if(ent.getMotionX() < 0)
-            {
-                flipped = true;
-            }
-            else if(ent.getMotionX() > 0)
-            {
-                flipped = false;
-            }
-        }
-    }
-
-    @Override
-    public void setFlipped(boolean flipped) 
-    {
-        this.flipped = flipped;
-    }
-    
-    private void bindSlot(Image image)
-    {
-        if(image != null)
-        {
-            Health h = ent.getHealth();
-            if(h.wasHealed())
-            {
-                image.bindSlot(1);
-            }
-            else if(h.wasHurt())
-            {
-                image.bindSlot(0);
-            }
-            else
-            {
-                image.bindSlot(-1);
-            }
-        }
-    }*/
-}

+ 22 - 23
src/me/hammerle/supersnuvi/gamelogic/Level.java

@@ -13,7 +13,6 @@ import me.hammerle.supersnuvi.Game;
 import me.hammerle.supersnuvi.entity.Entity;
 import me.hammerle.supersnuvi.entity.EntityBuilder;
 import me.hammerle.supersnuvi.tiles.Location;
-import me.hammerle.supersnuvi.tiles.StartTile;
 import me.hammerle.supersnuvi.tiles.Tile;
 import me.hammerle.supersnuvi.util.CollisionObject;
 import me.hammerle.supersnuvi.util.Utils;
@@ -87,9 +86,9 @@ public final class Level
             // debug stuff
             if(name.equals("00-Tech Demo"))
             {
-                int index = data.getBackgroundIndex();
-                /*data.setTile(index, 12, 9, -6);
-                data.setTile(index, 13, 9, -6);
+                int index = data.getBackgroundIndex() + 1;
+                //data.setTile(index, 12, 10, 2);
+                /*data.setTile(index, 13, 9, -6);
                 data.setTile(index, 14, 9, -6);
                 data.setTile(index, 15, 9, -6);
                 data.setTile(index, 16, 9, 6);
@@ -305,25 +304,6 @@ public final class Level
             time += Game.SECS_PER_TICK;
             Game.get().tickTiles();
             
-            // entity spawn layer
-            /*int startX = renderer.getFirstVisibleBlockX();
-            int startY = renderer.getFirstVisibleBlockY();
-            int endX = Math.min(renderer.getLastVisibleBlockX() + 1, data.getWidth());
-            int endY = Math.min(renderer.getLastVisibleBlockY() + 1, data.getHeight());
-            data.forEachEntity((x, y, tile) -> 
-            {
-                if(tile > 0)
-                {
-                    data.deactivateEntity(x, y);
- 
-                    Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
-                    if(ent != null)
-                    {
-                        entities.put(entityCounter++, ent);
-                    }
-                }
-            }, startX, endX, startY, endY);*/
-            
             // doing entity logic first
             entities.values().removeIf(entity -> 
             {
@@ -342,6 +322,25 @@ public final class Level
             oldCameraY = cameraY;
             cameraX = -getViewX(hero.getCenterX());
             cameraY = -getViewY(hero.getCenterY());
+            
+            // entity spawn layer after camera update
+            int startX = (int) (-cameraX / Tile.SIZE);
+            int startY = (int) (-cameraY / Tile.SIZE);
+            int endX = Math.min((int) Math.ceil((-cameraX + Shader.getViewWidth()) / Tile.SIZE), data.getWidth());
+            int endY = Math.min((int) Math.ceil((-cameraY + Shader.getViewHeight()) / Tile.SIZE), data.getWidth());
+            data.forEachEntity((x, y, tile) -> 
+            {
+                if(tile > 0)
+                {
+                    data.deactivateEntity(x, y);
+ 
+                    Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
+                    if(ent != null)
+                    {
+                        entities.put(entityCounter++, ent);
+                    }
+                }
+            }, startX, endX, startY, endY);
         }
     }   
     

+ 64 - 10
src/me/hammerle/supersnuvi/gamelogic/LevelData.java

@@ -91,7 +91,7 @@ public class LevelData
         out.write((i >> 16) & 0xFF);
         out.write((i >> 24) & 0xFF);
     }
-    
+
     private int readInt(FileInputStream in) throws IOException
     {
         int i = 0;
@@ -102,6 +102,29 @@ public class LevelData
         return i;
     }
     
+    private void writeRepeated(int count, int currentTile, FileOutputStream out) throws IOException
+    {
+        while(true)
+        {
+            if(count <= 0)
+            {
+                break;
+            }
+            else if(count >= 255)
+            {
+                count -= 255;
+                out.write(255);
+                writeInt(out, currentTile, false);
+            }
+            else
+            {
+                out.write(count);
+                writeInt(out, currentTile, false);
+                break;
+            }
+        }
+    }
+    
     public boolean save()
     {
         try
@@ -134,20 +157,36 @@ public class LevelData
                 writeInt(out, height, false);
                 
                 // write tiles
-                for(int x = 0; x < layers; x++)
+                if(layers > 0 && width > 0 && height > 0)
                 {
-                    for(int y = 0; y < width; y++)
+                    int count = 0;
+                    int currentTile = tiles[0][0][0];
+
+                    for(int x = 0; x < layers; x++)
                     {
-                        for(int z = 0; z < height; z++)
+                        for(int y = 0; y < width; y++)
                         {
-                            writeInt(out, tiles[x][y][z], false);
+                            for(int z = 0; z < height; z++)
+                            {
+                                if(currentTile == tiles[x][y][z])
+                                {
+                                    count++;
+                                }
+                                else
+                                {
+                                    writeRepeated(count, currentTile, out);
+                                    count = 1;
+                                    currentTile = tiles[x][y][z];
+                                }
+                            }
                         }
                     }
+                    writeRepeated(count, currentTile, out);
                 }
                 
                 out.flush();
                 out.close();
-            }
+            }      
             return true;
         }
         catch(IOException ex)
@@ -199,18 +238,33 @@ public class LevelData
                 // init tiles
                 tiles = new int[layers][width][height];
                 // getting tiles
-                for(int x = 0; x < layers; x++)
+                if(layers > 0 && width > 0 && height > 0)
                 {
-                    for(int y = 0; y < width; y++)
+                    int count = 0;
+                    int currentTile = -1;
+                    
+                    for(int x = 0; x < layers; x++)
                     {
-                        for(int z = 0; z < height; z++)
+                        for(int y = 0; y < width; y++)
                         {
-                            tiles[x][y][z] = readInt(in);
+                            for(int z = 0; z < height; z++)
+                            {
+                                if(count == 0)
+                                {
+                                    count = in.read();
+                                    currentTile = readInt(in);
+                                    //System.out.println(count + " " + currentTile);
+                                }
+                                tiles[x][y][z] = currentTile;
+                                count--;
+                            }
                         }
                     }
                 }
                 
                 in.close();
+                
+                //save();
             }
             return true;
         }

+ 6 - 0
src/me/hammerle/supersnuvi/tiles/NullTile.java

@@ -11,4 +11,10 @@ public class NullTile extends Tile
     {
         return false;
     }
+
+    @Override
+    public boolean shouldAiUseCollisionBox(int x, int y)
+    {
+        return false;
+    }
 }

+ 1 - 1
src/me/hammerle/supersnuvi/tiles/TrampolinTile.java

@@ -16,7 +16,7 @@ public class TrampolinTile extends BaseBoxTile
     {
         if(face == Face.UP)
         {
-            ent.setMotionY(-ent.getMovement().getJumpPower() * 1.5f);
+            ent.setMotionY(-ent.getMovement().getJumpPower());
             SoundUtils.playSound(SoundUtils.Sound.JUMP_ON_BOUNCE_SHROOM);
         }
     }