- Desktop (LWJGL3)
- Desktop (LWJGL)
- Android
- Game Activity
- Game Fragment
- Manifest configuration
- Live Wallpapers
- Screen Savers (aka Daydreams)
- iOS/Robovm
- HTML5/GWT
Applicationimplementation and theApplicationListenerthat implements the application logic. The starter classes are platform dependent, let’s have a look at how to instantiate and configure these for each back-end. Project Setup, Importing & Running a Project and therefore have imported the generated core, desktop, Android and HTML5 projects into Eclipse.Desktop (LWJGL3)
DesktopLauncher.javaclass inmy-gdx-gameshows the following:
Lwjgl3ApplicationConfiguration is instantiated. This class lets one specify various configuration settings, such as the initial screen resolution, whether to use OpenGL ES 2.0 or 3.0 and so on. Refer to the Javadocs of this class for more information.package com.me.mygdxgame;import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;public class DesktopLauncher { public static void main(String[] args) { Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); config.setTitle("my-gdx-game"); config.setWindowedMode(480, 320); new Lwjgl3Application(new MyGdxGame(), config); }}
Lwjgl3Applicationis instantiated. TheMyGdxGame()class is the ApplicationListener implementing the game logic. The Life-CycleCommon issues:
- macOS, the LWJGL 3 backend is only working when the JVM is run with the ** argument. This can typically be done in the Launch/Run Configurations of your IDE, as is described here. Alternatively, if you’re starting your project via Gradle, add this line to
runtask of the desktop gradle file:
jvmArgs = ['-XstartOnFirstThread']
here for a simple example). Lastly, if you want to deploy your game by packaging a JRE with it (which is the recommended way to distribute your later game), jpackage or packr allow you to set the JVM arguments.
- gdx-tools and the lwjgl3 backend in the same project, you need to modify your gdx-tools dependency like this:
compile ("com.badlogicgames.gdx:gdx-tools:$gdxVersion") { exclude group: 'com.badlogicgames.gdx', module: 'gdx-backend-lwjgl'}
here.
Desktop (LWJGL)
here.
DesktopLauncher.java class in my-gdx-game shows the following:
package com.me.mygdxgame;import com.badlogic.gdx.backends.lwjgl.LwjglApplication;import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;public class DesktopLauncher { public static void main(String[] args) { LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration(); cfg.title = "my-gdx-game"; cfg.useGL30 = false; cfg.width = 480; cfg.height = 320; new LwjglApplication(new MyGdxGame(), cfg); }}
LwjglApplicationConfiguration is instantiated. This class lets one specify various configuration settings, such as the initial screen resolution, whether to use OpenGL ES 2.0 or 3.0 (Experimental) and so on. Refer to the Javadocs of this class for more information.
LwjglApplication is instantiated. The MyGdxGame() class is the ApplicationListener implementing the game logic.
The Life-Cycle
Common issues:
- “illegal reflective access” warning is shown. This is nothing to be worried about. If it bothers you, downgrade the used JDK or switch to the LWJGL 3 backend.
- ** is shown, this can safely be ignored. A workaround is disabling forceExit:
config.forceExit = false;.Android
Game Activity
main()method as the entry-point, but instead require an Activity. Open theMainActivity.javaclass in themy-gdx-game-androidproject:package com.me.mygdxgame;import android.os.Bundle;import com.badlogic.gdx.backends.android.AndroidApplication;import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;public class MainActivity extends AndroidApplication { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); initialize(new MyGdxGame(), cfg); }}
onCreate()method. Note thatMainActivityderives fromAndroidApplication, which itself derives fromActivity. As in the desktop starter class, a configuration instance is created (AndroidApplicationConfiguration). Once configured, theAndroidApplication.initialize()method is called, passing in theApplicationListener,MyGdxGame)\ as well as the configuration. Refer to the AndroidApplicationConfiguration Javadocs for more information on what configuration settings are available.Activityalso implies creating a new OpenGL context, which is time consuming and also means that all graphical resources have to be reloaded.Game Fragment
Fragment instead of using a complete Activity. This allows it to take up a portion of the screen in an Activity or be moved between layouts. To create a libGDX fragment, subclassAndroidFragmentApplicationand implement theonCreateView()with the following initialization:
That code depends on some other changes to the -android project:@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return initializeForView(new MyGdxGame()); }
- Add AndroidX Fragment Library to the -android project and its build path if you haven’t already added it. This is needed in order to extend FragmentActivity later.
initializeForView()code in the Fragment’sonCreateViewmethod. 6. For example:// 2. Change AndroidLauncher activity to extend FragmentActivity, not AndroidApplication// 3. Implement AndroidFragmentApplication.Callbacks on the AndroidLauncher activitypublic class AndroidLauncher extends FragmentActivity implements AndroidFragmentApplication.Callbacks{ @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 6. Finally, replace the AndroidLauncher activity content with the libGDX Fragment. GameFragment fragment = new GameFragment(); FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.replace(android.R.id.content, fragment); trans.commit(); } // 4. Create a Class that extends AndroidFragmentApplication which is the Fragment implementation for libGDX. public static class GameFragment extends AndroidFragmentApplication { // 5. Add the initializeForView() code in the Fragment's onCreateView method. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return initializeForView(new MyGdxGame()); } } @Override public void exit() {}}
Manifest configuration
AndroidApplicationConfiguration, an Android application is also configured via theAndroidManifest.xmlfile, found in the root directory of the Android project. This might look something like this:<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.me.mygdxgame"> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:configChanges="keyboard|keyboardHidden|orientation"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
Screen Orientation & Configuration Changes
screenOrientationandconfigChangesattributes of the activity element should always be set.screenOrientationattribute specifies a fixed orientation for the application. One may omit this if the application can work with both landscape and portrait mode.configChangesattribute is crucial and should always have the values shown above. Omitting this attribute means that the application will be restarted every time a physical keyboard is slid out/in or if the orientation of the device changes. If thescreenOrientationattribute is omitted, a libGDX application will receive calls toApplicationListener.resize()to indicate the orientation change. API clients can then re-layout the application accordingly.Permissions
AndroidManifest.xmlfile:
Users are generally suspicious of applications with many permissions, so choose these wisely.<uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.VIBRATE"/>
AndroidApplicationConfiguration.useWakeLockneeds to be set to true.useAccelerometeranduseCompassfields ofAndroidApplicationConfigurationto false.useGyroscopeto true inAndroidApplicationConfiguration(It’s disabled by default, to save energy). Android Developer’s Guide for more information on how to set other attributes like icons for your application.Live Wallpapers
Live Wallpaper. The project setup is very similar to an Android game, butAndroidLiveWallpaperServiceis used in place ofAndroidApplication. Live Wallpapers are Android Services, not Activities. Note: Due to synchronization issues, you cannot combine games and live wallpapers in the same app. However, Live Wallpapers and Screen Savers can safely coexist in the same app.AndroidLiveWallpaperServiceand overrideonCreateApplication()(instead ofonCreate()like you would do with a gameActivity):public class MyLiveWallpaper extends AndroidLiveWallpaperService { @Override public void onCreateApplication() { AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); initialize(new MyGdxGame(), cfg); }}
AndroidWallpaperListenerwith yourApplicationListenerclass.AndroidWallpaperListeneris not available from thecoremodule, so you can either follow the strategy outlined in Interfacing With Platform-Specific Code, or you can manage it just from theandroidmodule by subclassing yourApplicationListenerlike this:
Interfacing With Platform-Specific Code:public class MyLiveWallpaper extends AndroidLiveWallpaperService { static class MyLiveWallpaperListener extends MyGdxGame implements AndroidWallpaperListener { @Override public void offsetChange (float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { // Called when the home screen is scrolled. Not all launchers support this. } @Override public void previewStateChange (boolean isPreview) { // Called when switched between being previewed and running as the wallpaper. } @Override public void iconDropped (int x, int y) { // Called when an icon is dropped on the home screen. } } @Override public void onCreateApplication() { AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); initialize(new MyLiveWallpaperListener(), cfg); }}
public void notifyColorsChanged (Color primaryColor, Color secondaryColor, Color tertiaryColor) { Application app = Gdx.app; if (Build.VERSION.SDK_INT >= 27 && app instanceof AndroidLiveWallpaper) { ((AndroidLiveWallpaper) app).notifyColorsChanged(primaryColor, secondaryColor, tertiaryColor); }}
xmlfile in the Androidres/xmldirectory to define some Live Wallpaper properties: its thumbnail and description shown in the wallpaper picker, and an optional settings Activity. Let’s call this filelivewallpaper.xml.<?xml version="1.0" encoding="UTF-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/ic_launcher" android:description="@string/description" android:settingsActivity="com.mypackage.MyLiveWallpaperSettingsActivity"/>
AndroidManifest.xmlfiles. Here’s an example for a Live Wallpaper with a simple settings Activity. The key elements here are theuses-featureandserviceblocks. The label and icon set on the service appear in the Android application settings. The settings Activity and the Live Wallpaper service must both be set withexportedtrue so they can be accessed by the Live Wallpaper picker.<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mypackage"> <uses-feature android:name="android.software.live_wallpaper" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyLiveWallpaperSettingsActivity" android:label="@string/app_name" android:exported="true" /> <service android:name=".LiveWallpaper" android:label="@string/app_name" android:icon="@drawable/icon" android:exported="true" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/livewallpaper" /> </service> </application></manifest>
AndroidApplicationConfiguration.getTouchEventsForLiveWallpaperfield to true.Screen Savers (aka Daydreams)
Screen Saver. Screen Savers were once known as Daydreams, so many of the related classes have the term “Daydream” in their names. Screen Savers have no relation to Google’s Daydream VR platform.AndroidDaydreamis used in place ofAndroidApplication. Screen Savers are Android Services, not Activities.AndroidDaydreamand overrideonAttachedToWindow()(instead ofonCreate()like you would do with a gameActivity). It must call through tosuper. You can also callsetInteractive()from this method to enable/disable touch. A non-interactive Screen Saver immediately closes when the screen is touched.public class MyScreenSaver extends AndroidDaydream { @Override public void onAttachedToWindow() { super.onAttachedToWindow(); setInteractive(true); AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); initialize(new MyGdxGame(), cfg); }}
xmlfile in the Androidres/xmldirectory to define the only Screensaver setting: an optional settings Activity. Let’s call this filescreensaver.xml.<?xml version="1.0" encoding="UTF-8"?><dream xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.badlogic.gdx.tests.android/.MyScreenSaverSettingsActivity" />
AndroidManifest.xmlfiles. Here’s an example for a Screen Saver with a simple settings Activity. Note that a settings Activity is optional. The key element is theserviceblock. The settings Activity and the Screen Saver service must both be set withexportedtrue so they can be accessed by the Screen Saver picker.<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mypackage"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyScreenSaverSettingsActivity" android:label="@string/app_name" android:exported="true" /> <service android:name=".MyScreenSaver" android:label="@string/app_name" android:icon="@drawable/icon" android:exported="true" > <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.service.dream" android:resource="@xml/screensaver" /> </service> </application></manifest>
iOS/Robovm
To come..HTML5/GWT
GwtApplication. OpenGwtLauncher.javain the my-gdx-game-html5 project:package com.me.mygdxgame.client;import com.me.mygdxgame.MyGdxGame;import com.badlogic.gdx.ApplicationListener;import com.badlogic.gdx.backends.gwt.GwtApplication;import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration;public class GwtLauncher extends GwtApplication { @Override public GwtApplicationConfiguration getConfig () { GwtApplicationConfiguration cfg = new GwtApplicationConfiguration(480, 320); return cfg; } @Override public ApplicationListener createApplicationListener () { return new MyGdxGame(); }}
GwtApplication.getConfig()andGwtApplication.createApplicationListener(). The former has to return a GwtApplicationConfiguration instance, which specifies various configuration settings for the HTML5 application. TheGwtApplication.createApplicatonListener()method returns theApplicationListenerto run.Module Files
GWT needs the actual Java code for each jar/project that is referenced. Additionally, each of these jars/projects needs to have one module definition file, having the suffix gwt.xml. In the example project setup, the module file of the html5 project looks like this:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit trunk//EN" "http://google-web-toolkit.googlecode.com/svn/trunk/distro-source/core/src/gwt-module.dtd"><module> <inherits name='com.badlogic.gdx.backends.gdx_backends_gwt' /> <inherits name='MyGdxGame' /> <entry-point class='com.me.mygdxgame.client.GwtLauncher' /> <set-configuration-property name="gdx.assetpath" value="../my-gdx-game-android/assets" /></module>
GwtLauncherabove) and a path relative to the html5 project’s root directory, pointing to the assets directory. You can not use jars/projects which do not contain a module file and source! GWT Developer Guide.Reflection Support
Json serialization capabilities of libgdx, you’ll run into issues. You can fix this by specifying for which packages and classes reflection information should be generated for. To do so, you can put configuration properties in your GWT project’s gwt.xml file like so:
You can add multiple packages and classes by adding more extend-configuration-property elements. This feature is experimental, use at your own risk.<?xml version="1.0" encoding="UTF-8" standalone="no"?><module> ... other elements ... <extend-configuration-property name="gdx.reflect.include" value="org.softmotion.explorers.model" /> <extend-configuration-property name="gdx.reflect.exclude" value="org.softmotion.explorers.model.HexMap" /></module>
Loading Screen
gdx.assetpath. During this loading process, a loading screen is displayed which is implemented via GWT widget. If you want to customize this loading screen, you can simply overwrite theGwtApplication.getPreloaderCallback()method (GwtLauncherin the above example). From 1.9.10 on, the following code changes the colors of the progress bar and the displayed logo to a file placed within your webapp folder:@Overridepublic Preloader.PreloaderCallback getPreloaderCallback() { return createPreloaderPanel(GWT.getHostPageBaseURL() + "preloadlogo.png");}@Overrideprotected void adjustMeterPanel(Panel meterPanel, Style meterStyle) { meterPanel.setStyleName("gdx-meter"); meterPanel.addStyleName("nostripes"); meterStyle.setProperty("backgroundColor", "#ffffff"); meterStyle.setProperty("backgroundImage", "none");}
getPreloaderCallback()content from libGDX’ sources and adjust it to your needs. Note that you can only use pure GWT facilities to display the loading screen, libGDX APIs will only be available after the preloading is complete. Prev | Next
