Initial flame_lua_runtime package

This commit is contained in:
gem
2026-06-07 22:53:58 +08:00
commit 733b2fb798
262 changed files with 28439 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
import 'package:flame/components.dart';
class RuntimeScaleMode {
const RuntimeScaleMode._();
static const fit = 'fit';
static const fill = 'fill';
static const stretch = 'stretch';
static const none = 'none';
static const all = {fit, fill, stretch, none};
static bool isSupported(String value) => all.contains(value);
}
class RuntimeViewportConfig {
const RuntimeViewportConfig({
required this.designWidth,
required this.designHeight,
this.scaleMode = RuntimeScaleMode.fit,
});
final double designWidth;
final double designHeight;
final String scaleMode;
Vector2 get designSize => Vector2(designWidth, designHeight);
}
class RuntimeViewportTransform {
const RuntimeViewportTransform({
required this.x,
required this.y,
required this.width,
required this.height,
required this.scaleX,
required this.scaleY,
required this.scaleMode,
});
final double x;
final double y;
final double width;
final double height;
final double scaleX;
final double scaleY;
final String scaleMode;
Map<String, Object?> toMap() {
return {
'x': x,
'y': y,
'width': width,
'height': height,
'scaleX': scaleX,
'scaleY': scaleY,
'scaleMode': scaleMode,
};
}
}
class RuntimeViewport {
const RuntimeViewport._();
static RuntimeViewportTransform compute({
required Vector2 screenSize,
required RuntimeViewportConfig config,
}) {
final designWidth = config.designWidth;
final designHeight = config.designHeight;
final screenWidth = screenSize.x;
final screenHeight = screenSize.y;
if (designWidth <= 0 || designHeight <= 0) {
throw const FormatException('Runtime viewport design size must be > 0');
}
if (!RuntimeScaleMode.isSupported(config.scaleMode)) {
throw FormatException(
'Runtime viewport scaleMode is unsupported: ${config.scaleMode}',
);
}
final safeScreenWidth = screenWidth <= 0 ? designWidth : screenWidth;
final safeScreenHeight = screenHeight <= 0 ? designHeight : screenHeight;
final scaleX = safeScreenWidth / designWidth;
final scaleY = safeScreenHeight / designHeight;
return switch (config.scaleMode) {
RuntimeScaleMode.fit => _uniform(
designWidth: designWidth,
designHeight: designHeight,
screenWidth: safeScreenWidth,
screenHeight: safeScreenHeight,
scale: scaleX < scaleY ? scaleX : scaleY,
scaleMode: config.scaleMode,
),
RuntimeScaleMode.fill => _uniform(
designWidth: designWidth,
designHeight: designHeight,
screenWidth: safeScreenWidth,
screenHeight: safeScreenHeight,
scale: scaleX > scaleY ? scaleX : scaleY,
scaleMode: config.scaleMode,
),
RuntimeScaleMode.stretch => RuntimeViewportTransform(
x: 0,
y: 0,
width: safeScreenWidth,
height: safeScreenHeight,
scaleX: scaleX,
scaleY: scaleY,
scaleMode: config.scaleMode,
),
RuntimeScaleMode.none => RuntimeViewportTransform(
x: (safeScreenWidth - designWidth) / 2,
y: (safeScreenHeight - designHeight) / 2,
width: designWidth,
height: designHeight,
scaleX: 1,
scaleY: 1,
scaleMode: config.scaleMode,
),
_ => throw FormatException(
'Runtime viewport scaleMode is unsupported: ${config.scaleMode}',
),
};
}
static void apply(
PositionComponent root,
RuntimeViewportTransform transform,
) {
root
..position = Vector2(transform.x, transform.y)
..scale = Vector2(transform.scaleX, transform.scaleY)
..size = Vector2(transform.width, transform.height);
}
static RuntimeViewportTransform _uniform({
required double designWidth,
required double designHeight,
required double screenWidth,
required double screenHeight,
required double scale,
required String scaleMode,
}) {
final width = designWidth * scale;
final height = designHeight * scale;
return RuntimeViewportTransform(
x: (screenWidth - width) / 2,
y: (screenHeight - height) / 2,
width: width,
height: height,
scaleX: scale,
scaleY: scale,
scaleMode: scaleMode,
);
}
}