Making a LibGDX Roguelike Survival Game Part 9 – Screen Shake & Inventory #gamedev

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 ]

shakes

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) :big_shake

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;amp;lt;Integer, Entity&amp;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
*****************

 

 

 

 

 

 

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s