Skip to content

Creating a Project

Brandon Davis edited this page Oct 27, 2022 · 8 revisions

In this guide I will be walking you through creating a new project using the Terminal Velocity Engine (TVE)

Setup Dependencies

The first thing you should do is create a new gradle java project.

Next using git add https://github.com/TerminalVelocityCabbage/TerminalVelocityEngine as a git sub-module.

You can do this with your git client or just create a .gitmodules file with the following contents

[submodule "TerminalVelocityEngine"]
	path = TerminalVelocityEngine
	url = https://github.com/TerminalVelocityCabbage/TerminalVelocityEngine.git

Then in your build.gradle add this project to your dependencies.

dependencies {
    implementation project('TerminalVelocityEngine')
    implementation project('StudioJar')
}

Then in your settings.gradle add this.

include("TerminalVelocityEngine")
include("StudioJar")
project(':StudioJar').projectDir = file('TerminalVelocityEngine/StudioJar')

Once you initialize the submodule you may need to reload gradle dependencies.

Setting Up Code Structure

The next things you will need to create to have a functional project is a client and a renderer.

First create a renderer class and extend Renderer

import com.terminalvelocitycabbage.engine.client.renderer.Renderer;

public class MultiplayerPongRenderer extends Renderer {

    public MultiplayerPongRenderer(int width, int height, String title, float tickRate, boolean debugMode) {
        super(width, height, title, tickRate, debugMode);
    }
    
}

Next in your main class extend the ClientBase class and define an ID for your project for use all over your project. You should have something that looks like this:

public class MultiplayerPongClient extends ClientBase {

    public static final String ID = "pong";

    public MultiplayerPongClient() {
        super(new Logger(ID), new MultiplayerPongRenderer(1900, 1000, "Pong Client", 60, false));
    }

    public static void main(String[] args) {
        new MultiplayerPongClient();
    }
}

You'll notice that nothing much happens if you run this yet. We need to create a window, luckily we make this very easy to do.

Creating a window and managing scenes

First you need to assign the client context to the class you just created and init and start the game, we will just do that in the constructor of the Client class.

You can see that the renderer we are passing in a width, height, windowTitle, tickrate, and debugMode parameter. these are generally self explanatory, except tickRate just controls the number of updates per second that the game requests updates for.

    public MultiplayerPongClient() {
        super(new Logger(ID), new MultiplayerPongRenderer(1900, 1000, "Pong Client", 60, false));

        //assign client context to this class
        instance = this;
        init();
        start();
    }

For TVE to know what to draw we must first setup a scene. A scene is just an object extending the Scene class provided by TVE that contains all the objects that you may draw to the screen and also houses update logic.

Let's create a scene. First create a scene class and extend Scene. a class extending Scene requires you to implement 2 methods and pass a Camera and a InputHandler to the scene. We will just create placeholders for those for now, we will get into the details of those objects later for now just copy this into your class.

public class GameScene extends Scene {

    public GameScene() {
        super(new FirstPersonCamera(60, 0.1f, 6000f), new InputHandler() {
            @Override
            public void processInput(KeyBind keyBind) {

            }
        });
    }

    @Override
    public void tick(float deltaTime) {

    }

    @Override
    public void destroy() {

    }
}

Next it is just a matter of registering this scene in the renderer and activating it. First override the init method in renderer and add the following to it:

    @Override
    public void init() {
        super.init();
        
        //Register scene
        getSceneHandler().addScene("game_scene", new GameScene());
        
        //Load the scene
        getSceneHandler().loadScene("game_scene");
    }

As you can see above, managing scenes in TVE is very easy, you just need to create a scene object and to activate it you tell the scene handler to load it, they will be initialized and run automatically.

We're almost done, just need to tell everything to turn on when the app starts. In the renderer we need to override the loop method and tell it to push a frame:

    @Override
    public void loop() {
        super.loop();
        push();
    }

Then in our client we need to init the renderer and run the renderer:

    @Override
    public void init() {
        super.init();
        getRenderer().init();
    }

    @Override
    public void start() {
        super.start();
        getRenderer().run();
    }

Running this code should open a window with your requested dimensions and tickrate.

Handling Input

Next let's get rid of that placeholder InputHandler in our scene and make our own. Start by creating a new class that extends InputHandler, we will start with a simple keybind to close the window when we press escape. we first need to create fields for the keys we want to listen to, then initialize them with keys.

public class GameInputHandler extends InputHandler {

    public static KeyBind CLOSE;

    @Override
    public void init(Window window) {
        super.init(window);

        CLOSE = new KeyBind(GLFW_KEY_ESCAPE, KeyBind.ANY, GLFW_RELEASE, KeyBind.NONE);
    }
}

Then in the processInput method we will do things with that input every frame, to close the window we will use the following code:

    @Override
    public void processInput(KeyBind keyBind) {
        if (CLOSE.isKeyPressed()) {
            keyBind.getWindow().queueClose();
        }
    }

Now all you need to do is swap out input handlers in your scene constructor and you'll have a working keybind!

    public GameScene() {
        super(new FirstPersonCamera(60, 0.1f, 6000f), new GameInputHandler());
    }

Clone this wiki locally