libGDX的启动类和配置

news/2024/9/23 9:36:57/

原文作者:libGDX
原文地址:https://github.com/libgdx/libgdx/wiki/Starter-classes-and-configuration
译文作者:Jianan - qinxiandiqi@foxmail.com
版本信息:本文基于2018-07-22版本翻译
译文版权:CC BY-NC-ND 4.0,允许复制转载,但必须保留译文作者署名及译文链接。


对于每个目标平台,我们都必须编写对应的启动类。这个类根据特定的底层平台实现Application接口,同时也实现提供应用逻辑代码的ApplicationListener接口。这个启动类依赖于具体的底层平台,下面让我们来看看启动类在每个底层平台上的实现和配置。

本文假设你已按照libGDX的项目设置、运行和调试一文中的说明进行操作,并已将生成的Core、桌面、Android和HTML5项目代码导入到Eclipse。(译注:该创建libGDX项目文章已经过时,新项目创建方法请参考使用gradle创建libGDX项目)


桌面平台 (基于LWJGL)


打开my-gdx-game项目中的Main.java类,你会看到以下代码:

package com.me.mygdxgame;import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;public class Main {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。此类允许设置各种配置,例如初始屏幕分辨率,是否使用OpenGL ES 2.0或3.0(当前还处于实验阶段)等。有关更多信息,请参阅此类的Javadocs。

设置好这个配置对象之后,下一步开始实例化LwjglApplication。它的构造方法包含一个MyGdxGame()类对象,这个MyGdxGame类实际上是实现了游戏逻辑的ApplicationListener接口实例。

在这之后就会有一个窗口被创建出来,并开始执行ApplicationListener接口中的相关生命周期方法,详情请参考libGDX的生命周期。


桌面平台 (基于LWJGL3)


等待补充……


Android平台


Android应用程序不使用main()方法作为启动类入口点,而是需要一个Activity。打开my-gdx-game-android项目中的MainActivity.java类:

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 {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();initialize(new MyGdxGame(), cfg);}
}

Android的主要入口是Activity的onCreate()方法。请注意,上面代码中的MainActivity继承了AndroidApplication类,而AndroidApplication又继承类Activity。类似桌面平台的启动类,首先要创建配置实例AndroidApplicationConfiguration。配置完成后,调用AndroidApplication.initialize()方法,与ApplicationListener实例(本例中是MyGdxGame)一起传入。有关配置类可用的设置参数,请参阅AndroidApplicationConfiguration Javadocs。

Android应用程序可以有多个Activity,但Libgdx游戏通常只应包含一个Activity。如果游戏需要显示多个分屏,应通过libgdx来实现,而不是使用多个Activity。这样做的原因是创建一个新的Activity意味着创建一个新的OpenGL Context,这是非常耗时的,而且也意味着必须重新加载所有图形资源。


基于Fragment的libgdx


Android SDK引入了一个API,可以为屏幕的特定区域创建控制器,甚至可以在多个屏幕上轻松重复使用。此API称为Fragments API。Libgdx现在也可以以Fragment的形式引入,做为更大屏幕的一部分。要创建包含Libgdx的Fragment,fragment必须继承AndroidFragmentApplication,并使用下面方式重写onCreateView()方法:

    @Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return initializeForView(new MyGdxGame());}

使用fragment引入libGDX的代码与上面使用Activity引入libGDX的步骤和代码有些许区别:
1. 添加Android V4支持库。如果你的Android项目还没有添加这个支持库,那你必须添加这个依赖库以便后面使用FragmentActivity。
2. 修改AndroidLauncher继承FragmentActivity,而不是继承AndroidApplication。
3. AndroidLauncher这个activity需要实现AndroidFragmentApplication.Callbacks接口。
4. 创建继承AndroidFragmentApplication类的Fragment,这个fragment是libGDX的实现。
5. 添加上面提到的initializeForView()代码到Fragment的onCreateView方法中。
6. 最后,将AndroidLauncher Activity的content替换为这个libGDX fragment。

例如:

// 2. 修改AndroidLauncher继承FragmentActivity,而不是继承AndroidApplication。
// 3. AndroidLauncher activity实现AndroidFragmentApplication.Callbacks接口
public class AndroidLauncher extends FragmentActivity implements AndroidFragmentApplication.Callbacks
{@Overrideprotected void onCreate (Bundle savedInstanceState){super.onCreate(savedInstanceState);// 6. 最后,将AndroidLauncher Activity的content替换为这个libGDX fragment。GameFragment fragment = new GameFragment();FragmentTransaction trans = getSupportFragmentManager().beginTransaction();trans.replace(android.R.id.content, fragment);trans.commit();}// 4. 创建继承AndroidFragmentApplication类的Fragment,这个fragment是libGDX的实现。public static class GameFragment extends AndroidFragmentApplication{// 5. 添加initializeForView()到Fragment的onCreateView方法中。@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){  return initializeForView(new MyGdxGame());   }}@Overridepublic void exit() {}
}

AndroidManifest.xml文件

除了AndroidApplicationConfiguration,Android应用程序还要对AndroidManifest.xml文件进行配置,该文件位于Android项目的根目录中。你大概需要进行以下的配置:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.me.mygdxgame"android:versionCode="1"android:versionName="1.0" ><uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /><application
        android:icon="@drawable/ic_launcher"android:label="@string/app_name" ><activity
            android:name=".AndroidLauncher"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>

目标Sdk版本

将targetSDKVersion设置为你要的目标Android版本。

屏幕方向和设备配置更改

除了targetSdkVersion,activity的screenOrientationconfigChanges属性通常也要设置。

screenOrientation属性指定应用程序屏幕的固定方向。如果应用程序可以同时使用横向和纵向模式,则可以省略此项。

configChanges属性至关重要,它应始终设置为上面显示的值。省略此属性意味着每次物理键盘滑出/插入或设备方向发生变化时,应用程序都将重新启动(译注:忽略这个属性,默认设备这些属性发生修改时会重新启动该Activity,由于libGDX基于Activity注入,Activity重启也意味着libGDX实例重启)。如果是screenOrientation属性被省略,libgdx应用程序将回调ApplicationListener.resize()方法以指示方向更改。然后,API客户端可以相应地重新调整应用程序的布局。

权限

如果应用程序需要能够写入设备的外部存储器(例如SD卡),或者需要访问互联网,又或者需要使用振动器或想要录制音频,则需要将以下权限添加到AndroidManifest.xml文件中:

    <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.useWakeLock需要将其设置为true。

如果游戏不需要加速计或指南针访问,建议通过将AndroidApplicationConfiguration.useAccelerometerAndroidApplicationConfiguration.useCompass字段设置false来禁用它们 。

如果你的游戏需要陀螺仪传感器,则必须设置AndroidApplicationConfiguration.useGyroscope为true(默认情况下它是被禁用,这样可以节省电量)。

有关如何为应用程序设置图标等其他属性的详细信息,请参阅Android开发人员指南。


动态壁纸


Libgdx提供了一种简单易用的方法来为Android创建动态壁纸。动态壁纸的启动类是AndroidLiveWallpaperService,下面是一个例子:

package com.mypackage;// imports snipped for brevity public class LiveWallpaper extends AndroidLiveWallpaperService {@Overridepublic ApplicationListener createListener () {return new MyApplicationListener();}@Overridepublic AndroidApplicationConfiguration createConfig () {return new AndroidApplicationConfiguration();}@Overridepublic void offsetChange (ApplicationListener listener, float xOffset, float yOffset, float xOffsetStep, float yOffsetStep,int xPixelOffset, int yPixelOffset) {Gdx.app.log("LiveWallpaper", "offset changed: " + xOffset + ", " + yOffset);}
}

当你的动态壁纸在选择器中显示或创建后在主屏幕上显示时,createListener()createConfig()方法会被回调。

当用户在主屏幕上滑动屏幕时,offsetChange() 方法会被调用,并且告诉你当前屏幕偏离中心屏幕多少。这个方法会在渲染线程上执行,因此你不必同步任何内容。

除了启动类之外,你还必须创建一个描述壁纸的XML文件,我们暂且称之为livewallpaper.xml。在Android项目的res/资源文件夹下创建一个xml/文件夹,并将文件放在这个文件夹里面(res/xml/livewallpaper.xml)。下面是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.LivewallpaperSettings"/>

文件中的thumbnail定义了你的动态壁纸在选择器中P显示的缩略图,descriptionsettingsActivity定义了当用户点击动态壁纸选择器中的“设置”时将显示的描述和Activity。这Activity应该只是一个标准的Activity,它有一些小组件可以更改动态壁纸的一些设置,例如背景颜色和类似的东西。你可以将这些设置存储在SharedPreferences中,稍后就可以在动态壁纸的ApplicationListener中通过Gdx.app.getPreferences()加载它们。

最后,你需要在AndroidManifest.xml文件中添加内容。以下是包含简单设置Activity的动态壁纸的示例:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.mypackage"android:versionCode="1"android:versionName="1.0"android:installLocation="preferExternal"><uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14"/> <uses-feature android:name="android.software.live_wallpaper" /><application android:icon="@drawable/icon" android:label="@string/app_name"><activity android:name=".LivewallpaperSettings" android:label="Livewallpaper Settings"/><service android:name=".LiveWallpaper"android:label="@string/app_name"android:icon="@drawable/icon"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> 

这个manifest定义了:

  • 它要使用动态壁纸功能,请参阅<uses-feature>标签。
  • 允许绑定壁纸的权限,请参阅android:permission属性。
  • 指定壁纸设置的Activity
  • 指定livewallpaper的service,它指向livewallpaper.xml文件,请参阅meta-data

注意动态壁纸从Android 2.1 (SDK level 7)之后才开始支持。

动态壁纸在触摸输入方面有一些限制。通常只会报告点击/拖放事件。如果你想要接收全部触摸事件,你可以将AndroidApplicationConfiguration#getTouchEventsForLiveWallpaper标志设为true以接收完整的多点触控事件。


Daydreams(VR)


从Android 4.2开始,当设备处于空闲或停靠状态时,用户可以设置Daydreams(译注:Google在Android上引入的VR平台)显示出来。这些Daydreams类似于屏保,可以用来显示相册等内容。Libgdx可以让你轻松写出这样的Daydreams应用。

Daydream的启动类是AndroidDaydream。下面是一个例子:

package com.badlogic.gdx.tests.android;import android.annotation.TargetApi;
import android.util.Log;import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.badlogic.gdx.backends.android.AndroidDaydream;
import com.badlogic.gdx.tests.MeshShaderTest;@TargetApi(17)
public class Daydream extends AndroidDaydream {@Overridepublic void onAttachedToWindow() {super.onAttachedToWindow();      setInteractive(false);AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();ApplicationListener app = new MeshShaderTest();initialize(app, cfg);}
}

只需要继承AndroidDaydream,重写onAttachedToWindow方法,添加配置和ApplicationListener就可以初始化你的Daydream。

除了Daydream本身,你还可以提供配置用的Activity,让用户配置你的Daydream。这可以是普通的Activity,也可以是libgdx的AndroidApplication。以空Activity为例:

package com.badlogic.gdx.tests.android;import android.app.Activity;public class DaydreamSettings extends Activity {}

必须将此配置Activity指定为Daydream服务的metadata。在Android项目的res/xml文件夹中创建一个xml文件,并指定如下activity:

<dream xmlns:android="http://schemas.android.com/apk/res/android"android:settingsActivity="com.badlogic.gdx.tests.android/.DaydreamSettings" />

最后,像往常一样在AndroidManifest.xml中添加配置activity的部分,以及daydream的service描述,如下所示:

<service android:name=".Daydream"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/daydream" />
</service>


iOS/Robovm平台


等待补充……


HTML5/GWT平台


HTML5/GWT应用程序的主要启动类是GwtApplication。打开my-gdx-game-html5项目中的GwtLauncher.java类:

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 {@Overridepublic GwtApplicationConfiguration getConfig () {GwtApplicationConfiguration cfg = new GwtApplicationConfiguration(480, 320);return cfg;}@Overridepublic ApplicationListener createApplicationListener () {return new MyGdxGame();}
}

启动类主要由两个方法组成,GwtApplication.getConfig()GwtApplication.createApplicationListener()。 前者必须返回一个GwtApplicationConfiguration实例, 这个实例指定HTML5应用程序的各种配置。GwtApplication.createApplicatonListener()方法为程序运行提供 ApplicationListener实例.

模块文件

GWT需要引用每个jars/projects目录下的Java代码。此外,每个jars/projects都需要有一个模块定义文件,后缀为gwt.xml。

在示例项目的设置中,html5项目的模块文件如下所示:

<?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>

上面指定了另外两个继承的模块(gdx-backends-gwt模块和Core项目模块),指明启动类(GwtLauncher),以及相对于HTML5项目根目录的assets资源目录。

注意,gdx-backend-gwt模块和Core项目都有一个类似的模块定义文件,里面可能指定了其他依赖项。你不能使用不包含模块文件和源文件的jars/projects模块!

有关模块和依赖关系的更多信息,请参阅GWT开发人员指南。

反射支持

由于各种原因,GWT不支持Java反射。Libgdx有一个内部仿真层,它将为少数几个内部类生成反射信息。这意味着如果你使用libgdx的Json序列化功能,你将遇到问题。你可以通过指定要为哪些包和类生成反射信息来解决此问题。为此,你可以将配置属性放在GWT项目的gwt.xml文件中,如下所示:

<?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>

你可以通过添加更多extend-configuration-property元素来添加多个包和类。

此功能目前属于实验性使用,使用风险自负。

载入画面

libgdx HTML5应用程序会预加载所有能在gdx.assetpath中找到的资源。在此加载过程中,将显示一个加载画面,该加载画面通过GWT小部件实现。如果要自定义此加载画面,只需覆盖该GwtApplication.getPreloaderCallback()方法(在上例中,该方法在GwtLauncher类中)。以下示例使用Canvas绘制一个非常简单,丑陋的加载画面:

long loadStart = TimeUtils.nanoTime();
public PreloaderCallback getPreloaderCallback () {final Canvas canvas = Canvas.createIfSupported();canvas.setWidth("" + (int)(config.width * 0.7f) + "px");canvas.setHeight("70px");getRootPanel().add(canvas);final Context2d context = canvas.getContext2d();context.setTextAlign(TextAlign.CENTER);context.setTextBaseline(TextBaseline.MIDDLE);context.setFont("18pt Calibri");return new PreloaderCallback() {@Overridepublic void done () {context.fillRect(0, 0, 300, 40);}@Overridepublic void loaded (String file, int loaded, int total) {System.out.println("loaded " + file + "," + loaded + "/" + total);String color = Pixmap.make(30, 30, 30, 1);context.setFillStyle(color);context.setStrokeStyle(color);context.fillRect(0, 0, 300, 70);color = Pixmap.make(200, 200, 200, (((TimeUtils.nanoTime() - loadStart) % 1000000000) / 1000000000f));context.setFillStyle(color);context.setStrokeStyle(color);context.fillRect(0, 0, 300 * (loaded / (float)total) * 0.97f, 70);context.setFillStyle(Pixmap.make(50, 50, 50, 1));context.fillText("loading", 300 / 2, 70 / 2);}@Overridepublic void error (String file) {System.out.println("error: " + file);}};
}

请注意,你只能使用纯GWT工具来显示加载画面,libgdx相关的API要在预加载完成后才可用。

上一章|libGDX的模块
下一章|查询libGDX运行环境相关信息


http://www.ppmy.cn/news/765271.html

相关文章

又有新的iPhone 8爆料图,这次嵌入式Touch ID或成真

此前在苹果的WWDC上&#xff0c;他们展示ios 11的更新&#xff0c;不过关于下一代手机的消息却是半点未透露。近日&#xff0c;国外媒体iDropNews曝光了一组新的iPhone 8渲染图&#xff0c;图片显示手机前置面板采用无边框设计&#xff0c;顶部保留了扬声器和摄像头的区域。而我…

[python 爬虫]微信公众号权律二表情和壁纸爬虫

搜狗搜索引擎可以搜索到微信的公众号&#xff0c;许久没有爬虫了&#xff0c;最近买了崔大神的《python网络爬虫开发实战》&#xff0c;感觉又回到了一年前初学爬虫时满怀激情的时代。下面小试牛刀&#xff0c;利用一些基本的库 requests-html&#xff0c;xpath&#xff0c;req…

如何做好VR全景营销?选择好的全景平台很重要

现如今&#xff0c;许多关于VR全景创业、VR全景加盟的信息铺天盖地&#xff0c;很多人都看到了VR行业的潜力&#xff0c;想要借助VR全景平台来创业&#xff0c;但是如何找合适的全景平台呢&#xff1f;这是一个很重要的问题&#xff0c;因为只有好的VR全景平台&#xff0c;才能…

Enscape 3.4这些功能还不会用?学会让你事半功倍

Enscape是面向建筑师、设计师和其他 AEC 专业人士的实时可视化和 VR 插件。其最新更新Enscape 3.4为现有功能提供了有价值的更新&#xff0c;因此您可以继续改进您的设计和可视化体验。 功能更新包括 Enscape 自定义资源库的类别、在视图中保存自然光位置的能力、对现有视图的进…

VR智慧家装,给业主带来别样的家装体验!

装修行业的格局是典型的大行业、小企业&#xff0c;中小企业占据了整个行业很大一部分&#xff0c;而且由于家装流程过于繁琐&#xff0c;涉及的环节也比较多&#xff0c;造成企业和客户信息不对称&#xff0c;客户满意度很难平衡&#xff0c;因此装修行业迫切的需要新的技术和…

免费HTTPS证书 Certbot Letsencrypt 傻瓜教程

概述 Letsencrypt提供了免费的https证书服务&#xff0c;但是操作复杂&#xff0c;所以官方就开发了Cerbot自动化工具。 我的环境 ubuntu 20.04.5 LTS nginx 1.18.0 python 3.8.10 配置Nginx #可以添加多个服务&#xff0c;Cerbot都会自动识别 server {listen 80;listen […

关于项目介入VR功能简单介绍

技术介绍 VR Virtual Reality&#xff0c;虚拟现实&#xff0c;或称灵境技术&#xff0c;实际上是一种可创建和体验虚拟世界&#xff08;Virtual World&#xff09;的计算机系统。 友好度很重要 随着社会经济的发展&#xff0c;计算机已经成为社会生活中不可缺少的重要组成部分…

如何扫描汽车并在VR中进行组装?

这个项目是如何诞生的&#xff1f; 在我开始这个项目之前&#xff0c;我的大部分周末都是在打工和玩车。我有第一代Miata&#xff0c;我自动横渡了几年&#xff0c;并开始准备赛道日。我也做一些碳纤维和钢铁制造。我喜欢制造&#xff0c;解决问题和设计。为了我的兴趣&#…