Java tutorial
/* 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; } }