playn.java.JavaPlatform Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of playn-java Show documentation
Show all versions of playn-java Show documentation
The PlayN Java (JVM) backend
/**
* Copyright 2010 The PlayN Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package playn.java;
import java.awt.Desktop;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import playn.core.AbstractPlatform;
import playn.core.Analytics;
import playn.core.Game;
import playn.core.Json;
import playn.core.Keyboard;
import playn.core.Mouse;
import playn.core.Net;
import playn.core.PlayN;
import playn.core.Pointer;
import playn.core.RegularExpression;
import playn.core.Storage;
import playn.core.Touch;
import playn.core.TouchImpl;
import playn.core.TouchStub;
import playn.core.json.JsonImpl;
public class JavaPlatform extends AbstractPlatform {
/** Defines JavaPlatform configurable parameters. */
public static class Config {
/** The graphics scale factor. Allows simulating HiDPI mode during testing. */
public float scaleFactor = getDefaultScaleFactor(); // default scale factor is 1
/** Configures platform in headless mode; useful for unit testing. */
public boolean headless = false;
/** Dictates the name of the temporary file used by {@link JavaStorage}. Configure this if you
* want to run multiple sessions without overwriting one another's storage. */
public String storageFileName = "playn";
/** The width of the PlayN window, in pixels. */
public int width = 640;
/** The height of the PlayN window, in pixels. */
public int height = 480;
/** If set, emulates Touch and disables Mouse. For testing. */
public boolean emulateTouch;
}
/**
* Registers the Java platform with a default configuration.
*/
public static JavaPlatform register() {
return register(new Config());
}
/**
* Registers the Java platform with the specified configuration.
*/
public static JavaPlatform register(Config config) {
// guard against multiple-registration (only in headless mode because this can happen when
// running tests in Maven; in non-headless mode, we want to fail rather than silently ignore
// erroneous repeated registration)
if (config.headless && testInstance != null) {
return testInstance;
}
JavaPlatform instance = new JavaPlatform(config);
if (config.headless) {
testInstance = instance;
}
PlayN.setPlatform(instance);
return instance;
}
// If updateRate is 0, we will cap updateDelta at this value.
private static final float MAX_DELTA = 100;
private static JavaPlatform testInstance;
private static float getDefaultScaleFactor() {
String sfprop = System.getProperty("playn.scaleFactor", "1");
try {
return Float.parseFloat(sfprop);
} catch (Exception e) {
System.err.println("Invalid scaleFactor supplied '" + sfprop + "': " + e);
return 1;
}
}
private final JavaAnalytics analytics = new JavaAnalytics();
private final JavaAudio audio = new JavaAudio(this);
private final JavaNet net = new JavaNet(this);
private final JavaRegularExpression regex = new JavaRegularExpression();
private final JavaStorage storage;
private final JsonImpl json = new JsonImpl();
private final JavaKeyboard keyboard = new JavaKeyboard();
private final JavaPointer pointer = new JavaPointer();
private final TouchImpl touch;
private final JavaGraphics graphics;
private final JavaMouse mouse;
private final JavaAssets assets = new JavaAssets(this);
private final ExecutorService _exec = Executors.newFixedThreadPool(4);
private final long start = System.nanoTime();
public JavaPlatform(Config config) {
super(new JavaLog());
graphics = new JavaGraphics(this, config);
storage = new JavaStorage(this, config);
if (config.emulateTouch) {
JavaEmulatedTouch emuTouch = new JavaEmulatedTouch();
mouse = emuTouch.createMouse(this);
touch = emuTouch;
} else {
mouse = new JavaMouse(this);
touch = new TouchStub();
}
}
/**
* Sets the title of the window.
*
* @param title the window title
*/
public void setTitle(String title) {
Display.setTitle(title);
}
@Override
public void invokeAsync(Runnable action) {
_exec.execute(action);
}
@Override
public Type type() {
return Type.JAVA;
}
@Override
public JavaAudio audio() {
return audio;
}
@Override
public JavaGraphics graphics() {
return graphics;
}
@Override
public Json json() {
return json;
}
@Override
public Keyboard keyboard() {
return keyboard;
}
@Override
public Net net() {
return net;
}
@Override
public Pointer pointer() {
return pointer;
}
@Override
public Mouse mouse() {
return mouse;
}
@Override
public Touch touch() {
return touch;
}
@Override
public Storage storage() {
return storage;
}
@Override
public Analytics analytics() {
return analytics;
}
@Override
public JavaAssets assets() {
return assets;
}
@Override
public RegularExpression regularExpression() {
return regex;
}
@Override
public float random() {
return (float) Math.random();
}
@Override
public double time() {
return System.currentTimeMillis();
}
@Override
public int tick() {
return (int)((System.nanoTime() - start) / 1000000L);
}
@Override
public void openURL(String url) {
try {
Desktop.getDesktop().browse(URI.create(url));
} catch (Exception e) {
log.warn("Failed to open URL [url=" + url + ", error=" + e + "]");
}
}
@Override
public void setPropagateEvents(boolean propagate) {
mouse.setPropagateEvents(propagate);
touch.setPropagateEvents(propagate);
pointer.setPropagateEvents(propagate);
}
@Override
public void run(final Game game) {
try {
// initialize LWJGL (and show the display) now that the game has been initialized
graphics.init();
// now that the display is initialized we can init our mouse and keyboard
mouse.init();
keyboard.init();
} catch (LWJGLException e) {
throw new RuntimeException("Unrecoverable initialization error", e);
}
game.init();
boolean wasActive = Display.isActive();
while (!Display.isCloseRequested()) {
// Event handling.
mouse.update();
keyboard.update();
pointer.update();
// Notify the app if lose or regain focus (treat said as pause/resume).
if (wasActive != Display.isActive()) {
if (wasActive)
onPause();
else
onResume();
wasActive = Display.isActive();
}
// Execute any pending runnables.
runQueue.execute();
// Run the game loop, render the scene graph, and update the display.
game.tick(tick());
graphics.paint();
Display.update();
// Sleep until it's time for the next frame.
Display.sync(60);
}
// let the game run any of its exit hooks
onExit();
// shutdown our thread pool
try {
_exec.shutdown();
_exec.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
// nothing to do here except go ahead and exit
}
// and finally stick a fork in the JVM
System.exit(0);
}
private static long now () {
return System.nanoTime() / 1000000L;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy