Ohhnews

分类导航

$ cd ..
foojay原文

原生Java Win32、3D游戏、打印与钱包功能发布

#codename one#原生windows支持#3d图形api#游戏开发#apple钱包

目录


[LOADING...]

本周我们推出了原生Windows支持(无需JVM!)、3D图形API、游戏API、Apple Wallet支持、打印功能等——这可能是我们迄今为止最大的一次更新……但最让我兴奋的还不是这些。

最让我兴奋的事

我不会在这方面吊你胃口。本周最令我兴奋的是 Francesco Galgani在Baeldung上发表的这篇介绍Codename One的新文章。除了出色的写作和形式外,更让我激动的是社区:你们所有人的使用方式,以及你们帮助我们构建它的过程。来自社区的反馈、跟踪以及对未来功能的热情,比如 这个 —— 一个合并文档章节的请求,在正式提出之前先对游戏开发API连说了三声感谢。

再次感谢大家成为这个社区的一部分。没有你们,我们真的无法做到这一切!

本周发布内容

版本 7.0.251 已上线,四大功能将在未来几天内分别发布完整教程。以下是更深入的介绍。

便携式3D图形API

com.codename1.gpu 是一个GPU加速的3D API,同样的Java代码能通过 iOS和Mac上的Metal、Android上的OpenGL ES、Web上的WebGL、新原生Windows端口上的Direct3D 11 以及模拟器中无依赖的软件光栅化进行渲染。实现便携性的诀窍在于你永远不需要编写着色器源码:你只需描述一个 Material(光照模型、颜色、纹理、光泽度),引擎便会根据目标平台生成对应的着色器(GLSL、Metal Shading Language 或 HLSL)。

一个带有光照且旋转的立方体,代码简洁如下:

$ java
public void onInit(GraphicsDevice device) {
    cube = Primitives.cube(device, 1.6f);
    material = new Material(Material.Type.PHONG)
            .setColor(0xff3366ff)
            .setShininess(24f);
    camera.setPerspective(45f, 0.1f, 100f)
            .setPosition(2.6f, 2.1f, 3.4f)
            .setTarget(0f, 0f, 0f);
    device.setLight(new Light().setDirection(-0.4f, -1f, -0.55f));
}

public void onFrame(GraphicsDevice device) {
    device.clear(0xff101018, true, true);
    device.setCamera(camera);
    device.draw(cube, material, Matrix4.rotation(angle, 0.35f, 1f, 0.12f));
}

并且它不限于基本几何体。在任何3D工具中制作的二进制 glTF 模型只需一次调用即可加载,并使用自己的纹理进行渲染。这是Khronos BoomBox示例模型在原生Mac目标上的渲染效果:

[LOADING...]

在iOS上,顶点缓冲区是SIMD对齐的,因此数据可直接交给Metal,无需中间复制。承载这一切的 RenderView 是一个常规组件,因此3D视图可以像普通按钮和文本一样,直接嵌入到普通表单中。我们在[这篇教程]中完整介绍了整个API。

核心游戏开发

com.codename1.gaming 在3D层之上构建了一个游戏表面:包含带紧凑 update(dt) 循环的 GameView、精灵、带摄像头的场景、可轮询的输入、低延迟的 SoundPool,以及由内置于核心的Box2D引擎驱动的刚体物理。这是一个物理演示的完整逻辑,每次点击都会掉落一个弹跳球:

$ java
protected void update(double dt) {
    if (getInput().wasPointerPressed()) {
        PhysicsBody body = world.createCircle(
            getInput().getPointerX(), getInput().getPointerY(),
            30, BodyType.DYNAMIC);
        body.setRestitution(0.7f);
        Sprite s = new Sprite(ballImage);
        body.setLinkedSprite(s);
        getScene().add(s);
    }
    world.step((float) dt);
}

无需渲染代码:链接的精灵会跟踪其物理体,场景自行绘制。以下是在模拟器中运行的效果:

[LOADING...]

物理引擎是重新打包在 com.codename1.gaming.physics.box2d 下的 JBox2D,并带有一个惯用的封装,使你的代码保留在屏幕像素中,隐藏了米和翻转的 y 轴。由于关键部分全部是纯 Java,它在每个目标(包括 iOS)上都能不加修改地运行。多年来我们一直拒绝在 Codename One 中添加游戏 API;这篇[文章]解释了是什么改变了我们的想法。

你的Java应用变成原生Windows可执行文件,无需JVM

新的Windows目标通过ParparVM将你的Java/Kotlin字节码翻译成C语言,再用 clang-cl 编译,并链接成一个独立的 Win32 .exe。渲染使用Direct2D,文本使用DirectWrite,网络使用WinHTTP,浏览器组件使用WebView2,而且完全没有JVM:不捆绑、不下载、用户机器上也不要求安装。一个hello world大约4MB,完整的Initializr应用约8MB。一次云端构建即可生成 x64 和 arm64 两种可执行文件。

编辑: 在发布本文后,我们发现二进制文件中内嵌了调试和堆栈展开表。现在我们将这些数据拆分到一个单独的符号文件中(仅用于崩溃符号化),并死代码剥离应用从未到达的代码,从而进一步缩小了体积——上述数字已反映精简后的构建。

需要明确这是什么,因为“Java on Windows”带有旧时的联想:这里没有Swing、没有AWT、没有JavaFX,也没有捆绑的运行时。它是完整编译为原生代码的Codename One框架,其中的一切都能正常工作,包括新的打印API和3D层。以下是同一个应用、同一代码库在Windows上通过Direct2D和DirectWrite渲染的效果:

[LOADING...]

自从上世纪90年代末起,人们就一直在问如何将Java变成真正的 .exe,而现代答案GraalVM是为不同目的设计的工具。架构、历史以及这如何完善Mac目标开启的原生桌面故事,都在[这篇教程]中。

打印与Apple Wallet

两个应用一直需要的平台集成功能。com.codename1.printing 可以在每个端口(包括新的Windows端口)上将PDF或图像交给原生打印对话框:

$ java
if (Printer.isPrintingSupported()) {
    Printer.printPDF(reportPath, result -> {
        if (result.isFailed()) {
            ToastBar.showErrorMessage("Print failed: " + result.getError());
        }
    });
}

现在,卡片发行商可以让用户在Wallet应用中直接将卡片添加到Apple Wallet。iOS构建从构建提示中生成Apple的发行商配置扩展对,你的代码中无需任何原生代码:

$ properties
ios.wallet.extension=true
ios.wallet.appGroup=group.com.mybank.app
ios.wallet.issuerEndpoint=https://api.mybank.com/wallet/provision

你的应用通过新的 WalletExtension API 发布卡片列表,扩展程序则从共享的 App Group 中获取它。这两个功能在[这里]都得到了完整介绍。

幕后:构建云已重建

Codename One 成立于2012年,当时Docker还是“新事物”,我们当时构建的许多基础设施都是初创模式下拼凑起来的。本周工作的一大部分发生在基础设施层面:构建服务器经历了重大的重建和架构调整,而且内部的变化比表面上看起来的更多。

我们提前告诉你,以便你做好准备:如果某个构建行为异常,或者以前不坏的东西现在坏了,请立即通过问题追踪器告诉我们,以便我们快速修复。这一切的目标是更快、更易维护的构建云,而过渡期是最危险的部分。

模拟器用户体验改进

PR #5211 重新设计了模拟器界面,解决了几个长期存在的烦人问题:

  • 慢动作回归。 50倍动画减速开关在多年前被注释掉了;现在它重新出现在“工具”菜单中。
  • 旋转保持缩放。 之前旋转设备会丢弃适应屏幕的缩放因子,迫使每次旋转后都要重新切换缩放。现在所有旋转/缩放路径共享相同的适应逻辑。
  • 独立模拟器是默认设置。 纯设备窗口是开箱即用的默认选项;多面板应用框架仍可通过“单窗口模式”偏好设置获得,显式设置也会被保留。
  • 菜单更合理。 令人困惑的“Simulator”与“Simulate”拆分已消失:设备及其窗口归入一个菜单,模拟设备状态(位置、推送、生物识别、暗色模式)归入另一个菜单,开发者工具归入“工具”菜单。

一个极难追踪的验证问题

PR #5216 修复了构建流水线字节码合规性检查中的一个错误,该错误可能在类被重新编译(源代码未变)时静默丢失API重写。症状是iOS构建在Xcode深处失败,错误信息为未声明的 String.replaceAll 函数,唯一的恢复方法是清除构建目录。现在该检查能检测到重新编译的类并重新运行,而且失败的检查在下次构建时不能再被跳过。如果你之前遇到过这个神秘错误,就是它了。

UIScene应用启动更流畅

PR #5218 修复了iOS应用启动时的黑闪问题,该问题在UIScene默认设置后出现。iOS没有为基于场景的应用渲染启动故事板,导致渲染表面在第一个表单绘制之前一直为空。现在构建会生成现代启动屏幕配置,原生代码用一个与启动屏幕完全匹配的占位图覆盖过渡期,并淡入第一个表单。结果是:点击图标、启动屏幕、无缝过渡、第一个表单,全程无黑屏。如果需要旧行为,可通过 ios.launchPlaceholder=false 构建提示选择退出。

在iOS上固定浏览器外观

iOS上的嵌入式网页视图遵循设备的浅色/深色外观,而自UIScene过渡后,应用范围的plist覆盖不再影响它们。PR #5203 添加了一个组件属性来固定它:

$ java
browser.setProperty(BrowserComponent.BROWSER_PROPERTY_INTERFACE_STYLE, "light");

有效值为 lightdarkauto。在构造函数中调用是安全的;该属性会在原生对等体就绪时应用。

未来亮点

本篇文章之后将连续四天发布四篇教程,每个链接在其对应日期发布:

总结

问题追踪器在这里,目前是联系我们最直接的方式。讨论论坛在这里,构建云控制台在 /console/PlaygroundInitializrSkin Designer 保持不变。

本文 《Native Java Win32, 3D Gaming, Printing and Wallet》 最初发表于 foojay