Practical use of the Input

Learn to move the Camera using Player Input.

Now we are going to add the ability to move the Camera around using Keyboard/Mouse and Controllers. Will we add the following code to the update() method in the MainScene method.

Controller Input

We first need to check if the first controller exists. We can do that through the ControllerManager . (Note: If the Input class is used and the controller does not exist, 0 or false is returned instead of an error occurring).

if (getControllerManager().controllerExists(ControllerID.CONTROLLER_ONE)) {
}

Now we can put our controller code in there. We first want to move the Camera around on the X and Z axis. The best way to do that with a controller is to use the an axis, more specifically the left stick.

There is another issue though. We want the Camera to always move forward based upon the direct the Camera is facing. We can achieve this through a special method in the Camera class. movePosition() moves the Camera based on the direction the Camera is facing.

float moveZ = Time.getDeltaTime() * 15f * 
    Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.LEFT_STICK_Y);
    
float moveX = Time.getDeltaTime() * 15f * 
    Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.LEFT_STICK_X);
    
// Move the position in the Z direction using the Left Stick
getCamera().movePosition(0, 0, moveZ);
// Move the position in the X direction using the Left Stick
getCamera().movePosition(moveX, 0, 0);

The code above achieve what we want to do. Notice a new method that we have not used yet. That method is Time.getDeltaTime(). That method returns the time between frames in milliseconds. We use delta time so the camera always move at the same rate no matter the frame rate. That is important since if you don't add that in, the controller will be a different speed on each computer. It is important to note that getGamePadAxis returns a float from -1 to 1 depending on how far you moved the stick in the X or Y direction. Finally, the movePosition method is used to move the Camera based upon the direction it is facing.

If you test it you might notice that the Camera moves a little slow, you can change the speed by changing the 15f value.

Now we want change the rotation of the Camera using the Right Stick. We use a similar way to get the axis as above, except we use moveRotation instead of movePosition.

getCamera().moveRotation(Time.getDeltaTime() * 150f * 
                    Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, 
                                        GamePadAxis.RIGHT_STICK_Y),
                    Time.getDeltaTime() * 150f * Input.getGamePadAxis(
                                        ControllerID.CONTROLLER_ONE, 
                                        GamePadAxis.RIGHT_STICK_X), 
                    0);

Once again we use deltaTime to control the speed and 150f is our speed constant. If you test the code you will now find the complete ability to move in every axis but the Y axis.

We will now just use the A and B buttons to move up or down.

// Move the Camera up in the Y Direction.
if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.A)) {
    getCamera().movePosition(0, 15f * Time.getDeltaTime(), 0);
}
// Move the Camera down in the Y Direction.
if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.B)) {
    getCamera().movePosition(0, -15f * Time.getDeltaTime(), 0);
}

Finally, we will add an easy way to exit the game using the controller via the start button.

// Exit the game.
if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.START))
    gameHandler.exit();

Key Board Input

Now we want to add in Key Board controls for people without controllers. We will start off with using W, A, S, D to control the camera movement on the X and Z axes. Put the following code after the if statement for the controller exist statement:

if (Input.isKeyDown(KeyCode.W)) {
    getCamera().movePosition(0, 0, Time.getDeltaTime() * -15f);
}
if (Input.isKeyDown(KeyCode.S)) {
    getCamera().movePosition(0, 0, Time.getDeltaTime() * 15f);
}
if (Input.isKeyDown(KeyCode.A)) {
    getCamera().movePosition(Time.getDeltaTime() * -15f, 0, 0);
}
if (Input.isKeyDown(KeyCode.D)) {
    getCamera().movePosition(Time.getDeltaTime() * 15f, 0, 0);
}

As you can see the code above is very similar to the code for controllers and shares a lot of the same methods.

Note that an if-else or a switch statement is not used. We want the user to be able to move in multiple directions (diagonal) at the same time.

Now we will also add in the equivalent of the quit button

if(Input.isKeyDown(KeyCode.ESCAPE)){
    gameHandler.exit();
}

Mouse Input

Using the Key Board we are able to move the camera around; however, we are unable to rotate the Camera. While you can use the arrow keys to control the rotation, that is unintuitive. We will use the mouse instead to achieve the same effect. We will calculate the rotation based upon the mouse's delta position (the change in the position between frames). It would be a good idea to disable the cursor first so the cursor won't constantly go off screen when trying to move around.

setCursorStatus(false);

Now we will get the MouseInput to obtain the delta position.

MouseInput mouseInput = gameHandler.getMouseInput();
getCamera().moveRotation((float) (Time.getDeltaTime() * 20f * 
                (mouseInput.getDeltaPosition().y)), 
        (float) (Time.getDeltaTime() * 20f * mouseInput.getDeltaPosition().x), 
        0);

The code above will achieve what we desire. Now the two input systems are equivalent.

Final Code

import org.kakara.engine.GameHandler;
import org.kakara.engine.events.EventHandler;
import org.kakara.engine.events.event.KeyPressEvent;
import org.kakara.engine.gameitems.GameItem;
import org.kakara.engine.gameitems.mesh.Mesh;
import org.kakara.engine.input.Input;
import org.kakara.engine.input.controller.ids.ControllerID;
import org.kakara.engine.input.controller.ids.GamePadAxis;
import org.kakara.engine.input.controller.ids.GamePadButton;
import org.kakara.engine.input.key.KeyCode;
import org.kakara.engine.input.mouse.MouseInput;
import org.kakara.engine.models.StaticModelLoader;
import org.kakara.engine.resources.ResourceManager;
import org.kakara.engine.scene.AbstractGameScene;
import org.kakara.engine.utils.Time;

public class MainScene extends AbstractGameScene {
    public MainScene(GameHandler gameHandler) {
        super(gameHandler);
    }

    @Override
    public void work() {

    }

    @Override
    public void loadGraphics(GameHandler gameHandler) throws Exception {
        ResourceManager rm = gameHandler.getResourceManager();

        Mesh[] monkeyMesh = StaticModelLoader.load(rm.getResource("/monkey.fbx"), "", this, rm);
        GameItem monkey = new GameItem(monkeyMesh);
        monkey.transform.setPosition(0, 0, -10);
        monkey.transform.getRotation().rotateX((float) Math.toRadians(-90));
        add(monkey);
    }

    @EventHandler
    public void onKeyPress(KeyPressEvent event) {
        System.out.println(event.getKeyName());
    }

    @Override
    public void update(float v) {
        // Controller
        if (getControllerManager().controllerExists(ControllerID.CONTROLLER_ONE)) {
            float moveZ = Time.getDeltaTime() * 15f * Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.LEFT_STICK_Y);
            float moveX = Time.getDeltaTime() * 15f * Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.LEFT_STICK_X);
            // Move the position in the Z direction using the Left Stick
            getCamera().movePosition(0, 0, moveZ);
            // Move the position in the X direction using the Left Stick
            getCamera().movePosition(moveX, 0, 0);
            // Rotate the camera based upon the Right Stick.
            getCamera().moveRotation(Time.getDeltaTime() * 150f * Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.RIGHT_STICK_Y),
                    Time.getDeltaTime() * 150f * Input.getGamePadAxis(ControllerID.CONTROLLER_ONE, GamePadAxis.RIGHT_STICK_X), 0);

            // Move the Camera up in the Y Direction.
            if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.A)) {
                getCamera().movePosition(0, 15f * Time.getDeltaTime(), 0);
            }
            // Move the Camera down in the Y Direction.
            if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.B)) {
                getCamera().movePosition(0, -15f * Time.getDeltaTime(), 0);
            }

            // Exit the game.
            if (Input.isGamePadButtonDown(ControllerID.CONTROLLER_ONE, GamePadButton.START))
                gameHandler.exit();
        }

        if (Input.isKeyDown(KeyCode.W)) {
            getCamera().movePosition(0, 0, Time.getDeltaTime() * -15f);
        }
        if (Input.isKeyDown(KeyCode.S)) {
            getCamera().movePosition(0, 0, Time.getDeltaTime() * 15f);
        }
        if (Input.isKeyDown(KeyCode.A)) {
            getCamera().movePosition(Time.getDeltaTime() * -15f, 0, 0);
        }
        if (Input.isKeyDown(KeyCode.D)) {
            getCamera().movePosition(Time.getDeltaTime() * 15f, 0, 0);
        }
        if (Input.isKeyDown(KeyCode.ESCAPE)) {
            gameHandler.exit();
        }

        setCursorStatus(false);

        MouseInput mouseInput = gameHandler.getMouseInput();
        getCamera().moveRotation((float) (Time.getDeltaTime() * 20f * (mouseInput.getDeltaPosition().y)), (float) (Time.getDeltaTime() * 20f * mouseInput.getDeltaPosition().x), 0);
    }
}

Last updated