com.dbi.games.fortress.engine.MainEngine.java Source code

Java tutorial

Introduction

Here is the source code for com.dbi.games.fortress.engine.MainEngine.java

Source

/*
 Copyright (C) 2014  Nathan Nelson
    
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
 Author E-mail: falken224@gmail.com
 */
package com.dbi.games.fortress.engine;

import com.dbi.games.fortress.engine.entity.EntityType;
import com.dbi.games.fortress.engine.entity.BasicMover;
import com.dbi.games.fortress.engine.entity.Entity;
import com.dbi.games.fortress.engine.entity.Mover;
import com.dbi.games.fortress.engine.entity.Path;
import com.dbi.games.fortress.engine.util.AdditiveDistanceScore;
import com.dbi.games.fortress.engine.util.DiagonalDistanceScore;
import com.dbi.games.fortress.engine.util.EuclideanDistance;
import com.dbi.games.fortress.engine.util.PathRemainingScore;
import com.dbi.games.fortress.engine.util.PathScore;
import com.dbi.games.fortress.engine.util.PathUtils;
import com.dbi.games.fortress.engine.util.StepBasedPathScore;
import com.dbi.games.fortress.map.MapInfo;
import com.dbi.games.fortress.map.MapManager;
import com.dbi.games.fortress.ui.ControlWindow;
import com.dbi.games.fortress.ui.LogWindow;
import com.dbi.games.fortress.ui.MainAppWindow;
import java.awt.Point;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.opengl.GL11;

/**
 *
 * @author nnels2
 */
public class MainEngine {
    private static MainEngine me;

    private LogWindow logWindow;
    private MainAppWindow mainWindow;
    private ControlWindow controlWindow;
    private GraphicsEngine graphicsEngine;
    private EntityEngine entityEngine;
    private MapManager mapManager;
    private MapInfo currentMap;
    private KeyBinder keyBinder;

    private PathRemainingScore distanceScore;
    private PathScore pathScore;

    private Random rnd;

    private int ticksPerSecondTarget = 10;
    private long targetTickLengthNanos = 100000000; //in nanos
    private long currentTickLengthNanos = 0;
    private boolean isReady = false;
    private long nanosSinceStatsUpdate = 0;
    private static final long NANOS_PER_STAT_UPDATE = 250000000;
    private int ticksSinceStatsUpdate = 0;
    private int framesSinceStatsUpdate = 0;
    private boolean running = true;

    private MainEngine() {
        logWindow = new LogWindow();
        rnd = new Random();
    }

    public static MainEngine get() {
        if (me == null) {
            me = new MainEngine();
            me.init();
        }
        return me;
    }

    public void init() {
        try {
            graphicsEngine = new GraphicsEngine();
            entityEngine = new EntityEngine();

            mainWindow = new MainAppWindow();
            controlWindow = new ControlWindow();

            keyBinder = new KeyBinder();

            keyBinder.setupDefaultKeyBindings();
            keyBinder.addBoundWindow(mainWindow);
            keyBinder.addBoundWindow(controlWindow);
            keyBinder.addBoundWindow(logWindow);

            mainWindow.setVisible(true);
            controlWindow.setLocationRelativeTo(mainWindow);
            controlWindow.setLocation(800, 0);
            controlWindow.setVisible(true);

            graphicsEngine.setViewportBounds(mainWindow.getViewportBounds());

            mapManager = new MapManager();
            currentMap = mapManager.buildDefaultMap();

            isReady = true;
            Logger.getLogger(getClass().getName()).info("Main Engine Started!");

            //Create test stuff
            BasicMover myDude = new BasicMover(EntityType.Dwarf, "MyDude");
            myDude.setMapLocation(new Point(5, 5));
            entityEngine.add(myDude);

            EuclideanDistance scorer = new EuclideanDistance();
            DiagonalDistanceScore diagonalDistance = new DiagonalDistanceScore();
            AdditiveDistanceScore additiveDistanceScore = new AdditiveDistanceScore();
            StepBasedPathScore diagonalHeavy = new StepBasedPathScore(1f, 1.4f);
            StepBasedPathScore diagonalEqual = new StepBasedPathScore(1f, 1f);
            pathScore = diagonalHeavy;
            distanceScore = diagonalDistance;

        } catch (Exception ex) {
            Logger.getGlobal().log(Level.SEVERE, "There was a SERIOUS error trying to start the app!", ex);
            logWindow.setVisible(true);
            controlWindow.setVisible(true);
        }
    }

    public void shutdown() {
        running = false;
        System.exit(0);
    }

    public boolean isRunning() {
        return running;
    }

    public LogWindow logWindow() {
        return logWindow;
    }

    public MainAppWindow mainWindow() {
        return mainWindow;
    }

    public ControlWindow controlWindow() {
        return controlWindow;
    }

    public KeyBinder keyBinder() {
        return keyBinder;
    }

    public int getTicksPerSecondTarget() {
        return ticksPerSecondTarget;
    }

    public void setTicksPerSecondTarget(int ticksPerSecondTarget) {
        if (ticksPerSecondTarget < 1)
            ticksPerSecondTarget = 1;
        this.ticksPerSecondTarget = ticksPerSecondTarget;
        this.targetTickLengthNanos = 1000000000 / ticksPerSecondTarget;
    }

    /**
     * Should ONLY be invoked from the GL thread!
     */
    public void renderScene(long deltaNanos) {
        if (!isReady)
            return;
        currentTickLengthNanos += deltaNanos;
        nanosSinceStatsUpdate += deltaNanos;

        framesSinceStatsUpdate++;

        if (currentTickLengthNanos >= targetTickLengthNanos) {
            tick();
        }

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();

        graphicsEngine.renderMap(currentMap);
        for (Entity ent : entityEngine.findAll()) {
            graphicsEngine.renderEntity(ent);
        }

        if (nanosSinceStatsUpdate > NANOS_PER_STAT_UPDATE) {
            controlWindow.setFPS(framesSinceStatsUpdate * 4);
            controlWindow.setTPS(ticksSinceStatsUpdate * 4, ticksPerSecondTarget);
            framesSinceStatsUpdate = 0;
            ticksSinceStatsUpdate = 0;
            nanosSinceStatsUpdate = 0;
        }
    }

    public void tick() {
        currentTickLengthNanos = 0;
        ticksSinceStatsUpdate++;

        for (Mover myMover : entityEngine.findAllType(Mover.class)) {
            if (!myMover.hasPath()) {
                Point newLocation = new Point(rnd.nextInt(18) + 1, rnd.nextInt(18) + 1);
                ;
                while (!currentMap.terrainAt(newLocation).isPassable()) {
                    newLocation = new Point(rnd.nextInt(18) + 1, rnd.nextInt(18) + 1);
                }
                Path newPath = PathUtils.findBestPath(myMover.getMapLocation(), newLocation, currentMap, pathScore,
                        distanceScore);
                myMover.paths().add(newPath);
            }
            myMover.step();
        }
    }

    public GraphicsEngine graphicsEngine() {
        //checkGLThread();
        return graphicsEngine;
    }

    public EntityEngine entityEngine() {
        return entityEngine;
    }
}