257 lines
8.1 KiB
Java
257 lines
8.1 KiB
Java
/*
|
|
* libgdx-scene2d-ui.java - LibGDX scene2d.ui Integration with Compose
|
|
*
|
|
* Production-ready example demonstrating:
|
|
* - LibGDX scene2d.ui for game interfaces
|
|
* - Compose interoperability patterns
|
|
* - DDA 3.0 enemy AI heuristic adjustment
|
|
* - Accessibility for game UI
|
|
* - Emergent gameplay through UI feedback
|
|
*
|
|
* © 2026 - Agent Guardrails Template
|
|
*/
|
|
|
|
package com.agentguardrails.composeui;
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.*;
|
|
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
|
import com.badlogic.gdx.graphics.Color;
|
|
import com.badlogic.gdx.math.Vector2;
|
|
import com.badlogic.gdx.utils.Array;
|
|
import androidx.game.core.DDAManager;
|
|
import androidx.game.accessibility.ColorblindnessMode;
|
|
import androidx.game.spatial.VolumetricRenderer;
|
|
|
|
/**
|
|
* LibGDX scene2d.ui integration layer for Jetpack Compose
|
|
* Enables traditional game UI widgets alongside Compose declarative patterns
|
|
*/
|
|
public class LibGDXScene2DUI {
|
|
|
|
private final Skin skin;
|
|
private final DDAManager ddaManager;
|
|
private final ColorblindnessMode colorblindnessMode;
|
|
private final VolumetricRenderer volumetricRenderer;
|
|
|
|
/**
|
|
* Constructor initializes LibGDX skin with Material 3 tokens
|
|
*/
|
|
public LibGDXScene2DUI(Skin skin, DDAManager ddaManager) {
|
|
this.skin = skin;
|
|
this.ddaManager = ddaManager;
|
|
this.colorblindnessMode = ColorblindnessMode.DEUTERANOPSY; // Protanopia/Deuteranopia support
|
|
this.volumetricRenderer = new VolumetricRenderer();
|
|
}
|
|
|
|
/**
|
|
* Creates game HUD with scene2d.ui widgets
|
|
* Integrates core loop: Action → Reward → Upgrade
|
|
*/
|
|
public Table createGameHUD() {
|
|
Table hudTable = new Table(skin);
|
|
|
|
// Action Phase: Combat stats
|
|
hudTable.add(createCombatPanel()).width(200).height(100);
|
|
|
|
// Reward Phase: Loot notification
|
|
hudTable.add(createLootNotification()).width(150).height(80);
|
|
|
|
// Upgrade Phase: XP bar
|
|
hudTable.add(createXPBar()).width(200).height(40);
|
|
|
|
// Accessibility: WCAG 3.0+ contrast ratios
|
|
applyAccessibilityStyles(hudTable);
|
|
|
|
return hudTable;
|
|
}
|
|
|
|
/**
|
|
* Combat panel with DDA 3.0 visual adaptation
|
|
* Enemy AI heuristic adjusts UI opacity based on player stress
|
|
*/
|
|
private TextButton createCombatPanel() {
|
|
TextButton combatButton = new TextButton("COMBAT", skin);
|
|
|
|
// DDA 3.0: Adjust opacity based on difficulty tier
|
|
float opacityFactor = ddaManager.getUIOpacityFactor();
|
|
combatButton.setColor(new Color(1, 1, 1, opacityFactor));
|
|
|
|
// Colorblindness independence: shape + icon redundancy
|
|
TextureRegionDrawable icon = skin.getDrawable("combat-icon");
|
|
combatButton.getImage().setDrawable(icon);
|
|
|
|
// Haptic feedback on press
|
|
combatButton.addListener(new InteractionListener() {
|
|
@Override
|
|
public void clicked(InputEvent event, float x, float y) {
|
|
HapticProfiles.apply(HapticProfile.COMBAT_TRIGGER);
|
|
}
|
|
});
|
|
|
|
return combatButton;
|
|
}
|
|
|
|
/**
|
|
* Loot notification with transparent RNG display
|
|
* Ethical engagement: no obfuscated drop rates
|
|
*/
|
|
private Dialog createLootNotification() {
|
|
Dialog lootDialog = new Dialog("Loot", skin);
|
|
|
|
// Transparent loot table display
|
|
lootDialog.text("Drop Rate: 2.5%");
|
|
lootDialog.text("Pity Timer: 3/10");
|
|
|
|
// Volumetric UI: Z-depth preview for legendary items
|
|
if (lootTable.isLegendary()) {
|
|
volumetricRenderer.setDepth(0.5f); // Z-axis parallax
|
|
lootDialog.image(skin.getDrawable("legendary-glow"));
|
|
}
|
|
|
|
return lootDialog;
|
|
}
|
|
|
|
/**
|
|
* XP bar with emergent gameplay feedback
|
|
* Visual particle effects on level-up
|
|
*/
|
|
private ProgressBar createXPBar() {
|
|
ProgressBar xpBar = new ProgressBar(0, 100, false, skin);
|
|
|
|
// Emergent gameplay: particle burst on level-up
|
|
xpBar.addListener(new ChangeListener() {
|
|
@Override
|
|
public void changed(ChangeEvent event) {
|
|
if (xpBar.getValue() == 100) {
|
|
triggerEmergentParticleEffect();
|
|
HapticProfiles.apply(HapticProfile.LEVEL_UP);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Spatial computing: XR parallax scrolling
|
|
xpBar.setParallaxFactor(0.2f);
|
|
|
|
return xpBar;
|
|
}
|
|
|
|
/**
|
|
* Applies WCAG 3.0+ accessibility styles
|
|
* Minimum contrast ratio: 4.5:1 (Level AA)
|
|
*/
|
|
private void applyAccessibilityStyles(Table table) {
|
|
// High contrast mode for colorblindness
|
|
if (colorblindnessMode != ColorblindnessMode.NONE) {
|
|
table.setColor(Color.WHITE);
|
|
table.setBackground(skin.getDrawable("high-contrast-border"));
|
|
}
|
|
|
|
// Eye-tracking support: dwell-based selection
|
|
table.setDwellThreshold(150f); // 150ms for eye-tracking selection
|
|
}
|
|
|
|
/**
|
|
* Creates skill tree with LibGDX scene2d.ui
|
|
* Upgrade phase of core loop
|
|
*/
|
|
public Tree createSkillTree() {
|
|
Tree skillTree = new Tree(skin);
|
|
|
|
// Root node: Core ability
|
|
Node root = new Node("Core Ability", skin);
|
|
skillTree.add(root);
|
|
|
|
// Child nodes: Specialized skills
|
|
Array<Node> children = new Array<>();
|
|
children.add(new Node("Fire Mastery", skin));
|
|
children.add(new Node("Ice Mastery", skin));
|
|
children.add(new Node("Lightning Mastery", skin));
|
|
|
|
root.add(children);
|
|
|
|
// Z-depth for spatial computing
|
|
skillTree.setDepthFactor(0.3f);
|
|
|
|
return skillTree;
|
|
}
|
|
|
|
/**
|
|
* DDA 3.0 enemy AI heuristic adjustment
|
|
* UI adapts visual complexity based on player performance
|
|
*/
|
|
public void adjustForDDATier(DDAManager.Tier tier) {
|
|
switch (tier) {
|
|
case DIFFICULT:
|
|
// Reduce UI complexity for stressed players
|
|
skin.getDrawables().forEach(d -> d.setOpacity(0.7f));
|
|
break;
|
|
case NORMAL:
|
|
// Standard UI presentation
|
|
skin.getDrawables().forEach(d -> d.setOpacity(1.0f));
|
|
break;
|
|
case RELAXED:
|
|
// Enhanced visual feedback for engagement
|
|
skin.getDrawables().forEach(d -> d.setOpacity(1.2f));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Triggers emergent particle effect for level-up
|
|
* Visual celebration reinforces core loop reward phase
|
|
*/
|
|
private void triggerEmergentParticleEffect() {
|
|
// LibGDX particle system integration
|
|
ParticleEffect levelUpEffect = new ParticleEffect();
|
|
levelUpEffect.loadEffect("particles/level-up");
|
|
levelUpEffect.start();
|
|
levelUpEffect.draw();
|
|
}
|
|
|
|
/**
|
|
* Creates inventory panel with volumetric UI
|
|
* Z-depth parallax for item previews
|
|
*/
|
|
public ScrollPane createInventoryPanel() {
|
|
Table inventoryTable = new Table(skin);
|
|
|
|
// Volumetric rendering for item cards
|
|
inventoryTable.setVolumetricDepth(0.5f);
|
|
|
|
// GPU instancing for UI elements (batch rendering)
|
|
inventoryTable.setGPUInstancing(true);
|
|
|
|
return new ScrollPane(inventoryTable, skin);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* LibGDX scene2d.ui skin loader with Material 3 tokens
|
|
*/
|
|
class SkinLoader {
|
|
|
|
/**
|
|
* Loads skin with Material 3 design tokens
|
|
* Dynamic color extraction from game theme
|
|
*/
|
|
public static Skin loadMaterial3Skin() {
|
|
Skin skin = new Skin();
|
|
|
|
// Material 3 color tokens
|
|
skin.add("primary", new Color(0x3B82F6));
|
|
skin.add("secondary", new Color(0x10B981));
|
|
skin.add("surface", new Color(0x1A1A2E));
|
|
|
|
// Material 3 typography scale
|
|
skin.add("display", FontScale.DISPLAY);
|
|
skin.add("headline", FontScale.HEADLINE);
|
|
skin.add("body", FontScale.BODY);
|
|
|
|
// Material 3 elevation tokens
|
|
skin.add("elevation-1", new TextureRegionDrawable("elevation1"));
|
|
skin.add("elevation-2", new TextureRegionDrawable("elevation2"));
|
|
skin.add("elevation-3", new TextureRegionDrawable("elevation3"));
|
|
|
|
return skin;
|
|
}
|
|
} |