seventh.client.SeventhGame.java Source code

Java tutorial

Introduction

Here is the source code for seventh.client.SeventhGame.java

Source

/*
 * The Seventh
 * see license.txt 
 */
package seventh.client;

import java.io.IOException;
import java.nio.IntBuffer;
import java.util.Date;
import java.util.Stack;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Mouse;

import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.controllers.Controller;
import com.badlogic.gdx.controllers.Controllers;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.TimeUtils;

import seventh.ClientMain;
import seventh.client.gfx.Art;
import seventh.client.gfx.Canvas;
import seventh.client.gfx.GdxCanvas;
import seventh.client.gfx.Terminal;
import seventh.client.gfx.Theme;
import seventh.client.gfx.effects.BlurEffectShader;
import seventh.client.gfx.effects.FireEffectShader;
import seventh.client.gfx.effects.LightEffectShader;
import seventh.client.gfx.effects.RippleEffectShader;
import seventh.client.inputs.Inputs;
import seventh.client.inputs.KeyMap;
import seventh.client.network.ClientConnection;
import seventh.client.screens.AnimationEditorScreen;
import seventh.client.screens.LoadingScreen;
import seventh.client.screens.MenuScreen;
import seventh.client.screens.Screen;
import seventh.client.screens.ShaderEditorScreen;
import seventh.client.sfx.Sounds;
import seventh.network.messages.PlayerNameChangeMessage;
import seventh.shared.Command;
import seventh.shared.CommonCommands;
import seventh.shared.Cons;
import seventh.shared.Console;
import seventh.shared.StateMachine;
import seventh.shared.TimeStep;
import seventh.ui.UserInterfaceManager;

/**
 * @author Tony
 *
 */
public class SeventhGame implements ApplicationListener {

    private static final String HEADER = "=============================================================================\n"
            + "                                                                             \n"
            + "                             === The Seventh ===                             \n"
            + "                                5d Studios (c)                               \n"
            + "                                                                             \n"
            + "                                                                             \n"
            + "=============================================================================\n"
            + "                                                                             \n";

    private static final String VERSION = "v0.1.3.0-BETA";
    public static final int DEFAULT_MINIMIZED_SCREEN_WIDTH = 1024;
    public static final int DEFAULT_MINIMIZED_SCREEN_HEIGHT = 768;

    private StateMachine<Screen> sm;

    private ClientSeventhConfig config;

    private Terminal terminal;
    private Console console;
    private Theme theme;

    private Canvas canvas;

    private InputMultiplexer inputs;
    private KeyMap keyMap;

    private final ClientConnection connection;

    private boolean isVSync;
    private Stack<Screen> screenStack;

    private UserInterfaceManager uiManager;
    private MenuScreen menuScreen;

    private TimeStep timeStep;
    private long gameClock;

    private double currentTime;
    private double accumulator;
    private static final double step = 1.0 / 30.0;
    private static final long DELTA_TIME = 1000 / 30;

    /**
     * @param config
     */
    public SeventhGame(ClientSeventhConfig config) throws Exception {
        this.console = Cons.getImpl();
        this.timeStep = new TimeStep();
        this.terminal = new Terminal(console, config);

        this.inputs = new InputMultiplexer();

        Cons.println(HEADER);
        Cons.println("*** Initializing " + VERSION + " ***");
        Cons.println("Start Stamp: " + new Date());

        this.config = config;
        this.keyMap = config.getKeyMap();

        this.connection = new ClientConnection(this, config, console);

        this.screenStack = new Stack<Screen>();
        this.sm = new StateMachine<Screen>();
        this.theme = new Theme();

        setupCommand(Cons.getImpl());

        // Can't set this up here because the 
        // Gdx context hasn't been created yet
        //        this.menuScreen = new MenuScreen(this);
    }

    private void setupCommand(Console console) {
        CommonCommands.addCommonCommands(console);

        Command exit = new Command("exit") {
            @Override
            public void execute(Console console, String... args) {
                console.println("Exiting the game...");
                shutdown();
            }
        };

        console.addCommand(exit);
        console.addCommand("quit", exit);

        console.addCommand(new Command("clear") {
            @Override
            public void execute(Console console, String... args) {
                terminal.clear();
            }
        });

        console.addCommand(new Command("name") {
            @Override
            public void execute(Console console, String... args) {
                String newName = this.mergeArgsDelim(" ", args);
                config.setPlayerName(newName);
                if (connection.isConnected()) {
                    PlayerNameChangeMessage msg = new PlayerNameChangeMessage();
                    msg.name = newName;
                    connection.getClientProtocol().sendPlayerNameChangedMessage(msg);
                }
            }
        });

        console.addCommand(new Command("connect") {
            @Override
            public void execute(Console console, String... args) {
                if (args.length < 1) {
                    console.println("<usage> connect [IP/DNS] \n   Ex. connect 68.2.44.100:9844");

                } else {
                    try {
                        String host = args[0];
                        String p[] = host.split(":");
                        host = p[0];
                        int port = Integer.parseInt(p[1]);

                        setScreen(new LoadingScreen(SeventhGame.this, host, port, true));
                    } catch (Exception e) {
                        console.println("*** Error attempting to connect: \n" + e);
                    }
                }
            }
        });

        console.addCommand(new Command("help") {
            @Override
            public void execute(Console console, String... args) {
                console.println("\n");
                console.println("The console is a means for executing commands.  The set of available commands ");
                console.println("differ given the current game context (i.e., in-game, main-menu, etc.).  To ");
                console.println(
                        "get a list of available commands type: 'cmdlist'.  The console supports TAB completion. ");
            }
        });

        console.addCommand(new Command("v_reload_shaders") {
            @Override
            public void execute(Console console, String... args) {
                BlurEffectShader.getInstance().reload();
                FireEffectShader.getInstance().reload();
                RippleEffectShader.getInstance().reload();
                LightEffectShader.getInstance().reload();
            }
        });

        console.addCommand(new Command("v_reload_gfx") {
            @Override
            public void execute(Console console, String... args) {
                Art.reload();
            }
        });

        //        console.addCommand(new Command("v_reload_animation") {            
        //            @Override
        //            public void execute(Console console, String... args) {
        //                try {
        //                    Art.debugAnimations(new Leola());
        //                } catch (Exception e) {
        //                    console.println("*** Error loading animations: " + e);
        //                }
        //            }
        //        });

        console.addCommand(new Command("animation_editor") {
            @Override
            public void execute(Console console, String... args) {
                pushScreen(new AnimationEditorScreen(SeventhGame.this));
            }
        });

        console.addCommand(new Command("shader_editor") {
            @Override
            public void execute(Console console, String... args) {
                pushScreen(new ShaderEditorScreen(SeventhGame.this));
            }
        });

        console.addCommand(new Command("mouse_sensitivity") {

            @Override
            public void execute(Console console, String... args) {
                seventh.client.gfx.Cursor cursor = uiManager.getCursor();
                if (args.length == 0) {
                    console.println(cursor.getMouseSensitivity());
                } else {
                    try {
                        float value = Float.parseFloat(args[0]);
                        cursor.setMouseSensitivity(value);
                    } catch (NumberFormatException e) {
                        console.println("Must be a number between 0 and 1");
                    }
                }

            }
        });
    }

    /**
     * Hide the Mouse cursor
     * 
     * @param visible
     */
    private void setHWCursorVisible(boolean visible) {
        if (Gdx.app.getType() != ApplicationType.Desktop && Gdx.app instanceof LwjglApplication) {
            return;
        }

        try {
            /* make sure the mouse doesn't move off the screen */
            Gdx.input.setCursorCatched(true);

            Cursor emptyCursor = null;
            if (Mouse.isCreated()) {
                int min = org.lwjgl.input.Cursor.getMinCursorSize();
                IntBuffer tmp = BufferUtils.createIntBuffer(min * min);
                emptyCursor = new org.lwjgl.input.Cursor(min, min, min / 2, min / 2, 1, tmp, null);
            } else {
                Cons.println("Could not create empty cursor before Mouse object is created");
            }

            if (/*Mouse.isInsideWindow() &&*/ emptyCursor != null) {
                Mouse.setNativeCursor(visible ? null : emptyCursor);
            }
        } catch (LWJGLException e) {
            Cons.println("*** Unable to hide cursor: " + e);
        }
    }

    /**
     * Shuts down the game
     */
    public void shutdown() {
        Gdx.app.exit();
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#create()
     */
    @Override
    public void create() {
        ClientMain.logSystemSpecs(console);
        ClientMain.logVideoSpecs(console);

        Art.load();
        Sounds.init(config);

        this.uiManager = new UserInterfaceManager();
        seventh.client.gfx.Cursor cursor = this.uiManager.getCursor();
        float sensitivity = config.getMouseSensitivity();
        if (sensitivity > 0) {
            cursor.setMouseSensitivity(sensitivity);
        }

        Gdx.input.setInputProcessor(this.inputs);
        //        Gdx.input.setCursorCatched(true);

        initControllers();
        videoReload();

        this.menuScreen = new MenuScreen(this);
        goToMenuScreen();
    }

    /**
     * @return the menuScreen
     */
    public MenuScreen getMenuScreen() {
        return menuScreen;
    }

    /**
     * Navigates to the {@link MenuScreen}
     */
    public void goToMenuScreen() {
        setScreen(menuScreen);
    }

    private void initControllers() {
        Cons.println("Detecting controllers...");
        for (Controller control : Controllers.getControllers()) {
            Cons.println("Found: " + control.getName());
        }
        Cons.println("Completed checking for controllers");
    }

    private void videoReload() {
        Gdx.input.setCursorPosition(getScreenWidth() / 2, getScreenHeight() / 2);
        setHWCursorVisible(false);

        this.inputs.addProcessor(new Inputs() {
            @Override
            public boolean keyUp(int key) {
                if (key == Keys.GRAVE) {
                    Gdx.input.setCursorCatched(!terminal.toggle());
                    return true;
                }
                return false;
            }
        });

        this.inputs.addProcessor(this.terminal.getInputs());

        setVSync(config.getVideo().isVsync());

        this.canvas = new GdxCanvas();
        try {
            this.canvas.loadFont("./assets/gfx/fonts/Courier New.ttf", "Courier New");
            this.canvas.loadFont("./assets/gfx/fonts/Consola.ttf", "Consola");
            this.canvas.loadFont("./assets/gfx/fonts/Army.ttf", "Army");
            this.canvas.loadFont("./assets/gfx/fonts/Napalm Vertigo.ttf", "Napalm Vertigo");
            //            this.canvas.loadFont("./assets/gfx/fonts/Bebas.ttf", "Bebas");
            this.canvas.loadFont("./assets/gfx/fonts/future.ttf", "Futurist Fixed-width");

            this.canvas.setDefaultFont("Courier New", 14);
        } catch (IOException e) {
            Cons.println("*** Unable to load font: " + e);
        }

        setHWCursorVisible(false);
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#dispose()
     */
    @Override
    public void dispose() {
        Sounds.destroy();
        Art.destroy();
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#pause()
     */
    @Override
    public void pause() {
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#render()
     */
    @Override
    public void render() {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        double newTime = TimeUtils.millis() / 1000.0;
        double frameTime = Math.min(newTime - currentTime, 0.25);

        currentTime = newTime;
        accumulator += frameTime;

        while (accumulator >= step) {
            timeStep.setDeltaTime(DELTA_TIME);
            timeStep.setGameClock(gameClock);

            updateScreen(timeStep);

            accumulator -= step;
            gameClock += DELTA_TIME;
        }

        float alpha = (float) (accumulator / step);
        renderScreen(canvas, alpha);
    }

    /**
     * Pushes a {@link Screen} onto the stack.
     * 
     * @param newScreen
     */
    public void pushScreen(Screen newScreen) {
        this.screenStack.add(newScreen);
        preserveStackSetScreen(newScreen);
    }

    /**
     * Pops a {@link Screen} off the stack.
     */
    public void popScreen() {
        if (!this.screenStack.isEmpty()) {
            this.screenStack.pop();
            if (!this.screenStack.isEmpty()) {
                preserveStackSetScreen(this.screenStack.peek());
            }
        }
    }

    /**
     * Pops and pushes the the current {@link Screen}, effectively
     * reloading it
     * @return true if actually reloaded a screen, false if no-op
     */
    public boolean reloadCurrentScreen() {
        if (!this.screenStack.isEmpty()) {
            Screen screen = this.screenStack.pop();
            preserveStackSetScreen(screen);
            return true;
        }

        return false;
    }

    /**
     * Preserves the stack state
     * @param newScreen
     */
    private void preserveStackSetScreen(Screen newScreen) {
        Screen previousScreen = this.sm.getCurrentState();
        this.sm.changeState(newScreen);
        updateInputs(previousScreen);
    }

    /**
     * @param newScreen
     */
    public void setScreen(Screen newScreen) {
        this.screenStack.clear();
        pushScreen(newScreen);
    }

    /**
     * @return the uiManager
     */
    public UserInterfaceManager getUiManager() {
        return uiManager;
    }

    /**
     * @return the network
     */
    public ClientConnection getClientConnection() {
        return connection;
    }

    /**
     * @return the keyMap
     */
    public KeyMap getKeyMap() {
        return keyMap;
    }

    /**
     * @return the theme
     */
    public Theme getTheme() {
        return theme;
    }

    /**
     * @return the terminal
     */
    public Terminal getTerminal() {
        return terminal;
    }

    /**
     * @return the config
     */
    public ClientSeventhConfig getConfig() {
        return config;
    }

    public int getFps() {
        return Gdx.graphics.getFramesPerSecond();
    }

    /**
     * @return the gameClock
     */
    public long getGameClock() {
        return gameClock;
    }

    /**
     * @return the screenHeight
     */
    public int getScreenHeight() {
        return Gdx.graphics.getHeight();
    }

    /**
     * @return the screenWidth
     */
    public int getScreenWidth() {
        return Gdx.graphics.getWidth();
    }

    /**
     * @return true if full screen
     */
    public boolean isFullscreen() {
        return Gdx.graphics.isFullscreen();
    }

    /**
     * @return if VSync is enabled
     */
    public boolean isVSync() {
        return this.isVSync;
    }

    /**
     * Enable/disable vsync
     * @param vsync
     */
    public void setVSync(boolean vsync) {
        this.isVSync = vsync;
        Gdx.graphics.setVSync(vsync);
    }

    /**
     * @return the version
     */
    public static String getVersion() {
        return VERSION;
    }

    private void updateScreen(TimeStep timeStep) {
        this.console.update(timeStep);
        this.sm.update(timeStep);

        if (this.terminal.isActive()) {
            this.terminal.update(timeStep);
        }
    }

    private void renderScreen(Canvas canvas, float alpha) {
        Screen screen = this.sm.getCurrentState();
        canvas.preRender();
        if (screen != null) {
            screen.render(canvas, alpha);
        }

        if (this.terminal.isActive()) {
            this.terminal.render(canvas, alpha);
        }
        canvas.postRender();
    }

    private void updateInputs(Screen previousScreen) {

        if (previousScreen != null) {
            this.inputs.removeProcessor(previousScreen.getInputs());
        }

        Screen screen = this.sm.getCurrentState();
        if (screen != null) {
            Inputs inputs = screen.getInputs();
            //Gdx.input.setInputProcessor(inputs);
            this.inputs.addProcessor(inputs);
        }
    }

    /**
     * Adds an input listener
     * @param inputs
     */
    public void addInput(Inputs inputs) {
        this.inputs.addProcessor(inputs);
    }

    /**
     * Adds an input listener to the front
     * @param inputs
     */
    public void addInputToFront(Inputs inputs) {
        this.inputs.addProcessor(0, inputs);
    }

    /**
     * Removes an input listener
     * @param inputs
     */
    public void removeInput(Inputs inputs) {
        this.inputs.removeProcessor(inputs);
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#resize(int, int)
     */
    @Override
    public void resize(int width, int height) {
        //        setHWCursorVisible(false);
        //        videoReload();
    }

    /**
     * Restarts the video 
     */
    public void restartVideo() {
        setHWCursorVisible(false);
        videoReload();
    }

    /* (non-Javadoc)
     * @see com.badlogic.gdx.ApplicationListener#resume()
     */
    @Override
    public void resume() {
        setHWCursorVisible(false);
        /* the mouse gets captured, so when we 
         * gain focus back, center the mouse so the 
         * user can find it
         */
        getUiManager().getCursor().centerMouse();
    }

    /**
     * @return
     */
    public Console getConsole() {
        return Cons.getImpl();
    }

}