pai
							
								
									af8535620b
								
							
						
					
					
						commit
						dbc32c4d0a
					
				| @ -1,133 +1,133 @@ | |||||||
| package junk; | //package junk;
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| import java.io.File; | //import java.io.File;
 | ||||||
| import java.util.ArrayList; | //import java.util.ArrayList;
 | ||||||
| import java.util.List; | //import java.util.List;
 | ||||||
| import java.util.logging.Level; | //import java.util.logging.Level;
 | ||||||
| 
 | //
 | ||||||
| import mightypork.gamecore.core.AppBackend; | //import mightypork.gamecore.core.AppBackend;
 | ||||||
| import mightypork.gamecore.resources.ResourceInitializer; | //import mightypork.gamecore.resources.ResourceInitializer;
 | ||||||
| import mightypork.gamecore.resources.loading.AsyncResourceLoader; | //import mightypork.gamecore.resources.loading.AsyncResourceLoader;
 | ||||||
| import mightypork.gamecore.resources.loading.ResourceLoader; | //import mightypork.gamecore.resources.loading.ResourceLoader;
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| /** | ///**
 | ||||||
|  * Init options holder class
 | // * Init options holder class
 | ||||||
|  */ | // */
 | ||||||
| public class AppInitOptions { | //public class AppInitOptions {
 | ||||||
| 
 | //
 | ||||||
| 	String logDir = "log"; | //	String logDir = "log";
 | ||||||
| 	String logFilePrefix = "runtime"; | //	String logFilePrefix = "runtime";
 | ||||||
| 
 | //
 | ||||||
| 	String screenshotDir = "screenshots"; | //	String screenshotDir = "screenshots";
 | ||||||
| 
 | //
 | ||||||
| 	boolean busLogging = false; | //	boolean busLogging = false;
 | ||||||
| 
 | //
 | ||||||
| 	String configFile = "settings.cfg"; | //	String configFile = "settings.cfg";
 | ||||||
| 	String configComment = "Main config file"; | //	String configComment = "Main config file";
 | ||||||
| 
 | //
 | ||||||
| 	final List<ResourceInitializer> resourceLists = new ArrayList<>(); | //	final List<ResourceInitializer> resourceLists = new ArrayList<>();
 | ||||||
| 	final List<KeySetup> keyLists = new ArrayList<>(); | //	final List<KeySetup> keyLists = new ArrayList<>();
 | ||||||
| 	final List<ConfigSetup> configLists = new ArrayList<>(); | //	final List<ConfigSetup> configLists = new ArrayList<>();
 | ||||||
| 
 | //
 | ||||||
| 	ResourceLoader resourceLoader = new AsyncResourceLoader(); | //	ResourceLoader resourceLoader = new AsyncResourceLoader();
 | ||||||
| 	Level logLevel = Level.ALL; | //	Level logLevel = Level.ALL;
 | ||||||
| 	public boolean sigleInstance = true; | //	public boolean sigleInstance = true;
 | ||||||
| 	Level logSoutLevel = Level.ALL; | //	Level logSoutLevel = Level.ALL;
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setConfigFile(String filename, String comment) | //	public void setConfigFile(String filename, String comment)
 | ||||||
| 	{ | //	{
 | ||||||
| 		configFile = filename; | //		configFile = filename;
 | ||||||
| 		configComment = comment; | //		configComment = comment;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void addConfig(ConfigSetup cfg) | //	public void addConfig(ConfigSetup cfg)
 | ||||||
| 	{ | //	{
 | ||||||
| 		configLists.add(cfg); | //		configLists.add(cfg);
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void addKeys(KeySetup keys) | //	public void addKeys(KeySetup keys)
 | ||||||
| 	{ | //	{
 | ||||||
| 		keyLists.add(keys); | //		keyLists.add(keys);
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void addResources(ResourceInitializer res) | //	public void addResources(ResourceInitializer res)
 | ||||||
| 	{ | //	{
 | ||||||
| 		resourceLists.add(res); | //		resourceLists.add(res);
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setBackend(AppBackend backend) | //	public void setBackend(AppBackend backend)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.backend = backend; | //		this.backend = backend;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	/** | //	/**
 | ||||||
| 	 * Set whether to run in single instance mode, or allow multiple instances.<br> | //	 * Set whether to run in single instance mode, or allow multiple instances.<br>
 | ||||||
| 	 * Multiple instances running can cause various collisions (eg. when writing | //	 * Multiple instances running can cause various collisions (eg. when writing
 | ||||||
| 	 * config file or logging). | //	 * config file or logging).
 | ||||||
| 	 * | //	 *
 | ||||||
| 	 * @param sigleInstance true to allow only one instance | //	 * @param sigleInstance true to allow only one instance
 | ||||||
| 	 */ | //	 */
 | ||||||
| 	public void setSigleInstance(boolean sigleInstance) | //	public void setSigleInstance(boolean sigleInstance)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.sigleInstance = sigleInstance; | //		this.sigleInstance = sigleInstance;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	/** | //	/**
 | ||||||
| 	 * Set working directory path. If not exists, it will be created. | //	 * Set working directory path. If not exists, it will be created.
 | ||||||
| 	 * | //	 *
 | ||||||
| 	 * @param workdir work dir path | //	 * @param workdir work dir path
 | ||||||
| 	 */ | //	 */
 | ||||||
| 	public void setWorkdir(File workdir) | //	public void setWorkdir(File workdir)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.workdir = workdir; | //		this.workdir = workdir;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setBusLogging(boolean yes) | //	public void setBusLogging(boolean yes)
 | ||||||
| 	{ | //	{
 | ||||||
| 		busLogging = yes; | //		busLogging = yes;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setLogOptions(String logDir, String filePrefix, int archivedCount, Level logLevel) | //	public void setLogOptions(String logDir, String filePrefix, int archivedCount, Level logLevel)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.logDir = logDir; | //		this.logDir = logDir;
 | ||||||
| 		this.logFilePrefix = filePrefix; | //		this.logFilePrefix = filePrefix;
 | ||||||
| 		this.logArchiveCount = archivedCount; | //		this.logArchiveCount = archivedCount;
 | ||||||
| 		this.logLevel = logLevel; | //		this.logLevel = logLevel;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setResourceLoader(ResourceLoader resLoader) | //	public void setResourceLoader(ResourceLoader resLoader)
 | ||||||
| 	{ | //	{
 | ||||||
| 		resourceLoader = resLoader; | //		resourceLoader = resLoader;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setScreenshotDir(String path) | //	public void setScreenshotDir(String path)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.screenshotDir = path; | //		this.screenshotDir = path;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setLockFile(String lockFile) | //	public void setLockFile(String lockFile)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.lockFile = lockFile; | //		this.lockFile = lockFile;
 | ||||||
| 	} | //	}
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| 	public void setLogLevel(Level logLevel, Level soutLevel) | //	public void setLogLevel(Level logLevel, Level soutLevel)
 | ||||||
| 	{ | //	{
 | ||||||
| 		this.logLevel = logLevel; | //		this.logLevel = logLevel;
 | ||||||
| 		this.logSoutLevel = soutLevel; | //		this.logSoutLevel = soutLevel;
 | ||||||
| 	} | //	}
 | ||||||
| } | //}
 | ||||||
|  | |||||||
| @ -1,184 +1,185 @@ | |||||||
| package junk; | //package junk;
 | ||||||
| 
 | //
 | ||||||
| 
 | //
 | ||||||
| import java.lang.Thread.UncaughtExceptionHandler; | //import java.lang.Thread.UncaughtExceptionHandler;
 | ||||||
| 
 | //
 | ||||||
| import mightypork.gamecore.core.App; | //import mightypork.gamecore.core.App;
 | ||||||
| import mightypork.gamecore.core.AppBackend; | //import mightypork.gamecore.core.AppBackend;
 | ||||||
| import mightypork.gamecore.core.MainLoop; | //import mightypork.gamecore.core.MainLoop;
 | ||||||
| import mightypork.gamecore.core.config.Config; | //import mightypork.gamecore.core.DeltaMainLoop;
 | ||||||
| import mightypork.gamecore.gui.screens.ScreenRegistry; | //import mightypork.gamecore.core.config.Config;
 | ||||||
| import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay; | //import mightypork.gamecore.gui.screens.ScreenRegistry;
 | ||||||
| import mightypork.gamecore.resources.Res; | //import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay;
 | ||||||
| import mightypork.gamecore.resources.ResourceInitializer; | //import mightypork.gamecore.resources.Res;
 | ||||||
| import mightypork.utils.files.WorkDir; | //import mightypork.gamecore.resources.ResourceInitializer;
 | ||||||
| import mightypork.utils.logging.Log; | //import mightypork.utils.files.WorkDir;
 | ||||||
| 
 | //import mightypork.utils.logging.Log;
 | ||||||
| 
 | //
 | ||||||
| /** | //
 | ||||||
|  * Basic screen-based game with subsystems.<br> | ///**
 | ||||||
|  * This class takes care of the initialization sequence. | // * Basic screen-based game with subsystems.<br>
 | ||||||
|  * | // * This class takes care of the initialization sequence.
 | ||||||
|  * @author Ondřej Hruška (MightyPork) | // *
 | ||||||
|  */ | // * @author Ondřej Hruška (MightyPork)
 | ||||||
| public abstract class BaseApp extends App implements UncaughtExceptionHandler { | // */
 | ||||||
| 
 | //public abstract class BaseApp extends App implements UncaughtExceptionHandler {
 | ||||||
| 	// modules
 | //
 | ||||||
| 	private MainLoop gameLoop; | //	// modules
 | ||||||
| 	private ScreenRegistry screenRegistry; | //	private MainLoop gameLoop;
 | ||||||
| 
 | //	private ScreenRegistry screenRegistry;
 | ||||||
| 	private boolean started = false; | //
 | ||||||
| 	private boolean lockObtained = false; | //	private boolean started = false;
 | ||||||
| 
 | //	private boolean lockObtained = false;
 | ||||||
| 	// init opt holder
 | //
 | ||||||
| 	private final AppInitOptions opt = new AppInitOptions(); | //	// init opt holder
 | ||||||
| 
 | //	private final AppInitOptions opt = new AppInitOptions();
 | ||||||
| 
 | //
 | ||||||
| 	/** | //
 | ||||||
| 	 * Get init options | //	/**
 | ||||||
| 	 * | //	 * Get init options
 | ||||||
| 	 * @return opt holder | //	 *
 | ||||||
| 	 */ | //	 * @return opt holder
 | ||||||
| 	public AppInitOptions getInitOptions() | //	 */
 | ||||||
| 	{ | //	public AppInitOptions getInitOptions()
 | ||||||
| 		if (started) { | //	{
 | ||||||
| 			throw new IllegalStateException("Cannot alter init options after starting the App."); | //		if (started) {
 | ||||||
| 		} | //			throw new IllegalStateException("Cannot alter init options after starting the App.");
 | ||||||
| 
 | //		}
 | ||||||
| 		return opt; | //
 | ||||||
| 	} | //		return opt;
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	public BaseApp(AppBackend backend) | //
 | ||||||
| 	{ | //	public BaseApp(AppBackend backend)
 | ||||||
| 		super(backend); | //	{
 | ||||||
| 	} | //		super(backend);
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	/** | //
 | ||||||
| 	 * Start the application | //	/**
 | ||||||
| 	 */ | //	 * Start the application
 | ||||||
| 	@Override | //	 */
 | ||||||
| 	public final void start() | //	@Override
 | ||||||
| 	{ | //	public final void start()
 | ||||||
| 		initialize(); | //	{
 | ||||||
| 
 | //		initialize();
 | ||||||
| 		Log.i("Starting main loop..."); | //
 | ||||||
| 
 | //		Log.i("Starting main loop...");
 | ||||||
| 		// open first screen	!!!
 | //
 | ||||||
| 		started = true; | //		// open first screen	!!!
 | ||||||
| 		gameLoop.start(); | //		started = true;
 | ||||||
| 	} | //		gameLoop.start();
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	/** | //
 | ||||||
| 	 * Init the app | //	/**
 | ||||||
| 	 */ | //	 * Init the app
 | ||||||
| 	protected void initialize() | //	 */
 | ||||||
| 	{ | //	protected void initialize()
 | ||||||
| 		WorkDir.setBaseDir(opt.workdir); | //	{
 | ||||||
| 
 | //		WorkDir.setBaseDir(opt.workdir);
 | ||||||
| 		if (opt.sigleInstance) initLock(); | //
 | ||||||
| 		lockObtained = true; | //		if (opt.sigleInstance) initLock();
 | ||||||
| 
 | //		lockObtained = true;
 | ||||||
| 		for (final RouteSetup rs : opt.routeLists) { | //
 | ||||||
| 			WorkDir.registerRoutes(rs); | //		for (final RouteSetup rs : opt.routeLists) {
 | ||||||
| 		} | //			WorkDir.registerRoutes(rs);
 | ||||||
| 		WorkDir.addPath("_screenshot_dir", opt.screenshotDir); | //		}
 | ||||||
| 
 | //		WorkDir.addPath("_screenshot_dir", opt.screenshotDir);
 | ||||||
| 		// apply configurations
 | //
 | ||||||
| 		Config.init(WorkDir.getFile(opt.configFile), opt.configComment); | //		// apply configurations
 | ||||||
| 
 | //		Config.init(WorkDir.getFile(opt.configFile), opt.configComment);
 | ||||||
| 		// add keys to config
 | //
 | ||||||
| 		for (final KeySetup l : opt.keyLists) { | //		// add keys to config
 | ||||||
| 			Config.registerKeys(l); | //		for (final KeySetup l : opt.keyLists) {
 | ||||||
| 		} | //			Config.registerKeys(l);
 | ||||||
| 
 | //		}
 | ||||||
| 		// add options to config
 | //
 | ||||||
| 		for (final ConfigSetup c : opt.configLists) { | //		// add options to config
 | ||||||
| 			Config.registerOptions(c); | //		for (final ConfigSetup c : opt.configLists) {
 | ||||||
| 		} | //			Config.registerOptions(c);
 | ||||||
| 		Config.load(); | //		}
 | ||||||
| 
 | //		Config.load();
 | ||||||
| 		/* | //
 | ||||||
| 		 * Display | //		/*
 | ||||||
| 		 */ | //		 * Display
 | ||||||
| 		Log.f2("Initializing Display System..."); | //		 */
 | ||||||
| 		initDisplay(gfx()); | //		Log.f2("Initializing Display System...");
 | ||||||
| 
 | //		initDisplay(gfx());
 | ||||||
| 		/* | //
 | ||||||
| 		 * Audio | //		/*
 | ||||||
| 		 */ | //		 * Audio
 | ||||||
| 		Log.f2("Initializing Sound System..."); | //		 */
 | ||||||
| 		soundSystem = new SoundSystem(this); | //		Log.f2("Initializing Sound System...");
 | ||||||
| 		initSoundSystem(soundSystem); | //		soundSystem = new SoundSystem(this);
 | ||||||
| 
 | //		initSoundSystem(soundSystem);
 | ||||||
| 		/* | //
 | ||||||
| 		 * Input | //		/*
 | ||||||
| 		 */ | //		 * Input
 | ||||||
| 		Log.f2("Initializing Input System..."); | //		 */
 | ||||||
| 		inputSystem = new LwjglInputModule(this); | //		Log.f2("Initializing Input System...");
 | ||||||
| 		initInputSystem(inputSystem); | //		inputSystem = new LwjglInputModule(this);
 | ||||||
| 
 | //		initInputSystem(inputSystem);
 | ||||||
| 		/* | //
 | ||||||
| 		 * Prepare main loop | //		/*
 | ||||||
| 		 */ | //		 * Prepare main loop
 | ||||||
| 		Log.f1("Creating Screen Registry and Game Loop..."); | //		 */
 | ||||||
| 		screenRegistry = new ScreenRegistry(this); | //		Log.f1("Creating Screen Registry and Game Loop...");
 | ||||||
| 		gameLoop = createMainLoop(); | //		screenRegistry = new ScreenRegistry(this);
 | ||||||
| 		gameLoop.setRootRenderable(screenRegistry); | //		gameLoop = createMainLoop();
 | ||||||
| 
 | //		gameLoop.setRootRenderable(screenRegistry);
 | ||||||
| 		/* | //
 | ||||||
| 		 * Load resources | //		/*
 | ||||||
| 		 * | //		 * Load resources
 | ||||||
| 		 * Resources should be registered to registries, and AsyncResourceLoader will load them. | //		 *
 | ||||||
| 		 */ | //		 * Resources should be registered to registries, and AsyncResourceLoader will load them.
 | ||||||
| 		Log.f1("Loading resources..."); | //		 */
 | ||||||
| 		if (opt.resourceLoader != null) { | //		Log.f1("Loading resources...");
 | ||||||
| 			opt.resourceLoader.setBaseDir(this); | //		if (opt.resourceLoader != null) {
 | ||||||
| 		} | //			opt.resourceLoader.setBaseDir(this);
 | ||||||
| 
 | //		}
 | ||||||
| 		Res.setBaseDir(this); | //
 | ||||||
| 
 | //		Res.setBaseDir(this);
 | ||||||
| 		for (final ResourceInitializer rl : opt.resourceLists) { | //
 | ||||||
| 			Res.load(rl); | //		for (final ResourceInitializer rl : opt.resourceLists) {
 | ||||||
| 		} | //			Res.load(rl);
 | ||||||
| 
 | //		}
 | ||||||
| 		/* | //
 | ||||||
| 		 * Screen registry | //		/*
 | ||||||
| 		 * | //		 * Screen registry
 | ||||||
| 		 * Must be after resources, because screens can request them during instantiation. | //		 *
 | ||||||
| 		 */ | //		 * Must be after resources, because screens can request them during instantiation.
 | ||||||
| 		Log.f2("Registering screens..."); | //		 */
 | ||||||
| 		initScreens(screenRegistry); | //		Log.f2("Registering screens...");
 | ||||||
| 	} | //		initScreens(screenRegistry);
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	/** | //
 | ||||||
| 	 * Register game screens to the registry. | //	/**
 | ||||||
| 	 * | //	 * Register game screens to the registry.
 | ||||||
| 	 * @param screens | //	 *
 | ||||||
| 	 */ | //	 * @param screens
 | ||||||
| 	protected void initScreens(ScreenRegistry screens) | //	 */
 | ||||||
| 	{ | //	protected void initScreens(ScreenRegistry screens)
 | ||||||
| 		screens.addOverlay(new CrossfadeOverlay(this)); | //	{
 | ||||||
| 	} | //		screens.addOverlay(new CrossfadeOverlay(this));
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	/** | //
 | ||||||
| 	 * Create game loop instance | //	/**
 | ||||||
| 	 * | //	 * Create game loop instance
 | ||||||
| 	 * @return the game loop. | //	 *
 | ||||||
| 	 */ | //	 * @return the game loop.
 | ||||||
| 	protected MainLoop createMainLoop() | //	 */
 | ||||||
| 	{ | //	protected MainLoop createMainLoop()
 | ||||||
| 		return new MainLoop(this); | //	{
 | ||||||
| 	} | //		return new DeltaMainLoop(this);
 | ||||||
| 
 | //	}
 | ||||||
| 
 | //
 | ||||||
| 	protected void beforeShutdown() | //
 | ||||||
| 	{ | //	protected void beforeShutdown()
 | ||||||
| 		// ???
 | //	{
 | ||||||
| 		if (lockObtained) Config.save(); | //		// ???
 | ||||||
| 	} | //		if (lockObtained) Config.save();
 | ||||||
| } | //	}
 | ||||||
|  | //}
 | ||||||
|  | |||||||
| @ -0,0 +1,128 @@ | |||||||
|  | package mightypork.gamecore.core; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import java.util.Deque; | ||||||
|  | import java.util.concurrent.ConcurrentLinkedDeque; | ||||||
|  | 
 | ||||||
|  | import mightypork.gamecore.graphics.Renderable; | ||||||
|  | import mightypork.utils.annotations.Stub; | ||||||
|  | import mightypork.utils.eventbus.clients.BusNode; | ||||||
|  | import mightypork.utils.eventbus.events.UpdateEvent; | ||||||
|  | import mightypork.utils.logging.Log; | ||||||
|  | import mightypork.utils.math.timing.Profiler; | ||||||
|  | import mightypork.utils.math.timing.TimerDelta; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Delta-timed game loop with task queue etc. | ||||||
|  |  * | ||||||
|  |  * @author Ondřej Hruška (MightyPork) | ||||||
|  |  */ | ||||||
|  | public class DeltaMainLoop extends BusNode implements MainLoop { | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Max time spent on main loop tasks per cycle (s) | ||||||
|  | 	 */ | ||||||
|  | 	protected double MAX_TIME_TASKS = 1 / 30D; | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Max delta time (s) per frame.<br> | ||||||
|  | 	 * If delta is larger than this, it's clamped to it. | ||||||
|  | 	 */ | ||||||
|  | 	protected double MAX_DELTA = 1 / 20D; | ||||||
|  | 	 | ||||||
|  | 	private final Deque<Runnable> tasks = new ConcurrentLinkedDeque<>(); | ||||||
|  | 	private TimerDelta timer; | ||||||
|  | 	private Renderable rootRenderable; | ||||||
|  | 	private volatile boolean running = true; | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public void setRootRenderable(Renderable rootRenderable) | ||||||
|  | 	{ | ||||||
|  | 		this.rootRenderable = rootRenderable; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public void start() | ||||||
|  | 	{ | ||||||
|  | 		timer = new TimerDelta(); | ||||||
|  | 		 | ||||||
|  | 		while (running) { | ||||||
|  | 			App.gfx().beginFrame(); | ||||||
|  | 			 | ||||||
|  | 			double delta = timer.getDelta(); | ||||||
|  | 			if (delta > MAX_DELTA) { | ||||||
|  | 				Log.f3("(timing) Clamping delta: was " + delta + " s, MAX_DELTA = " + MAX_DELTA + " s"); | ||||||
|  | 				delta = MAX_DELTA; | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			// dispatch update event
 | ||||||
|  | 			App.bus().sendDirect(new UpdateEvent(delta)); | ||||||
|  | 			 | ||||||
|  | 			// run main loop tasks
 | ||||||
|  | 			Runnable r; | ||||||
|  | 			final long t = Profiler.begin(); | ||||||
|  | 			 | ||||||
|  | 			while ((r = tasks.poll()) != null) { | ||||||
|  | 				Log.f3(" * Main loop task."); | ||||||
|  | 				r.run(); | ||||||
|  | 				 | ||||||
|  | 				if (Profiler.end(t) > MAX_TIME_TASKS) { | ||||||
|  | 					Log.f3("! Time's up, postponing task to next cycle."); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			beforeRender(); | ||||||
|  | 			 | ||||||
|  | 			if (rootRenderable != null) { | ||||||
|  | 				rootRenderable.render(); | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			afterRender(); | ||||||
|  | 			 | ||||||
|  | 			App.gfx().endFrame(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Called before render | ||||||
|  | 	 */ | ||||||
|  | 	@Stub | ||||||
|  | 	protected void beforeRender() | ||||||
|  | 	{ | ||||||
|  | 		//
 | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Called after render | ||||||
|  | 	 */ | ||||||
|  | 	@Stub | ||||||
|  | 	protected void afterRender() | ||||||
|  | 	{ | ||||||
|  | 		//
 | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public void destroy() | ||||||
|  | 	{ | ||||||
|  | 		running = false; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public synchronized void queueTask(Runnable task, boolean skipQueue) | ||||||
|  | 	{ | ||||||
|  | 		if (skipQueue) { | ||||||
|  | 			tasks.addFirst(task); | ||||||
|  | 		} else { | ||||||
|  | 			tasks.addLast(task); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
| @ -1,143 +1,45 @@ | |||||||
| package mightypork.gamecore.core; | package mightypork.gamecore.core; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import java.util.Deque; |  | ||||||
| import java.util.concurrent.ConcurrentLinkedDeque; |  | ||||||
| 
 |  | ||||||
| import mightypork.gamecore.graphics.Renderable; | import mightypork.gamecore.graphics.Renderable; | ||||||
| import mightypork.gamecore.gui.screens.ScreenRegistry; | import mightypork.gamecore.gui.screens.ScreenRegistry; | ||||||
| import mightypork.utils.annotations.Stub; |  | ||||||
| import mightypork.utils.eventbus.clients.BusNode; |  | ||||||
| import mightypork.utils.eventbus.events.UpdateEvent; |  | ||||||
| import mightypork.utils.interfaces.Destroyable; | import mightypork.utils.interfaces.Destroyable; | ||||||
| import mightypork.utils.logging.Log; |  | ||||||
| import mightypork.utils.math.timing.Profiler; |  | ||||||
| import mightypork.utils.math.timing.TimerDelta; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Delta-timed game loop with task queue etc. |  * A main loop of the app. | ||||||
|  * |  * | ||||||
|  * @author Ondřej Hruška (MightyPork) |  * @author Ondřej Hruška (MightyPork) | ||||||
|  */ |  */ | ||||||
| public class MainLoop extends BusNode implements Destroyable { | public interface MainLoop extends Destroyable { | ||||||
| 
 | 	 | ||||||
| 	/** |  | ||||||
| 	 * Max time spent on main loop tasks per cycle (s) |  | ||||||
| 	 */ |  | ||||||
| 	protected double MAX_TIME_TASKS = 1 / 30D; |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Max delta time (s) per frame.<br> |  | ||||||
| 	 * If delta is larger than this, it's clamped to it. |  | ||||||
| 	 */ |  | ||||||
| 	protected double MAX_DELTA = 1 / 20D; |  | ||||||
| 
 |  | ||||||
| 	private final Deque<Runnable> tasks = new ConcurrentLinkedDeque<>(); |  | ||||||
| 	private TimerDelta timer; |  | ||||||
| 	private Renderable rootRenderable; |  | ||||||
| 	private volatile boolean running = true; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Set primary renderable | 	 * Set primary renderable | ||||||
| 	 * | 	 * | ||||||
| 	 * @param rootRenderable main {@link Renderable}, typically a | 	 * @param rootRenderable main {@link Renderable}, typically a | ||||||
| 	 *            {@link ScreenRegistry} | 	 *            {@link ScreenRegistry} | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setRootRenderable(Renderable rootRenderable) | 	public abstract void setRootRenderable(Renderable rootRenderable); | ||||||
| 	{ | 	 | ||||||
| 		this.rootRenderable = rootRenderable; | 	 | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Start the loop | 	 * Start the loop. The loop should be terminated when the destroy() method | ||||||
|  | 	 * is called. | ||||||
| 	 */ | 	 */ | ||||||
| 	public void start() | 	public abstract void start(); | ||||||
| 	{ | 	 | ||||||
| 		timer = new TimerDelta(); | 	 | ||||||
| 
 |  | ||||||
| 		while (running) { |  | ||||||
| 			App.gfx().beginFrame(); |  | ||||||
| 
 |  | ||||||
| 			double delta = timer.getDelta(); |  | ||||||
| 			if (delta > MAX_DELTA) { |  | ||||||
| 				Log.f3("(timing) Clamping delta: was " + delta + " s, MAX_DELTA = " + MAX_DELTA + " s"); |  | ||||||
| 				delta = MAX_DELTA; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// dispatch update event
 |  | ||||||
| 			App.bus().sendDirect(new UpdateEvent(delta)); |  | ||||||
| 
 |  | ||||||
| 			// run main loop tasks
 |  | ||||||
| 			Runnable r; |  | ||||||
| 			final long t = Profiler.begin(); |  | ||||||
| 
 |  | ||||||
| 			while ((r = tasks.poll()) != null) { |  | ||||||
| 				Log.f3(" * Main loop task."); |  | ||||||
| 				r.run(); |  | ||||||
| 
 |  | ||||||
| 				if (Profiler.end(t) > MAX_TIME_TASKS) { |  | ||||||
| 					Log.f3("! Time's up, postponing task to next cycle."); |  | ||||||
| 					break; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			beforeRender(); |  | ||||||
| 
 |  | ||||||
| 			if (rootRenderable != null) { |  | ||||||
| 				rootRenderable.render(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			afterRender(); |  | ||||||
| 
 |  | ||||||
| 			App.gfx().endFrame(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Called before render |  | ||||||
| 	 */ |  | ||||||
| 	@Stub |  | ||||||
| 	protected void beforeRender() |  | ||||||
| 	{ |  | ||||||
| 		//
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Called after render |  | ||||||
| 	 */ |  | ||||||
| 	@Stub |  | ||||||
| 	protected void afterRender() |  | ||||||
| 	{ |  | ||||||
| 		//
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void destroy() | 	public abstract void destroy(); | ||||||
| 	{ | 	 | ||||||
| 		running = false; | 	 | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Add a task to queue to be executed in the main loop (in rendering | 	 * Add a task to queue to be executed in the main loop (in rendering | ||||||
| 	 * context) | 	 * context). This may be eg. loading textures. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param task task | 	 * @param task task | ||||||
| 	 * @param skipQueue true to skip the queue | 	 * @param skipQueue true to skip the queue | ||||||
| 	 */ | 	 */ | ||||||
| 	public synchronized void queueTask(Runnable task, boolean skipQueue) | 	public abstract void queueTask(Runnable task, boolean skipQueue); | ||||||
| 	{ | 	 | ||||||
| 		if (skipQueue) { |  | ||||||
| 			tasks.addFirst(task); |  | ||||||
| 		} else { |  | ||||||
| 			tasks.addLast(task); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,40 @@ | |||||||
|  | package mightypork.gamecore.core.init; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import mightypork.gamecore.core.MainLoop; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Task to add a resource loader.<br> | ||||||
|  |  * By default the async resource loader is used | ||||||
|  |  * | ||||||
|  |  * @author Ondřej Hruška (MightyPork) | ||||||
|  |  */ | ||||||
|  | public abstract class InitTaskMainLoop extends InitTask { | ||||||
|  | 	 | ||||||
|  | 	/** The loader. */ | ||||||
|  | 	protected MainLoop loop; | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public void run() | ||||||
|  | 	{ | ||||||
|  | 		loop = getLoopImpl(); | ||||||
|  | 		app.setMainLoop(loop); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Create a loader impl | ||||||
|  | 	 * | ||||||
|  | 	 * @return loader | ||||||
|  | 	 */ | ||||||
|  | 	protected abstract MainLoop getLoopImpl(); | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	@Override | ||||||
|  | 	public String getName() | ||||||
|  | 	{ | ||||||
|  | 		return "resource_loader"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar mais
					Carregando…
					
					
				
		Referência em uma nova issue