AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Battery Optimization

skill-bullish0x-gamestudio-battery-optimization · by bullish0x

Mobile battery optimization techniques including adaptive quality, power-efficient rendering, and background behavior

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add skill-bullish0x-gamestudio-battery-optimization

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bullish0x-gamestudio-battery-optimization)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Battery Optimization? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Mobile Battery Optimization

When to Use

Use this skill when:

  • Optimizing for mobile battery life
  • Implementing adaptive quality systems
  • Managing background behavior
  • Reducing power consumption
  • Handling device thermal throttling
  • Creating power-efficient games

Core Principles

  1. Adaptive Quality: Scale based on power state
  2. Intelligent Throttling: Reduce updates when inactive
  3. Background Pause: Stop rendering when hidden
  4. Thermal Management: Detect and respond to heat
  5. Power Awareness: Monitor battery state
  6. Efficient Rendering: Minimize GPU/CPU usage

Battery Optimization Implementation

1. Power State Management

// power/PowerStateManager.ts
export enum PowerState {
  High = 'high', // Plugged in, full quality
  Normal = 'normal', // Good battery, normal quality
  Low = 'low', // Low battery, reduced quality
  Critical = 'critical', // Very low battery, minimal quality
}

export interface PowerMetrics {
  batteryLevel: number; // 0-1
  isCharging: boolean;
  isSaveModeEnabled: boolean;
  temperature?: number; // Device temperature if available
}

export class PowerStateManager {
  private state: PowerState = PowerState.Normal;
  private metrics: PowerMetrics = {
    batteryLevel: 1,
    isCharging: false,
    isSaveModeEnabled: false,
  };

  private listeners = new Set void>();

  constructor() {
    this.initBatteryAPI();
    this.initVisibilityAPI();
  }

  private async initBatteryAPI(): Promise {
    if ('getBattery' in navigator) {
      try {
        const battery = await (navigator as any).getBattery();

        // Initial state
        this.updateMetrics({
          batteryLevel: battery.level,
          isCharging: battery.charging,
        });

        // Listen for changes
        battery.addEventListener('levelchange', () => {
          this.updateMetrics({ batteryLevel: battery.level });
        });

        battery.addEventListener('chargingchange', () => {
          this.updateMetrics({ isCharging: battery.charging });
        });
      } catch (error) {
        console.warn('Battery API not available:', error);
      }
    }
  }

  private initVisibilityAPI(): void {
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        this.onBackgrounded();
      } else {
        this.onForegrounded();
      }
    });
  }

  private updateMetrics(partial: Partial): void {
    Object.assign(this.metrics, partial);
    this.updatePowerState();
  }

  private updatePowerState(): void {
    const newState = this.calculatePowerState();

    if (newState !== this.state) {
      this.state = newState;
      this.notifyListeners();
    }
  }

  private calculatePowerState(): PowerState {
    // Charging = high performance
    if (this.metrics.isCharging) {
      return PowerState.High;
    }

    // Battery-based states
    if (this.metrics.batteryLevel  void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }
}

2. Adaptive Quality System

// power/AdaptiveQualityManager.ts
export interface QualitySettings {
  targetFPS: number;
  renderScale: number; // 0.5 - 1.0
  shadowQuality: 'none' | 'low' | 'medium' | 'high';
  particleLimit: number;
  drawDistance: number;
  postProcessing: boolean;
  antiAliasing: boolean;
  maxLights: number;
  textureQuality: number; // 0.25 - 1.0
}

export class AdaptiveQualityManager {
  private currentSettings: QualitySettings;

  private presets = new Map([
    [
      PowerState.High,
      {
        targetFPS: 60,
        renderScale: 1.0,
        shadowQuality: 'high',
        particleLimit: 1000,
        drawDistance: 100,
        postProcessing: true,
        antiAliasing: true,
        maxLights: 8,
        textureQuality: 1.0,
      },
    ],
    [
      PowerState.Normal,
      {
        targetFPS: 60,
        renderScale: 0.9,
        shadowQuality: 'medium',
        particleLimit: 500,
        drawDistance: 75,
        postProcessing: true,
        antiAliasing: true,
        maxLights: 4,
        textureQuality: 0.75,
      },
    ],
    [
      PowerState.Low,
      {
        targetFPS: 30,
        renderScale: 0.75,
        shadowQuality: 'low',
        particleLimit: 200,
        drawDistance: 50,
        postProcessing: false,
        antiAliasing: false,
        maxLights: 2,
        textureQuality: 0.5,
      },
    ],
    [
      PowerState.Critical,
      {
        targetFPS: 20,
        renderScale: 0.5,
        shadowQuality: 'none',
        particleLimit: 50,
        drawDistance: 30,
        postProcessing: false,
        antiAliasing: false,
        maxLights: 1,
        textureQuality: 0.25,
      },
    ],
  ]);

  constructor(
    private renderer: THREE.WebGLRenderer,
    private scene: THREE.Scene,
    powerManager: PowerStateManager
  ) {
    this.currentSettings = this.presets.get(PowerState.Normal)!;

    // Listen for power state changes
    powerManager.onStateChange((state) => {
      this.applyPowerState(state);
    });
  }

  private applyPowerState(state: PowerState): void {
    const settings = this.presets.get(state);
    if (!settings) return;

    this.currentSettings = settings;
    this.applySettings();
  }

  private applySettings(): void {
    const s = this.currentSettings;

    // Render scale
    const width = window.innerWidth * s.renderScale;
    const height = window.innerHeight * s.renderScale;
    this.renderer.setSize(width, height, false);

    // Shadows
    this.renderer.shadowMap.enabled = s.shadowQuality !== 'none';
    if (s.shadowQuality !== 'none') {
      this.updateShadowQuality(s.shadowQuality);
    }

    // Post-processing
    // Toggle post-processing composer here

    // Anti-aliasing (requires renderer recreation)
    // Store setting for next renderer creation

    // Update all lights
    this.scene.traverse((obj) => {
      if (obj instanceof THREE.Light) {
        if ((obj as any).shadow) {
          obj.castShadow = s.shadowQuality !== 'none';
        }
      }
    });

    // Limit active lights
    this.limitLights(s.maxLights);

    // Update particle systems
    this.updateParticleLimits(s.particleLimit);

    // Update texture quality
    this.updateTextureQuality(s.textureQuality);
  }

  private updateShadowQuality(quality: 'low' | 'medium' | 'high'): void {
    const sizes = {
      low: 512,
      medium: 1024,
      high: 2048,
    };

    const size = sizes[quality];

    this.scene.traverse((obj) => {
      if (obj instanceof THREE.Light && (obj as any).shadow) {
        const light = obj as THREE.Light & { shadow: THREE.LightShadow };
        light.shadow.mapSize.width = size;
        light.shadow.mapSize.height = size;
        light.shadow.map?.dispose();
        light.shadow.map = null;
      }
    });
  }

  private limitLights(maxLights: number): void {
    let lightCount = 0;

    this.scene.traverse((obj) => {
      if (obj instanceof THREE.Light && !(obj instanceof THREE.AmbientLight)) {
        lightCount++;
        obj.visible = lightCount  {
      if (obj instanceof THREE.Mesh) {
        const materials = Array.isArray(obj.material) ? obj.material : [obj.material];

        for (const material of materials) {
          if (material instanceof THREE.MeshStandardMaterial) {
            // Update texture anisotropy
            const textures = [
              material.map,
              material.normalMap,
              material.roughnessMap,
              material.metalnessMap,
            ];

            for (const texture of textures) {
              if (texture) {
                texture.anisotropy = Math.floor(16 * quality);
              }
            }
          }
        }
      }
    });
  }

  getSettings(): QualitySettings {
    return { ...this.currentSettings };
  }

  setCustomSettings(settings: Partial): void {
    Object.assign(this.currentSettings, settings);
    this.applySettings();
  }
}

3. Frame Rate Throttling

// power/FrameRateThrottle.ts
export class FrameRateThrottle {
  private targetInterval: number;
  private lastFrameTime = 0;
  private accumulator = 0;

  constructor(private targetFPS: number) {
    this.targetInterval = 1000 / targetFPS;
  }

  setTargetFPS(fps: number): void {
    this.targetFPS = fps;
    this.targetInterval = 1000 / fps;
  }

  shouldRender(currentTime: number): boolean {
    const deltaTime = currentTime - this.lastFrameTime;
    this.accumulator += deltaTime;

    if (this.accumulator >= this.targetInterval) {
      this.lastFrameTime = currentTime;
      this.accumulator %= this.targetInterval;
      return true;
    }

    return false;
  }

  reset(): void {
    this.lastFrameTime = 0;
    this.accumulator = 0;
  }
}

// Usage in game loop
export class PowerAwareGameLoop {
  private throttle: FrameRateThrottle;
  private isPaused = false;
  private animationFrameId: number | null = null;

  constructor(
    private renderer: THREE.WebGLRenderer,
    private scene: THREE.Scene,
    private camera: THREE.Camera,
    powerManager: PowerStateManager,
    qualityManager: AdaptiveQualityManager
  ) {
    this.throttle = new FrameRateThrottle(60);

    // Adjust frame rate based on power state
    powerManager.onStateChange((state) => {
      const settings = qualityManager.getSettings();
      this.throttle.setTargetFPS(settings.targetFPS);

      // Pause on critical/background
      if (state === PowerState.Critical) {
        this.pause();
      } else {
        this.resume();
      }
    });

    // Pause when page is hidden
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        this.pause();
      } else {
        this.resume();
      }
    });
  }

  private tick = (currentTime: number): void => {
    if (this.isPaused) return;

    // Throttle based on target FPS
    if (this.throttle.shouldRender(currentTime)) {
      this.update(currentTime);
      this.render();
    }

    this.animationFrameId = requestAnimationFrame(this.tick);
  };

  private update(currentTime: number): void {
    // Update game logic
  }

  private render(): void {
    this.renderer.render(this.scene, this.camera);
  }

  start(): void {
    this.isPaused = false;
    this.throttle.reset();
    this.animationFrameId = requestAnimationFrame(this.tick);
  }

  pause(): void {
    this.isPaused = true;
    if (this.animationFrameId !== null) {
      cancelAnimationFrame(this.animationFrameId);
      this.animationFrameId = null;
    }
  }

  resume(): void {
    if (!this.isPaused) return;
    this.start();
  }

  stop(): void {
    this.pause();
  }
}

4. Thermal Management

// power/ThermalManager.ts
export class ThermalManager {
  private temperature = 0;
  private isThrottling = false;
  private performanceObserver: PerformanceObserver | null = null;

  private readonly THROTTLE_TEMP = 45; // Celsius
  private readonly CRITICAL_TEMP = 50;

  constructor(private qualityManager: AdaptiveQualityManager) {
    this.initPerformanceMonitoring();
  }

  private initPerformanceMonitoring(): void {
    // Monitor frame drops as a proxy for thermal throttling
    if ('PerformanceObserver' in window) {
      try {
        this.performanceObserver = new PerformanceObserver((list) => {
          const entries = list.getEntries();

          // Long frames indicate thermal throttling
          for (const entry of entries) {
            if (entry.duration > 50) {
              // Frame took > 50ms ( {
      this.isThrottling = false;
    }, 5000);
  }

  dispose(): void {
    if (this.performanceObserver) {
      this.performanceObserver.disconnect();
    }
  }
}

5. Battery-Aware Updates

// power/BatteryAwareSystem.ts
export abstract class BatteryAwareSystem extends UpdateSystem {
  protected updateInterval = 0; // 0 = every frame
  protected accumulator = 0;
  protected powerState: PowerState = PowerState.Normal;

  constructor(
    protected powerManager: PowerStateManager,
    baseInterval: number = 0
  ) {
    super();

    this.updateInterval = baseInterval;

    powerManager.onStateChange((state) => {
      this.powerState = state;
      this.onPowerStateChanged(state);
    });
  }

  update(world: World, deltaTime: number): void {
    // Skip updates based on power state
    if (this.shouldSkipUpdate()) {
      return;
    }

    // Interval-based updates
    if (this.updateInterval > 0) {
      this.accumulator += deltaTime;

      if (this.accumulator >= this.updateInterval) {
        this.doUpdate(world, this.accumulator);
        this.accumulator = 0;
      }
    } else {
      this.doUpdate(world, deltaTime);
    }
  }

  protected shouldSkipUpdate(): boolean {
    // Skip on critical power
    return this.powerState === PowerState.Critical;
  }

  protected onPowerStateChanged(state: PowerState): void {
    // Adjust update interval based on power state
    switch (state) {
      case PowerState.High:
        this.updateInterval = 0; // Every frame
        break;
      case PowerState.Normal:
        this.updateInterval = 0;
        break;
      case PowerState.Low:
        this.updateInterval = 0.1; // 10 times per second
        break;
      case PowerState.Critical:
        this.updateInterval = 0.5; // 2 times per second
        break;
    }
  }

  protected abstract doUpdate(world: World, deltaTime: number): void;
}

// Example usage
export class AISystem extends BatteryAwareSystem {
  constructor(powerManager: PowerStateManager) {
    super(powerManager, 0.1); // Base 10 updates/second
  }

  protected doUpdate(world: World, deltaTime: number): void {
    // AI logic here
    const aiEntities = world.query([Transform, AIComponent]);

    aiEntities.iterate((entity, [transform, ai]) => {
      // Update AI
    });
  }

  protected onPowerStateChanged(state: PowerState): void {
    super.onPowerStateChanged(state);

    // Additional AI-specific adjustments
    if (state === PowerState.Low || state === PowerState.Critical) {
      // Reduce AI complexity
      // Limit pathfinding
      // Simplify decision trees
    }
  }
}

Usage Examples

// Example 1: Setup power management
const powerManager = new PowerStateManager();
const qualityManager = new AdaptiveQualityManager(renderer, scene, powerManager);
const thermalManager = new ThermalManager(qualityManager);

// Example 2: Power-aware game loop
const gameLoop = new PowerAwareGameLoop(
  renderer,
  scene,
  camera,
  powerManager,
  qualityManager
);

gameLoop.start();

// Example 3: Monitor battery state
powerManager.onStateChange((state) => {
  console.log(`Power state changed to: ${state}`);

  const metrics = powerManager.getMetrics();
  console.log(`Battery: ${(metrics.batteryLevel * 100).toFixed(0)}%`);
  console.log(`Charging: ${metrics.isCharging}`);
});

// Example 4: Manual quality adjustment
const settings = qualityManager.getSettings();

// User preference override
qualityManager.setCustomSettings({
  targetFPS: 30,
  renderScale: 0.8,
  shadowQuality: 'low',
});

// Example 5: Battery-aware AI system
class EnemyAISystem extends BatteryAwareSystem {
  constructor(powerManager: PowerStateManager) {
    super(powerManager, 0.2); // Update every 200ms
  }

  protected doUpdate(world: World, deltaTime: number): void {
    // Simple AI logic when on battery
    if (this.powerState === PowerState.Low || this.powerState === PowerState.Critical) {
      // Simplified AI
      return;
    }

    // Full AI when charging or normal battery
    // Complex pathfinding, decision making, etc.
  }
}

// Example 6: Adaptive particle system
class PowerAwareParticleSystem {
  private maxParticles: number;

  constructor(powerManager: PowerStateManager) {
    this.maxParticles = 1000;

    powerManager.onStateChange((state) => {
      switch (state) {
        case PowerState.High:
          this.maxParticles = 2000;
          break;
        case PowerState.Normal:
          t

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [bullish0x](https://github.com/bullish0x)
- **Source:** [bullish0x/GameStudio](https://github.com/bullish0x/GameStudio)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.