Procházet zdrojové kódy

Code Refactoring (menu, player abilities) responsive Menu, Key Rebinding, improved Minus für Gehen, character animation begonnen

Hudriwudri před 4 roky
rodič
revize
9a9f27b37f

binární
res/character/characterWalkRight.png


+ 9 - 44
src/pathgame/PathGame.java

@@ -2,24 +2,21 @@ package pathgame;
 
 import me.hammerle.snuviengine.api.IGame;
 import me.hammerle.snuviengine.api.Renderer;
-import pathgame.gameplay.EscMenu;
 import pathgame.gameplay.Gamestate;
 import pathgame.gameplay.Gamestates;
 import pathgame.gameplay.Keys;
-import pathgame.gameplay.MainMenu;
 import pathgame.rendering.TileMapRenderer;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileMapGenerator;
 import pathgame.gameplay.Player;
-import pathgame.rendering.EscMenuRenderer;
+import pathgame.gameplay.menu.Menu;
 import pathgame.rendering.HUDRenderer;
-import pathgame.rendering.MainMenuRenderer;
+import pathgame.rendering.MenuRenderer;
 import pathgame.rendering.PlayerRenderer;
 import pathgame.rendering.TileRenderer;
 
 public class PathGame implements IGame
 {
-
     private final Gamestate gamestate = new Gamestate();
 
     private final TileMapRenderer mapRenderer = new TileMapRenderer();
@@ -28,12 +25,8 @@ public class PathGame implements IGame
     private final PlayerRenderer playerRenderer = new PlayerRenderer();
     private final Player player = new Player(100, 10);
 
-    private final MainMenuRenderer menuRenderer = new MainMenuRenderer();
-    private final MainMenu menu = new MainMenu();
-
-    private final EscMenuRenderer escMenuRenderer = new EscMenuRenderer();
-    private final EscMenu escMenu = new EscMenu();
-    
+    private final Menu menu = new Menu();
+    private final MenuRenderer menuRenderer = new MenuRenderer();
     private final HUDRenderer hudRenderer = new HUDRenderer();
 
     private float lastScale = 1.0f;
@@ -46,21 +39,12 @@ public class PathGame implements IGame
     @Override
     public void tick()
     {
-        checkForGamestateChange();
         mapRenderer.tick();
-        switch(gamestate.getState())
+        if(gamestate.getState() == Gamestates.GAMEPLAY)
         {
-            case ESCMENU:
-                escMenu.tick(gamestate);
-                break;
-            case GAMEPLAY:
-                player.tick(map);
-                break;
-            case MAINMENU:
-                menu.tick(gamestate);
-                break;
-
+            player.tick(map);
         }
+        menu.tick(gamestate);
 
         lastScale = scale;
         if(Keys.ZOOM_IN_KEY.isDown())
@@ -71,13 +55,11 @@ public class PathGame implements IGame
         {
             scale /= 1.1f;
         }
-
     }
 
     @Override
     public void renderTick(Renderer r, float lag)
     {
-
         float interScale = lastScale + (scale - lastScale) * lag;
         mapRenderer.setScale(interScale);
 
@@ -87,19 +69,15 @@ public class PathGame implements IGame
         mapRenderer.renderTick(map, r, false, offX, offY);
         switch(gamestate.getState())
         {
-            case ESCMENU:
-                escMenuRenderer.renderTick(r, lag, escMenu);
-                    break;
             case GAMEPLAY:
                 playerRenderer.renderTick(map, mapRenderer, r, player, lag, offX, offY);
                 hudRenderer.renderTick(r, player, lag);
                 break;
-            case MAINMENU:
+            case MENU:
                 menuRenderer.renderTick(r, lag, menu);
                 break;
 
         }
-
     }
 
     private float getMapOffsetX(Renderer r, float lag, float interScale)
@@ -137,18 +115,5 @@ public class PathGame implements IGame
     @Override
     public void onStop()
     {
-        //System.out.println("stopped game");
-    }
-
-    private void checkForGamestateChange()
-    {
-        if(Keys.ESCAPE_KEY.isDown() && Keys.ESCAPE_KEY.getTime() == 1 && gamestate.isGamestate(Gamestates.GAMEPLAY))
-        {
-            gamestate.setState(Gamestates.ESCMENU);
-        }
-        else if(Keys.ESCAPE_KEY.isDown() && Keys.ESCAPE_KEY.getTime() == 1 && gamestate.isGamestate(Gamestates.ESCMENU))
-        {
-            gamestate.setState(Gamestates.GAMEPLAY);
-        }
     }
-}
+}

+ 0 - 72
src/pathgame/gameplay/EscMenu.java

@@ -1,72 +0,0 @@
-package pathgame.gameplay;
-
-import me.hammerle.snuviengine.api.Engine;
-
-public class EscMenu
-{
-
-    public enum EscMenuButtons
-    {
-        CONTINUE, MAINMENU, EXIT
-    }
-    private EscMenuButtons activeButton = EscMenuButtons.CONTINUE;
-
-    public void tick(Gamestate gamestate)
-    {
-     
-        if(Keys.UP_KEY.isDown() && Keys.UP_KEY.getTime() == 1 || (Keys.UP_KEY.getTime() >= 20 && Keys.UP_KEY.getTime() % 5 == 1))
-        {
-            
-            activeButton = getPrevButton(activeButton);
-            System.out.println(activeButton);
-        }
-        else if(Keys.DOWN_KEY.isDown() && Keys.DOWN_KEY.getTime() == 1 || (Keys.DOWN_KEY.getTime() >= 20 && Keys.DOWN_KEY.getTime() % 5 == 1))
-        {
-            activeButton = getNextButton(activeButton);
-            System.out.println(activeButton);
-        }
-        else if(Keys.CONFIRM_KEY.isDown() && Keys.CONFIRM_KEY.getTime() == 1)
-        {
-            if(activeButton.equals(EscMenuButtons.EXIT))
-            {
-                Engine.stop();
-            }
-            else if(activeButton.equals(EscMenuButtons.CONTINUE))
-            {
-                gamestate.setState(Gamestates.GAMEPLAY);
-            }
-            else if(activeButton.equals(EscMenuButtons.MAINMENU))
-            {
-                gamestate.setState(Gamestates.MAINMENU);
-            }
-        }
-    }
-
-    public EscMenuButtons getActiveButton()
-    {
-        return activeButton;
-    }
-
-    public boolean isActiveButton(EscMenuButtons button)
-    {
-        return activeButton.equals(button);
-    }
-
-    protected EscMenuButtons getNextButton(EscMenuButtons e)
-    {
-        int index = e.ordinal();
-        int nextIndex = index + 1;
-        EscMenuButtons[] btns = EscMenuButtons.values();
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-
-    protected EscMenuButtons getPrevButton(EscMenuButtons e)
-    {
-        int index = e.ordinal();
-        EscMenuButtons[] btns = EscMenuButtons.values();
-        int nextIndex = index + btns.length - 1;
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-}

+ 1 - 2
src/pathgame/gameplay/Gamestate.java

@@ -2,8 +2,7 @@ package pathgame.gameplay;
 
 public class Gamestate
 {
-
-    private Gamestates state = Gamestates.MAINMENU;
+    private Gamestates state = Gamestates.MENU;
 
     public void setState(Gamestates state)
     {

+ 1 - 1
src/pathgame/gameplay/Gamestates.java

@@ -2,5 +2,5 @@ package pathgame.gameplay;
 
 public enum Gamestates
 {
-    GAMEPLAY, MAINMENU, ESCMENU
+    GAMEPLAY, MENU
 }

+ 0 - 31
src/pathgame/gameplay/LastPlayerMinusSteps.java

@@ -1,31 +0,0 @@
-package pathgame.gameplay;
-
-import java.util.LinkedList;
-
-public class LastPlayerMinusSteps
-{
-
-    private LinkedList<MinusStepsValues> minusEnergy = new LinkedList<>();
-
-    public void addMinus(MinusStepsValues minusEnergy)
-    {
-        this.minusEnergy.add(minusEnergy);
-    }
-
-    public void addMinus(int minusValue, float x, float y)
-    {
-        MinusStepsValues values = new MinusStepsValues(minusValue);
-        addMinus(values);
-    }
-
-    public LinkedList<MinusStepsValues> getLastPlayerSteps()
-    {
-
-        if(minusEnergy.size() > 0 && minusEnergy.getFirst().getLifeTime() <= 0)
-        {
-            minusEnergy.removeFirst();
-        }
-        return minusEnergy;
-    }
-
-}

+ 0 - 146
src/pathgame/gameplay/MainMenu.java

@@ -1,146 +0,0 @@
-package pathgame.gameplay;
-
-import me.hammerle.snuviengine.api.Engine;
-import me.hammerle.snuviengine.api.KeyHandler;
-import org.lwjgl.glfw.GLFW;
-import pathgame.rendering.MainMenuRenderer;
-
-public class MainMenu
-{
-
-    public enum MenuButtons
-    {
-        START, OPTIONS, EXIT
-    }
-
-    public enum KeybindingButtons
-    {
-        UP, DOWN, LEFT, RIGHT, ESCAPE, CONFIRM, ZOOM_IN, ZOOM_OUT, BACK
-    }
-
-    private MenuButtons activeButton = MenuButtons.START;
-    private KeybindingButtons activeKeybindingButton = KeybindingButtons.UP;
-    private boolean optionsIsActive = false;
-
-    public void tick(Gamestate gamestate)
-    {
-
-        if(Keys.UP_KEY.isDown() && Keys.UP_KEY.getTime() == 1 || (Keys.UP_KEY.getTime() >= 20 && Keys.UP_KEY.getTime() % 5 == 1))
-        {
-            if(optionsIsActive)
-            {
-                activeKeybindingButton = getPrevButton(activeKeybindingButton);
-            }
-            else
-            {
-                activeButton = getPrevButton(activeButton);
-            }
-
-            //System.out.println(activeButton);
-        }
-        else if(Keys.DOWN_KEY.isDown() && Keys.DOWN_KEY.getTime() == 1 || (Keys.DOWN_KEY.getTime() >= 20 && Keys.DOWN_KEY.getTime() % 5 == 1))
-        {
-            if(optionsIsActive)
-            {
-                activeKeybindingButton = getNextButton(activeKeybindingButton);
-            }
-            else
-            {
-
-                activeButton = getNextButton(activeButton);
-            }
-        }
-        else if(Keys.CONFIRM_KEY.isDown() && Keys.CONFIRM_KEY.getTime() == 1)
-        {
-            if(optionsIsActive)
-            {
-                if(activeKeybindingButton.equals(KeybindingButtons.UP))
-                {
-                    System.out.println("rebinding");
-
-                    //Todo: Key Rebinding
-                    //Keys.UP_KEY.isRebinding();
-                    //Keys.UP_KEY.getKey();
-                    //Keys.UP_KEY = KeyHandler.register(GLFW.GLFW_KEY_W);
-                }
-                else if(activeKeybindingButton.equals(KeybindingButtons.BACK))
-                {
-                    optionsIsActive = false;
-                }
-            }
-            else
-            {
-                if(activeButton.equals(MenuButtons.EXIT))
-                {
-                    Engine.stop();
-                }
-                else if(activeButton.equals(MenuButtons.START))
-                {
-                    gamestate.setState(Gamestates.GAMEPLAY);
-                }
-                else if(activeButton.equals(MenuButtons.OPTIONS))
-                {
-                    optionsIsActive = true;
-                }
-            }
-
-        }
-    }
-
-    public MenuButtons getActiveButton()
-    {
-        return activeButton;
-    }
-
-    public boolean isActiveButton(MenuButtons button)
-    {
-        return activeButton.equals(button);
-    }
-
-    public boolean isActiveButton(KeybindingButtons button)
-    {
-        return activeKeybindingButton.equals(button);
-    }
-
-    public boolean isOptionsIsActive()
-    {
-        return optionsIsActive;
-    }
-
-    private MenuButtons getNextButton(MenuButtons e)
-    {
-        int index = e.ordinal();
-        int nextIndex = index + 1;
-        MenuButtons[] btns = MenuButtons.values();
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-
-    private MenuButtons getPrevButton(MenuButtons e)
-    {
-        int index = e.ordinal();
-        MenuButtons[] btns = MenuButtons.values();
-        int nextIndex = index + btns.length - 1;
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-
-    private KeybindingButtons getPrevButton(KeybindingButtons e)
-    {
-        int index = e.ordinal();
-        KeybindingButtons[] btns = KeybindingButtons.values();
-        int nextIndex = index + btns.length - 1;
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-
-    private KeybindingButtons getNextButton(KeybindingButtons e)
-    {
-        int index = e.ordinal();
-        int nextIndex = index + 1;
-        KeybindingButtons[] btns = KeybindingButtons.values();
-        nextIndex %= btns.length;
-        return btns[nextIndex];
-    }
-
-}

+ 9 - 24
src/pathgame/gameplay/MinusStepsValues.java

@@ -2,42 +2,27 @@ package pathgame.gameplay;
 
 public class MinusStepsValues
 {
+    private final int minusValue;
+    private int lifeTime = 0;
 
-    private int minusValue;
-    private float diffY = 0;
-    private float lastDiffY = 0;
-    private float lifeTime;
-
-    MinusStepsValues(int minusValue)
+    public MinusStepsValues(int minusValue)
     {
         this.minusValue = minusValue;
-        lifeTime = 3;
     }
 
-    public int getMinusValue()
+    public int getValue()
     {
         return minusValue;
     }
 
-    public float getLifeTime()
+    public int getLifeTime()
     {
         return lifeTime;
     }
 
-    public float getDiffY()
-    {
-        return diffY;
-    }
-
-    public float getLastDiffY()
-    {
-        return lastDiffY;
-    }
-
-    public void updateMinusValues()
+    public boolean tick()
     {
-        lastDiffY = diffY;
-        lifeTime -= 0.07f;
-        diffY += 0.16f;
+        lifeTime++;
+        return lifeTime >= 10;
     }
-}
+}

+ 23 - 45
src/pathgame/gameplay/Player.java

@@ -1,15 +1,15 @@
 package pathgame.gameplay;
 
+import java.util.Iterator;
+import java.util.LinkedList;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.Tiles;
 
 public class Player
 {
-
     private static final float SPEED = 0.125f;
 
-    private PlayerAbilities abilities = new PlayerAbilities();
-    private int currAbilityBoost = 0;
+    private PlayerAbilities abilities;
 
     private float lastX = 0;
     private float lastY = 0;
@@ -25,14 +25,14 @@ public class Player
     private int energyUsed = 0;
     private final int objectivesAmount;
     private int objectivesVisited = 0;
-    private LastPlayerMinusSteps lastSteps = new LastPlayerMinusSteps();
+    private final LinkedList<MinusStepsValues> steps = new LinkedList<>();
     //private int minusEnergy = 0;
 
     public Player(int energySupply, int objectivesAmount)
     {
         this.energySupply = energySupply;
         this.objectivesAmount = objectivesAmount;
-        abilities.setClimberValues();
+        abilities = PlayerAbilities.SWIMMER;
     }
 
     public float getLastX()
@@ -54,54 +54,37 @@ public class Player
     {
         return y;
     }
-
-    public void tick(TileMap map)
+    
+    private void tickSteps()
     {
-        if((map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_3_BUSHES)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_6_BUSHES)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_EARTH)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_FLOWERS)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_HILL)
-                || (map.getTile(Math.round(x), Math.round(y)) == Tiles.GRASS_WITH_STONE))
-        {
-            currAbilityBoost = abilities.getFasterGrass();
-        }
-        else if((map.getTile(Math.round(x), Math.round(y)) == Tiles.FOREST))
-        {
-            currAbilityBoost = abilities.getFasterForest();
-        }
-        else if((map.getTile(Math.round(x), Math.round(y)) == Tiles.HILL))
-        {
-            currAbilityBoost = abilities.getFasterHill();
-        }
-        else if((map.getTile(Math.round(x), Math.round(y)) == Tiles.MOUNTAIN))
-        {
-            currAbilityBoost = abilities.getFasterMountain();
-        }
-        else if((map.getTile(Math.round(x), Math.round(y)) == Tiles.SHALLOW_WATER))
+        Iterator<MinusStepsValues> iter = steps.iterator();
+        while(iter.hasNext())
         {
-            currAbilityBoost = abilities.getFasterShallowWater();
-        }
-        else if((map.getTile(Math.round(x), Math.round(y)) == Tiles.DEEP_WATER))
-        {
-            currAbilityBoost = abilities.getFasterDeepWater();
+            MinusStepsValues next = iter.next();
+            if(next.tick())
+            {
+                iter.remove();
+            }
         }
+    }
 
-        currSpeedSlowdown = map.getTile(Math.round(x), Math.round(y)).getEnergyCost() - currAbilityBoost;
+    public void tick(TileMap map)
+    {
+        tickSteps();
+        
+        currSpeedSlowdown = map.getTile(Math.round(x), Math.round(y)).getEnergyCost(abilities);
         lastX = x;
         lastY = y;
 
         if(isOnTile())
         {
-
             velX = 0.0f;
             velY = 0.0f;
             if(isMoving)
             {
                 ++objectivesVisited;//TODO check for objective
                 //System.out.print(map.getTile((int)x,(int) y).getEnergyCost());
-                lastSteps.addMinus(currSpeedSlowdown, x, y);
+                steps.addLast(new MinusStepsValues(currSpeedSlowdown));
                 energyUsed += currSpeedSlowdown;
             }
             isMoving = false;
@@ -212,13 +195,8 @@ public class Player
         return objectivesVisited;
     }
 
-    public LastPlayerMinusSteps getLastSteps()
-    {
-        return lastSteps;
-    }
-    
-    public PlayerAbilities getAbilities()
+    public LinkedList<MinusStepsValues> getLastSteps()
     {
-        return abilities;
+        return steps;
     }
 }

+ 23 - 67
src/pathgame/gameplay/PlayerAbilities.java

@@ -2,74 +2,31 @@ package pathgame.gameplay;
 
 public class PlayerAbilities
 {
-
-    private int fasterGrass = 0;
-    private int fasterForest = 0;
-    private int fasterShallowWater = 0;
-    private int fasterDeepWater = 0;
-    private int fasterHill = 0;
-    private int fasterMountain = 0;
-    private int fasterSwamp = 0;
-
-    public void setHikerValues()
-    {
-        fasterHill = 1;
-
-        fasterGrass = 0;
-        fasterForest = 0;
-        fasterShallowWater = 0;
-        fasterDeepWater = 0;
-        fasterMountain = 0;
-        fasterSwamp = 0;
-    }
-
-    public void setClimberValues()
+    private final int fasterGrass;
+    private final int fasterForest;
+    private final int fasterShallowWater;
+    private final int fasterDeepWater;
+    private final int fasterHill;
+    private final int fasterMountain;
+    private final int fasterSwamp;
+    
+    public PlayerAbilities(int fasterGrass, int fasterForest, int fasterShallowWater, 
+            int fasterDeepWater, int fasterHill, int fasterMountain, int fasterSwamp)
     {
-        fasterMountain = 1;
-        
-        fasterGrass = 0;
-        fasterForest = 0;
-        fasterShallowWater = 0;
-        fasterDeepWater = 0;
-        fasterHill = 0;
-        fasterSwamp = 0;
+        this.fasterGrass = fasterGrass;
+        this.fasterForest = fasterForest;
+        this.fasterShallowWater = fasterShallowWater;
+        this.fasterDeepWater = fasterDeepWater;
+        this.fasterHill = fasterHill;
+        this.fasterMountain = fasterMountain;
+        this.fasterSwamp = fasterSwamp;
     }
 
-    public void setForesterValues()
-    {
-        fasterForest = 1;
-        
-        fasterGrass = 0;
-        fasterShallowWater = 0;
-        fasterDeepWater = 0;
-        fasterHill = 0;
-        fasterMountain = 0;
-        fasterSwamp = 0;
-    }
-
-    public void setSwimmerValues()
-    {
-        fasterShallowWater = 2;
-        
-        fasterGrass = 0;
-        fasterForest = 0;
-        fasterDeepWater = 0;
-        fasterHill = 0;
-        fasterMountain = 0;
-        fasterSwamp = 0;
-    }
-
-    public void setSailorValues()
-    {
-        fasterDeepWater = 1;
-        
-        fasterGrass = 0;
-        fasterForest = 0;
-        fasterShallowWater = 0;
-        fasterHill = 0;
-        fasterMountain = 0;
-        fasterSwamp = 0;
-    }
+    public final static PlayerAbilities HIKER = new PlayerAbilities(0, 0, 0, 0, 1, 0, 0);
+    public final static PlayerAbilities CLIMBER = new PlayerAbilities(0, 0, 0, 0, 0, 1, 0);
+    public final static PlayerAbilities FOREST = new PlayerAbilities(0, 1, 0, 0, 0, 0, 0);
+    public final static PlayerAbilities SWIMMER = new PlayerAbilities(0, 0, 2, 0, 0, 0, 0);
+    public final static PlayerAbilities SAILOR = new PlayerAbilities(0, 0, 0, 1, 0, 0, 0);
 
     public int getFasterGrass()
     {
@@ -105,5 +62,4 @@ public class PlayerAbilities
     {
         return fasterSwamp;
     }
-
-}
+}

+ 75 - 0
src/pathgame/gameplay/menu/BaseMenu.java

@@ -0,0 +1,75 @@
+package pathgame.gameplay.menu;
+
+import pathgame.gameplay.Gamestate;
+import pathgame.gameplay.Keys;
+
+public abstract class BaseMenu
+{
+    private final int id;
+    private int index = 0;
+    public abstract MenuOption[] getOptions();
+    private int returnId;
+    
+    public BaseMenu(int id)
+    {
+        this.id = id;
+    }
+    
+    public int getActiveIndex()
+    {
+        return index;
+    }
+    
+    public boolean isOptionMenu()
+    {
+        return false;
+    }
+    
+    public int tick(Gamestate gamestate)
+    {
+        returnId = id;
+        if(isUpPressed())
+        {
+            int length = getOptions().length;
+            index = ((index - 1) + length) % length;
+        }
+        else if(isDownPressed())
+        {
+            index = (index + 1) % getOptions().length;
+        }
+        else if(isEnterPressed())
+        {
+            getOptions()[index].run(gamestate);
+        }
+        if(returnId != id)
+        {
+            index = 0;
+        }
+        return returnId;
+    }
+    
+    public void setReturnId(int id)
+    {
+        returnId = id;
+    }
+            
+    private boolean isUpPressed()
+    {
+        return Keys.UP_KEY.isDown() && Keys.UP_KEY.getTime() == 1 || (Keys.UP_KEY.getTime() >= 20 && Keys.UP_KEY.getTime() % 5 == 1);
+    }
+    
+    private boolean isDownPressed()
+    {
+        return Keys.DOWN_KEY.isDown() && Keys.DOWN_KEY.getTime() == 1 || (Keys.DOWN_KEY.getTime() >= 20 && Keys.DOWN_KEY.getTime() % 5 == 1);
+    }
+    
+    private boolean isEnterPressed()
+    {
+        return Keys.CONFIRM_KEY.isDown() && Keys.CONFIRM_KEY.getTime() == 1;
+    }
+    
+    public void resetIndex()
+    {
+        index = 0;
+    }
+}

+ 36 - 0
src/pathgame/gameplay/menu/EscMenu.java

@@ -0,0 +1,36 @@
+package pathgame.gameplay.menu;
+
+import me.hammerle.snuviengine.api.Engine;
+import pathgame.gameplay.Gamestates;
+
+public class EscMenu extends BaseMenu
+{
+    private final MenuOption[] options;
+    
+    public EscMenu(int id, int mainId)
+    {
+        super(id);
+        
+        options = new MenuOption[] 
+        {
+            new MenuOption("Continue", (gamestate) -> 
+            {
+                gamestate.setState(Gamestates.GAMEPLAY);
+            }),
+            new MenuOption("Main Menu", (gamestate) -> 
+            {
+                setReturnId(mainId);
+            }),
+            new MenuOption("Exit", (gamestate) -> 
+            {
+                Engine.stop();
+            }),
+        };
+    }
+
+    @Override
+    public MenuOption[] getOptions()
+    {
+        return options;
+    }
+}

+ 36 - 0
src/pathgame/gameplay/menu/MainMenu.java

@@ -0,0 +1,36 @@
+package pathgame.gameplay.menu;
+
+import me.hammerle.snuviengine.api.Engine;
+import pathgame.gameplay.Gamestates;
+
+public class MainMenu extends BaseMenu
+{
+    private final MenuOption[] options;
+    
+    public MainMenu(int id, int optionsId)
+    {
+        super(id);
+        
+        options = new MenuOption[] 
+        {
+            new MenuOption("Start", (gamestate) -> 
+            {
+                gamestate.setState(Gamestates.GAMEPLAY);
+            }),
+            new MenuOption("Options", (gamestate) -> 
+            {
+                setReturnId(optionsId);
+            }),
+            new MenuOption("Exit", (gamestate) -> 
+            {
+                Engine.stop();
+            })
+        }; 
+    }
+
+    @Override
+    public MenuOption[] getOptions()
+    {
+        return options;
+    }
+}

+ 67 - 0
src/pathgame/gameplay/menu/Menu.java

@@ -0,0 +1,67 @@
+package pathgame.gameplay.menu;
+
+import pathgame.gameplay.Gamestate;
+import pathgame.gameplay.Gamestates;
+import pathgame.gameplay.Keys;
+
+public class Menu
+{
+    private final static int MAIN_ID;
+    private final static int ESCAPE_ID;
+    private final static int OPTION_ID;
+    
+    static
+    {
+        int id = 0;
+        MAIN_ID = id++;
+        ESCAPE_ID = id++;
+        OPTION_ID = id++;
+    }
+    
+    private final BaseMenu[] menus = new BaseMenu[] 
+    { 
+        new MainMenu(MAIN_ID, OPTION_ID), 
+        new EscMenu(ESCAPE_ID, MAIN_ID), 
+        new OptionMenu(OPTION_ID, MAIN_ID) 
+    };
+    
+    private int currentIndex = 0;
+    
+    public void tick(Gamestate gamestate)
+    {
+        if(gamestate.getState() == Gamestates.MENU)
+        {
+            currentIndex = menus[currentIndex].tick(gamestate);
+            if(currentIndex == ESCAPE_ID && Keys.ESCAPE_KEY.getTime() == 1)
+            {
+                gamestate.setState(Gamestates.GAMEPLAY);
+            }
+        }
+        else if(gamestate.getState() == Gamestates.GAMEPLAY && Keys.ESCAPE_KEY.getTime() == 1)
+        {
+            currentIndex = ESCAPE_ID;
+            gamestate.setState(Gamestates.MENU);
+            menus[currentIndex].resetIndex();
+        }
+    }
+    
+    public MenuOption[] getOptions()
+    {
+        return menus[currentIndex].getOptions();
+    }
+    
+    public int getActiveIndex()
+    {
+        return menus[currentIndex].getActiveIndex();
+    }
+    
+    public boolean isOptionMenu()
+    {
+        return menus[currentIndex].isOptionMenu();
+    }
+    
+    public void showEscapeMenu()
+    {
+        currentIndex = ESCAPE_ID;
+    }
+}

+ 26 - 0
src/pathgame/gameplay/menu/MenuOption.java

@@ -0,0 +1,26 @@
+package pathgame.gameplay.menu;
+
+import java.util.function.Consumer;
+import pathgame.gameplay.Gamestate;
+
+public class MenuOption
+{
+    private final String name;
+    private final Consumer<Gamestate> r;
+    
+    public MenuOption(String name, Consumer<Gamestate> r)
+    {
+        this.name = name;
+        this.r = r;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+    
+    public void run(Gamestate gamestate)
+    {
+        r.accept(gamestate);
+    }
+}

+ 66 - 0
src/pathgame/gameplay/menu/OptionMenu.java

@@ -0,0 +1,66 @@
+package pathgame.gameplay.menu;
+
+import me.hammerle.snuviengine.api.KeyHandler;
+import pathgame.gameplay.Keys;
+
+public class OptionMenu extends BaseMenu
+{
+    private final MenuOption[] options; 
+    
+    public OptionMenu(int id, int mainId)
+    {
+        super(id);
+        
+        options = new MenuOption[] 
+        {
+            new MenuOption("Up Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.UP_KEY);
+            }),
+            new MenuOption("Down Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.DOWN_KEY);
+            }),
+            new MenuOption("Left Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.LEFT_KEY);
+            }),
+            new MenuOption("Right Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.RIGHT_KEY);
+            }),
+            new MenuOption("Escape Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.ESCAPE_KEY);
+            }),
+            new MenuOption("Confirm Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.CONFIRM_KEY);
+            }),
+            new MenuOption("Zoom In Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.ZOOM_IN_KEY);
+            }),
+            new MenuOption("Zoom Out Key", (gamestate) -> 
+            {
+                KeyHandler.rebind(Keys.ZOOM_OUT_KEY);
+            }),
+            new MenuOption("Back to Main Menu", (gamestate) -> 
+            {
+                setReturnId(mainId);
+            }),
+        };
+    }
+
+    @Override
+    public MenuOption[] getOptions()
+    {
+        return options;
+    }
+
+    @Override
+    public boolean isOptionMenu()
+    {
+        return true;
+    }
+}

+ 0 - 49
src/pathgame/rendering/EscMenuRenderer.java

@@ -1,49 +0,0 @@
-
-package pathgame.rendering;
-
-import me.hammerle.snuviengine.api.Renderer;
-import pathgame.gameplay.EscMenu;
-
-public class EscMenuRenderer
-{
-    public void renderTick(Renderer r, float lag, EscMenu escMenu)
-    {
-        r.translateTo(0.0f, 0.0f);
-        r.scale(2.0f, 2.0f);
-        r.updateMatrix();
-
-        renderBackground(r);
-        renderButton("Continue", r.getViewHeight() * 0.25f - 20 - r.getFontRenderer().getSize("Continue").getHeight() * 0.5f, escMenu.isActiveButton(EscMenu.EscMenuButtons.CONTINUE), r);
-        renderButton("Main Menu", r.getViewHeight() * 0.25f - r.getFontRenderer().getSize("Main Menu").getHeight() * 0.5f, escMenu.isActiveButton(EscMenu.EscMenuButtons.MAINMENU), r);
-        renderButton("Exit", r.getViewHeight() * 0.25f + 20 - r.getFontRenderer().getSize("Exit").getHeight() * 0.5f, escMenu.isActiveButton(EscMenu.EscMenuButtons.EXIT), r);
-    
-        
-    }
-    
-    private void renderButton(String text, float y, boolean active, Renderer r)
-    {
-        r.setMixColorEnabled(false);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(true);
-        String s = text;
-        if(active)
-        {
-            s = "&f" + s;
-        }
-        else
-        {
-            s = "&7" + s;
-        }
-        r.getFontRenderer().drawString(r.getViewWidth() * 0.25f - (r.getFontRenderer().getSize(s).getWidth() * 0.5f), y, s);
-    }
-
-    private void renderBackground(Renderer r)
-    {
-        r.setMixColorEnabled(true);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(false);
-        r.setBlendingEnabled(true);
-
-        r.getColorRenderer().drawRectangle(r.getViewWidth() * 0.25f - 100, r.getViewHeight() * 0.25f - 50, r.getViewWidth() * 0.25f + 100, r.getViewHeight() * 0.25f + 50, 0x33_00_00_00);//ABGR
-    }
-}

+ 7 - 19
src/pathgame/rendering/HUDRenderer.java

@@ -1,18 +1,15 @@
 package pathgame.rendering;
 
-import java.util.Map;
+import java.util.LinkedList;
 import me.hammerle.snuviengine.api.Renderer;
 import me.hammerle.snuviengine.api.Texture;
+import pathgame.gameplay.MinusStepsValues;
 import pathgame.gameplay.Player;
-import pathgame.gameplay.LastPlayerMinusSteps;
-import pathgame.tilemap.TileMap;
 
 public class HUDRenderer
 {
-
     private static final Texture ENERGYBAR = new Texture("res/energyBar.png");
     private static final Texture ENERGYBARGREY = new Texture("res/energyBarGrey.png");
-    private LastPlayerMinusSteps lastSteps = new LastPlayerMinusSteps();
 
     public void renderTick(Renderer r, Player p, float lag)//TileMap map, TileMapRenderer map, float lag, float offX, float offY)
     {
@@ -86,20 +83,11 @@ public class HUDRenderer
         r.setColorEnabled(true);
         r.setTextureEnabled(true);
 
-        String minusEnergy = "";
-
-        for(int i = 0; i < p.getLastSteps().getLastPlayerSteps().size(); ++i)
+        LinkedList<MinusStepsValues> steps = p.getLastSteps();
+        for(MinusStepsValues step : steps)
         {
-            minusEnergy = "&4-" + String.valueOf(p.getLastSteps().getLastPlayerSteps().get(i).getMinusValue());
-            //r.getFontRenderer().drawString(p.getLastSteps().getLastPlayerSteps().get(i).getX()*32, p.getLastSteps().getLastPlayerSteps().get(i).getY()*32, minusEnergy);
-            float YPos = 3 + (p.getLastSteps().getLastPlayerSteps().get(i).getLastDiffY()
-                    + (p.getLastSteps().getLastPlayerSteps().get(i).getDiffY()
-                    - p.getLastSteps().getLastPlayerSteps().get(i).getLastDiffY())
-                    * lag);
-            //System.out.println(YPos);
-            r.getFontRenderer().drawString(r.getViewWidth() * 0.5f
-                    - 63, YPos, minusEnergy);
-            p.getLastSteps().getLastPlayerSteps().get(i).updateMinusValues(); //todo: outsource to tick
+            String minusEnergy = String.format("&4-%d", step.getValue());
+            r.getFontRenderer().drawString(r.getViewWidth() * 0.5f - 63, 3 + step.getLifeTime() + lag, minusEnergy);
         }
     }
-}
+}

+ 0 - 100
src/pathgame/rendering/MainMenuRenderer.java

@@ -1,100 +0,0 @@
-package pathgame.rendering;
-
-import me.hammerle.snuviengine.api.Renderer;
-import pathgame.gameplay.Keys;
-import pathgame.gameplay.MainMenu;
-
-public class MainMenuRenderer
-{
-
-    public void renderTick(Renderer r, float lag, MainMenu menu)
-    {
-        r.translateTo(0.0f, 0.0f);
-        r.scale(2.0f, 2.0f);
-        r.updateMatrix();
-
-        if(menu.isOptionsIsActive())
-        {
-            renderBigBackground(r);
-
-            renderOptionButton("Up Key", Keys.UP_KEY.getName(), r.getViewHeight() * 0.25f - 60 - r.getFontRenderer().getSize("Up Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.UP), r);
-            renderOptionButton("Down Key", Keys.DOWN_KEY.getName(), r.getViewHeight() * 0.25f - 45 - r.getFontRenderer().getSize("Down Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.DOWN), r);
-            renderOptionButton("Left Key", Keys.LEFT_KEY.getName(), r.getViewHeight() * 0.25f - 30 - r.getFontRenderer().getSize("Left Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.LEFT), r);
-            renderOptionButton("Right Key", Keys.RIGHT_KEY.getName(), r.getViewHeight() * 0.25f - 15 - r.getFontRenderer().getSize("Right Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.RIGHT), r);
-            renderOptionButton("Escape Key", Keys.ESCAPE_KEY.getName(), r.getViewHeight() * 0.25f + 0 - r.getFontRenderer().getSize("Escape Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.ESCAPE), r);
-            renderOptionButton("Confirm Key", Keys.CONFIRM_KEY.getName(), r.getViewHeight() * 0.25f + 15 - r.getFontRenderer().getSize("Confirm Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.CONFIRM), r);
-            renderOptionButton("Zoom In Key", Keys.ZOOM_IN_KEY.getName(), r.getViewHeight() * 0.25f + 30 - r.getFontRenderer().getSize("Zoom In Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.ZOOM_IN), r);
-            renderOptionButton("Zoom Out Key", Keys.ZOOM_OUT_KEY.getName(), r.getViewHeight() * 0.25f + 45 - r.getFontRenderer().getSize("Zoom Out Key").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.ZOOM_OUT), r);
-            renderButton("Back to Main Menu", r.getViewHeight() * 0.25f + 70 - r.getFontRenderer().getSize("Back to Main Menu").getHeight() * 0.5f, menu.isActiveButton(MainMenu.KeybindingButtons.BACK), r);
-
-        }
-        else
-        {
-            renderBackground(r);
-
-            renderButton("Start", r.getViewHeight() * 0.25f - 20 - r.getFontRenderer().getSize("Start").getHeight() * 0.5f, menu.isActiveButton(MainMenu.MenuButtons.START), r);
-            renderButton("Options", r.getViewHeight() * 0.25f - r.getFontRenderer().getSize("Options").getHeight() * 0.5f, menu.isActiveButton(MainMenu.MenuButtons.OPTIONS), r);
-            renderButton("Exit", r.getViewHeight() * 0.25f + 20 - r.getFontRenderer().getSize("Exit").getHeight() * 0.5f, menu.isActiveButton(MainMenu.MenuButtons.EXIT), r);
-
-        }
-    }
-
-    private void renderButton(String text, float y, boolean active, Renderer r)
-    {
-        r.setMixColorEnabled(false);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(true);
-        String s = text;
-        if(active)
-        {
-            s = "&f" + s;
-        }
-        else
-        {
-            s = "&7" + s;
-        }
-        r.getFontRenderer().drawString(r.getViewWidth() * 0.25f - (r.getFontRenderer().getSize(s).getWidth() * 0.5f), y, s);
-    }
-
-    private void renderOptionButton(String text, String binding, float y, boolean active, Renderer r)
-    {
-        r.setMixColorEnabled(false);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(true);
-        String s = text;
-        String b = binding;
-        if(active)
-        {
-            s = "&f" + s;
-            b = "&f" + b;
-        }
-        else
-        {
-            s = "&7" + s;
-            b = "&7" + b;
-        }
-        //r.getFontRenderer().drawString(r.getViewWidth() * 0.25f - (r.getFontRenderer().getSize(s).getWidth() * 0.5f), y, s+" - "+binding);
-        r.getFontRenderer().drawString(50, y, s);
-        r.getFontRenderer().drawString(180 - (r.getFontRenderer().getSize(binding).getWidth() * 0.5f), y, b);
-    }
-
-    private void renderBackground(Renderer r)
-    {
-        r.setMixColorEnabled(true);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(false);
-        r.setBlendingEnabled(true);
-
-        r.getColorRenderer().drawRectangle(r.getViewWidth() * 0.25f - 100, r.getViewHeight() * 0.25f - 50, r.getViewWidth() * 0.25f + 100, r.getViewHeight() * 0.25f + 50, 0x33_00_00_00);//ABGR
-    }
-
-    private void renderBigBackground(Renderer r)
-    {
-        r.setMixColorEnabled(true);
-        r.setColorEnabled(true);
-        r.setTextureEnabled(false);
-        r.setBlendingEnabled(true);
-
-        r.getColorRenderer().drawRectangle(r.getViewWidth() * 0.25f - 100, r.getViewHeight() * 0.25f - 75, r.getViewWidth() * 0.25f + 100, r.getViewHeight() * 0.25f + 80, 0x33_00_00_00);//ABGR
-    }
-}

+ 116 - 0
src/pathgame/rendering/MenuRenderer.java

@@ -0,0 +1,116 @@
+package pathgame.rendering;
+
+import me.hammerle.snuviengine.api.KeyBinding;
+import me.hammerle.snuviengine.api.Renderer;
+import pathgame.gameplay.Keys;
+import pathgame.gameplay.menu.Menu;
+import pathgame.gameplay.menu.MenuOption;
+
+public class MenuRenderer
+{
+    private final KeyBinding[] keys = new KeyBinding[]
+    {
+        Keys.UP_KEY,
+        Keys.DOWN_KEY,
+        Keys.LEFT_KEY,
+        Keys.RIGHT_KEY,
+        Keys.ESCAPE_KEY,
+        Keys.CONFIRM_KEY,
+        Keys.ZOOM_IN_KEY,
+        Keys.ZOOM_OUT_KEY
+    };
+
+    private final float keyWidths[] = new float[keys.length];
+
+    public void renderTick(Renderer r, float lag, Menu menu)
+    {
+        r.translateTo(0.0f, 0.0f);
+        float scale = 2.0f;
+        r.scale(scale, scale);
+        r.updateMatrix();
+        scale = 1.0f / scale;
+
+        MenuOption[] options = menu.getOptions();
+
+        float lastGap = 10.0f;
+        float baseBoxHeight = 300.0f * scale;
+        float textBoxPaddingY = (100.0f - (20.0f / 3.0f) * options.length) * scale;
+        float windowHeight = r.getViewHeight() * scale;
+        float windowWidth = r.getViewWidth() * scale;
+
+        float y = (windowHeight - baseBoxHeight) * 0.5f + textBoxPaddingY;
+        float textBoxHeight = baseBoxHeight - textBoxPaddingY * 2;
+        float step = (textBoxHeight - r.getFontRenderer().getHeight()) / (options.length - 1) - lastGap / (options.length - 2);
+
+        r.setMixColorEnabled(false);
+        r.setColorEnabled(true);
+        r.setTextureEnabled(false);
+        r.setBlendingEnabled(true);
+
+        r.getColorRenderer().drawRectangle(windowWidth * 0.10f, y - textBoxPaddingY * 0.5f, windowWidth * 0.90f, y + textBoxHeight + textBoxPaddingY * 0.5f, 0x33000000);
+
+        r.setTextureEnabled(true);
+
+        if(!menu.isOptionMenu())
+        {
+            for(int i = 0; i < options.length - 1; i++)
+            {
+                renderText(options[i].getName(), menu.getActiveIndex() == i, r, windowWidth, y, false);
+                y += step;
+            }
+            y += lastGap;
+            renderText(options[options.length - 1].getName(), menu.getActiveIndex() == options.length - 1, r, windowWidth, y, false);
+        }
+        else
+        {
+            float max = Float.MIN_VALUE;
+            for(int i = 0; i < keys.length; i++)
+            {
+                keyWidths[i] = r.getFontRenderer().getSize(getKeyName(keys[i])).getWidth();
+                if(keyWidths[i] > max)
+                {
+                    max = keyWidths[i];
+                }
+            }
+
+            for(int i = 0; i < options.length - 1; i++)
+            {
+                boolean active = menu.getActiveIndex() == i;
+                renderText(options[i].getName(), active, r, windowWidth, y, true);
+                r.getFontRenderer().drawString(windowWidth * 0.85f - max * 0.5f - keyWidths[i] * 0.5f, y, addColor(getKeyName(keys[i]), active));
+                y += step;
+            }
+            y += lastGap;
+            renderText(options[options.length - 1].getName(), menu.getActiveIndex() == options.length - 1, r, windowWidth, y, true);
+        }
+    }
+
+    private void renderText(String s, boolean active, Renderer r, float wWidth, float y, boolean left)
+    {
+        if(left)
+        {
+            r.getFontRenderer().drawString(wWidth * 0.15f, y, addColor(s, active));
+        }
+        else
+        {
+            r.getFontRenderer().drawString(wWidth * 0.5f - (r.getFontRenderer().getSize(s).getWidth() * 0.5f), y, addColor(s, active));
+        }
+    }
+    
+    private String addColor(String s, boolean active)
+    {
+        return (active ? "&f" : "&7") + s;
+    }
+    
+    private String getKeyName(KeyBinding key)
+    {
+        if(key.isRebinding())
+        {
+            return "[...]";
+        }
+        else
+        {
+            return key.getName();
+        }
+    }
+}

+ 27 - 3
src/pathgame/rendering/PlayerRenderer.java

@@ -46,10 +46,34 @@ public class PlayerRenderer
             CHARACTER.bind();
         }
 
-        float ix = (p.getLastX() + (p.getX() - p.getLastX()) * lag) * mapR.getScale() * TileRenderer.TILE_SIZE + offX;
+        float baseX = (p.getLastX() + (p.getX() - p.getLastX()) * lag);
+        float ix = baseX * mapR.getScale() * TileRenderer.TILE_SIZE + offX;
 
-        //System.out.println(ix);
+//        //TODO: refactor
+//        baseX = baseX - (int) baseX;
+//        int tIndex = 0;
+//        if(baseX <= 0.125f)
+//        {
+//            tIndex = 0;
+//        }
+//        else if(baseX <= 0.375f)
+//        {
+//            tIndex = 1;
+//        }
+//        else if(baseX <= 0.625f)
+//        {
+//            tIndex = 2;
+//        }
+//        else if(baseX <= 0.875f)
+//        {
+//            tIndex = 3;
+//        }
+//        
+//        System.out.println(baseX);
         float iy = (p.getLastY() + (p.getY() - p.getLastY()) * lag) * mapR.getScale() * TileRenderer.TILE_SIZE + offY;
-        r.getTextureRenderer().drawRectangle(ix, iy, ix + playerSize, iy + playerSize, 0, 0, 1, 1); //TODO: change last 4 texture coordinates for animation 
+//        r.getTextureRenderer().drawRectangle(ix, iy, ix + playerSize, iy + playerSize, 
+//                tIndex * 0.25f, 0.0f, (tIndex + 1) * 0.25f, 1.0f);
+r.getTextureRenderer().drawRectangle(ix, iy, ix + playerSize, iy + playerSize, 
+                0.0f, 0.0f, 1.0f, 1.0f);
     }
 }

+ 17 - 4
src/pathgame/tilemap/Tile.java

@@ -1,5 +1,8 @@
 package pathgame.tilemap;
 
+import java.util.function.Function;
+import pathgame.gameplay.PlayerAbilities;
+
 /** Base class for tiles. Tiles are registered on construction.
  *
  * @author kajetan
@@ -38,15 +41,25 @@ public class Tile
     private final int id;
     private final int energyCost;
     private final float forestReplaceChance;
+    private final Function<PlayerAbilities, Integer> speedUp;
     
     /** Creates a new tile, which is automatically registered.
      *
      */
-    public Tile(int energyCost, float forestReplaceChance)
+    public Tile(int energyCost, float forestReplaceChance, Function<PlayerAbilities, Integer> speedUp)
     {
         id = addTile(this);
         this.energyCost = energyCost;
         this.forestReplaceChance = forestReplaceChance;
+        this.speedUp = speedUp;
+    }
+    
+    /** Creates a new tile, which is automatically registered.
+     *
+     */
+    public Tile(int energyCost, Function<PlayerAbilities, Integer> speedUp)
+    {
+        this(energyCost, 1.0f, speedUp);
     }
     
     /** Creates a new tile, which is automatically registered.
@@ -54,7 +67,7 @@ public class Tile
      */
     public Tile(int energyCost)
     {
-        this(energyCost, 1.0f);
+        this(energyCost, 1.0f, (pa) -> 0);
     }
 
     /** Returns the id of the tile.
@@ -66,9 +79,9 @@ public class Tile
         return id;
     }
     
-    public int getEnergyCost()
+    public int getEnergyCost(PlayerAbilities pa)
     {
-        return energyCost;
+        return energyCost - speedUp.apply(pa);
     }
 
     /** Returns the chance that this tile is replaced by forest.

+ 12 - 12
src/pathgame/tilemap/Tiles.java

@@ -2,13 +2,13 @@ package pathgame.tilemap;
 
 public class Tiles
 {
-    public final static Tile GRASS = new Tile(1);
-    public final static Tile GRASS_WITH_STONE = new Tile(1);
-    public final static Tile GRASS_WITH_6_BUSHES = new Tile(1);
-    public final static Tile GRASS_WITH_3_BUSHES = new Tile(1);
-    public final static Tile GRASS_WITH_FLOWERS = new Tile(1);
-    public final static Tile GRASS_WITH_HILL = new Tile(1);
-    public final static Tile GRASS_WITH_EARTH = new Tile(1);
+    public final static Tile GRASS = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_STONE = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_6_BUSHES = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_3_BUSHES = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_FLOWERS = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_HILL = new Tile(1, (pa) -> pa.getFasterGrass());
+    public final static Tile GRASS_WITH_EARTH = new Tile(1, (pa) -> pa.getFasterGrass());
     
     public final static Tile[] GRASS_VARIANTS = new Tile[]
     {
@@ -16,9 +16,9 @@ public class Tiles
         GRASS_WITH_FLOWERS, GRASS_WITH_HILL, GRASS_WITH_EARTH
     };
     
-    public final static Tile FOREST = new Tile(2);
-    public final static Tile SHALLOW_WATER = new Tile(3, 0.0f);
-    public final static Tile DEEP_WATER = new Tile(5, 0.0f);
-    public final static Tile HILL = new Tile(3, 0.5f);
-    public final static Tile MOUNTAIN = new Tile(5, 0.0f);
+    public final static Tile FOREST = new Tile(2, (pa) -> pa.getFasterForest());
+    public final static Tile SHALLOW_WATER = new Tile(3, 0.0f, (pa) -> pa.getFasterShallowWater());
+    public final static Tile DEEP_WATER = new Tile(5, 0.0f, (pa) -> pa.getFasterDeepWater());
+    public final static Tile HILL = new Tile(3, 0.5f, (pa) -> pa.getFasterHill());
+    public final static Tile MOUNTAIN = new Tile(5, 0.0f, (pa) -> pa.getFasterMountain());
 }