In the last tutorial trees could be removed from the map by interacting (pressing ‘E’) on them, as the trees are being cut down lets add in a small screen shake. On a tree being cut down we will add it the the Hero inventory (we will need to create a basic inventory).

[ Full source code for this tutorial ]

Rumble.java

Rumble allows us to return a Vector allowing us to move the camera relevant to a shake size for a given time in seconds. The variables and methods in this class are all static, so we will be able to use the class without creating an instance of it. Rumble.rumble(1,10) will set the power to 1 and the length of the shake to 10 seconds, the current time is reset to 0.

We have to call the tick method to update the x and y values of the Vector3 to new random values taking into account the size of the shake and update the current time. When current time is greater than time (shake was lasted 10 seconds) we reset the time to 0.

package uk.co.carelesslabs; import java.util.Random; import com.badlogic.gdx.math.Vector3; public class Rumble { private static float time = 0; private static float currentTime = 0; private static float power = 0; private static float currentPower = 0; private static Random random; private static Vector3 pos = new Vector3(); public static void rumble(float rumblePower, float rumbleLength) { random = new Random(); power = rumblePower; time = rumbleLength; currentTime = 0; } public static Vector3 tick(float delta) { if (currentTime <= time) { currentPower = power * ((time - currentTime) / time); pos.x = (random.nextFloat() - 0.5f) * 2 * currentPower; pos.y = (random.nextFloat() - 0.5f) * 2 * currentPower; currentTime += delta; } else { time = 0; } return pos; } public static float getRumbleTimeLeft() { return time; } public static Vector3 getPos() { return pos; } }

Entity.java

The interact method is changed to accept Entity as a parameter:

public void interact(Entity entity){}

Hero.java

When the Hero Entity interacts with another Entity we pass itself, this will give us access to the Hero in the Tree interact method:

// If interact key pressed and interactEntities present interact with first in list. if(control.interact && interactEntities.size() > 0){ interactEntities.get(0).interact(this); }

Tree.java

When a tree is removed we can use Rumble to change the power and time, 1 is a small shake and .2 of a second is a short period:

@Override public void interact(Entity entity){ remove = true; Rumble.rumble(1, .2f); }

gameclass.java

We update the render section of gameclass where previously there was only “camera.position.lerp(hero.pos, .2f);”, we now check if there is a shake/rumble to process, if there is then the camera is taken over by the rumble. When the rumble is complete the camera lerps back the the hero.

// Hero Position if (Rumble.getRumbleTimeLeft() > 0){ Rumble.tick(Gdx.graphics.getDeltaTime()); camera.translate(Rumble.getPos()); } else { camera.position.lerp(hero.pos, .2f); }

Before we look at how we implement a basic inventory lets try out a larger shake just for fun:

Rumble.rumble(3, 5) :

Control.java

Setup the “I” key to turn on inventory, we can use this to print out the current inventory when ever I is pressed:

public boolean inventory; ... // Key up case Keys.I: inventory = true; break;

Inventory.java

This is just a basic class to hold an array of inventory entities and will change in future tutorials. To future proof the idea of the inventory it is better to create a new class rather than testing some inline solution. The class uses a HashMap but any array type would be fine at the moment, we need methods to initialise the array, add to it, return its size and print to console our current inventory:

package uk.co.carelesslabs.entity; import java.util.HashMap; public class Inventory { HashMap&amp;lt;Integer, Entity&amp;gt; entities; public Inventory(){ reset(); } public int getInventorySize(){ return entities.size(); } public void addEntity(Entity entity) { entities.put(getInventorySize(), entity); } public HashMap<Integer, Entity> getInventory(){ return entities; } public void print() { System.out.println("*** Inventory ***"); for(int i = 0 ; i < entities.size(); i++){ Entity e = entities.get(i); System.out.println("* ["+i+"] " + e.type.toString()); } System.out.println("*****************"); } public void reset() { entities = new HashMap<Integer, Entity>(); } }

Entity.java

Add a new Inventory variable to the Entity class:

public Inventory inventory;

Hero.java

Inventory is initialised within Hero and not in the base class, not every Entity will require one:

public Hero(Vector3 pos, Box2DWorld box2d){ type = EntityType.HERO; width = 8; height = 8; texture = Media.hero; speed = 30; inventory = new Inventory(); // Init Inventory reset(box2d, pos); }

Tree.java

When an Entity interacts with a Tree we check if that entity has an inventory, at present only our Hero has an inventory, given this is true we add the Tree to the inventory array of entities, flag the tree for removal from the map and trigger some screen shake, more logic will be applied here later:

@Override public void interact(Entity entity){ if(entity.inventory != null){ entity.inventory.addEntity(this); remove = true; Rumble.rumble(1, .2f); } }

gameclass.java

Checking if inventory key has been pressed we can call the method/function that prints out the entities in the current inventory array and then set inventory boolean to false:

// Render method ... if(control.inventory){ hero.inventory.print(); control.inventory = false; }

Running the application and hitting down some trees our inventory will contain some entities, pressing “I” will print out the current inventory to the console:

*** Inventory ***

* [0] TREE

* [1] TREE

* [2] TREE

*****************