Fixed HUD background rendering
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,91 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:wolf_3d_engine/wolf_3d_engine.dart';
|
||||
|
||||
class Hud extends StatelessWidget {
|
||||
final Player player;
|
||||
|
||||
const Hud({super.key, required this.player});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// We'll give the HUD a fixed height relative to the screen
|
||||
return Container(
|
||||
height: 100,
|
||||
color: const Color(0xFF323232), // Classic dark grey status bar
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_buildStatColumn("FLOOR", "1"),
|
||||
_buildStatColumn("SCORE", "${player.score}"),
|
||||
_buildStatColumn("LIVES", "3"),
|
||||
_buildFace(),
|
||||
_buildStatColumn(
|
||||
"HEALTH",
|
||||
"${player.health}%",
|
||||
color: _getHealthColor(),
|
||||
),
|
||||
_buildStatColumn("AMMO", "${player.ammo}"),
|
||||
_buildWeaponIcon(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatColumn(
|
||||
String label,
|
||||
String value, {
|
||||
Color color = Colors.white,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
color: Colors.red,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(color: color, fontSize: 20, fontFamily: 'monospace'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFace() {
|
||||
// For now, we'll use a simple icon. Later we can map VSWAP indices
|
||||
// for BJ Blazkowicz's face based on health percentage.
|
||||
return Container(
|
||||
width: 60,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueGrey[800],
|
||||
border: Border.all(color: Colors.grey, width: 2),
|
||||
),
|
||||
child: const Icon(Icons.face, color: Colors.white, size: 40),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildWeaponIcon() {
|
||||
IconData weaponIcon = Icons.horizontal_rule; // Default Knife/Pistol
|
||||
if (player.hasChainGun) weaponIcon = Icons.reorder;
|
||||
if (player.hasMachineGun) weaponIcon = Icons.view_headline;
|
||||
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text("WEAPON", style: TextStyle(color: Colors.red, fontSize: 10)),
|
||||
Icon(weaponIcon, color: Colors.white),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Color _getHealthColor() {
|
||||
if (player.health > 50) return Colors.white;
|
||||
if (player.health > 25) return Colors.orange;
|
||||
return Colors.red;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:wolf_3d_data_types/wolf_3d_data_types.dart';
|
||||
|
||||
class WeaponPainter extends CustomPainter {
|
||||
final Sprite? sprite;
|
||||
|
||||
// Initialize a reusable Paint object and disable anti-aliasing to keep the
|
||||
// pixels perfectly sharp and chunky.
|
||||
final Paint _paint = Paint()
|
||||
..isAntiAlias = false
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
WeaponPainter({required this.sprite});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
if (sprite == null) return;
|
||||
|
||||
// Calculate width and height separately in case the container isn't a
|
||||
// perfect square
|
||||
double pixelWidth = size.width / 64;
|
||||
double pixelHeight = size.height / 64;
|
||||
|
||||
for (int x = 0; x < 64; x++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
int colorByte = sprite!.pixels[x * 64 + y];
|
||||
|
||||
if (colorByte != 255) {
|
||||
// 255 is our transparent magenta
|
||||
_paint.color = Color(ColorPalette.vga32Bit[colorByte]);
|
||||
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
x * pixelWidth,
|
||||
y * pixelHeight,
|
||||
// Add a tiny 0.5 overlap to completely eliminate visual seams
|
||||
pixelWidth + 0.5,
|
||||
pixelHeight + 0.5,
|
||||
),
|
||||
_paint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant WeaponPainter oldDelegate) {
|
||||
// ONLY repaint if the actual animation frame (sprite) has changed!
|
||||
// This saves massive amounts of CPU when the player is just walking around.
|
||||
return oldDelegate.sprite != sprite;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import 'package:flutter/scheduler.dart';
|
||||
import 'package:wolf_3d_data_types/wolf_3d_data_types.dart';
|
||||
import 'package:wolf_3d_engine/wolf_3d_engine.dart';
|
||||
import 'package:wolf_3d_input/wolf_3d_input.dart';
|
||||
import 'package:wolf_3d_renderer/hud.dart';
|
||||
|
||||
class WolfRenderer extends StatefulWidget {
|
||||
const WolfRenderer(
|
||||
@@ -123,7 +122,7 @@ class _WolfRendererState extends State<WolfRenderer>
|
||||
builder: (context, constraints) {
|
||||
return Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 10,
|
||||
aspectRatio: 320 / 200,
|
||||
child: CustomPaint(
|
||||
size: Size(constraints.maxWidth, constraints.maxHeight),
|
||||
painter: BufferPainter(_renderedFrame),
|
||||
@@ -133,7 +132,6 @@ class _WolfRendererState extends State<WolfRenderer>
|
||||
},
|
||||
),
|
||||
),
|
||||
Hud(player: engine.player),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user