@@ -1,5 +1,6 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:arcane_helper_utils/arcane_helper_utils.dart';
|
||||
import 'package:wolf_3d_data_types/wolf_3d_data_types.dart';
|
||||
import 'package:wolf_3d_engine/wolf_3d_engine.dart';
|
||||
|
||||
@@ -222,53 +223,97 @@ class AsciiRasterizer extends Rasterizer {
|
||||
}
|
||||
|
||||
void _drawSimpleHud(WolfEngine engine) {
|
||||
// 1. Clear the HUD area so stray wall characters don't bleed in
|
||||
for (int y = viewHeight; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
_screen[y][x] = ColoredChar(' ', 0xFF000000);
|
||||
// 1. Pull Retro Colors
|
||||
final int vgaStatusBarBlue = ColorPalette.vga32Bit[153];
|
||||
final int vgaPanelDark = ColorPalette.vga32Bit[0];
|
||||
final int white = ColorPalette.vga32Bit[15];
|
||||
final int yellow = ColorPalette.vga32Bit[11];
|
||||
final int red = ColorPalette.vga32Bit[4];
|
||||
|
||||
// 2. Setup Centered Layout
|
||||
// The total width of our standard HUD elements is roughly 120 chars
|
||||
const int hudContentWidth = 120;
|
||||
final int offsetX = ((width - hudContentWidth) ~/ 2).clamp(0, width);
|
||||
|
||||
// 3. Clear HUD Base
|
||||
_fillRect(0, viewHeight, width, height - viewHeight, ' ', vgaStatusBarBlue);
|
||||
_writeString(0, viewHeight, "═" * width, white);
|
||||
|
||||
// 4. Panel Drawing Helper
|
||||
void drawBorderedPanel(int startX, int startY, int w, int h) {
|
||||
_fillRect(startX, startY, w, h, ' ', vgaPanelDark);
|
||||
// Horizontal lines
|
||||
_writeString(startX, startY, "┌${"─" * (w - 2)}┐", white);
|
||||
_writeString(startX, startY + h - 1, "└${"─" * (w - 2)}┘", white);
|
||||
// Vertical sides
|
||||
for (int i = 1; i < h - 1; i++) {
|
||||
_writeString(startX, startY + i, "│", white);
|
||||
_writeString(startX + w - 1, startY + i, "│", white);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Draw a decorative border to separate the 3D view from the HUD
|
||||
int borderColor = 0xFF555555; // Dark Gray
|
||||
for (int x = 0; x < width; x++) {
|
||||
_screen[viewHeight][x] = ColoredChar('=', borderColor);
|
||||
}
|
||||
// 5. Draw the Panels
|
||||
// FLOOR
|
||||
drawBorderedPanel(offsetX + 4, viewHeight + 2, 12, 5);
|
||||
_writeString(offsetX + 7, viewHeight + 3, "FLOOR", white);
|
||||
_writeString(
|
||||
offsetX + 9,
|
||||
viewHeight + 5,
|
||||
engine.activeLevel.name.split(' ').last,
|
||||
white,
|
||||
);
|
||||
|
||||
// 3. Define some clean terminal colors
|
||||
int white = 0xFFFFFFFF;
|
||||
int yellow = 0xFFFFFF55;
|
||||
int red = 0xFFFF5555;
|
||||
// SCORE
|
||||
drawBorderedPanel(offsetX + 18, viewHeight + 2, 24, 5);
|
||||
_writeString(offsetX + 27, viewHeight + 3, "SCORE", white);
|
||||
_writeString(
|
||||
offsetX + 27,
|
||||
viewHeight + 5,
|
||||
engine.player.score.toString().padLeft(6, '0'),
|
||||
white,
|
||||
);
|
||||
|
||||
// Turn health text red if dying
|
||||
int healthColor = engine.player.health > 25 ? white : red;
|
||||
// LIVES
|
||||
drawBorderedPanel(offsetX + 44, viewHeight + 2, 12, 5);
|
||||
_writeString(offsetX + 47, viewHeight + 3, "LIVES", white);
|
||||
_writeString(offsetX + 49, viewHeight + 5, "3", white);
|
||||
|
||||
// Format the strings nicely
|
||||
String score = "SCORE: ${engine.player.score.toString().padLeft(6, '0')}";
|
||||
String health = "HEALTH: ${engine.player.health}%";
|
||||
String ammo = "AMMO: ${engine.player.ammo}";
|
||||
|
||||
int textY = viewHeight + 4; // Center it vertically in the HUD area
|
||||
|
||||
// 4. Print the stats evenly spaced across the bottom
|
||||
_writeString(6, textY, "FLOOR 1", white);
|
||||
_writeString(22, textY, score, white);
|
||||
_writeString(44, textY, "LIVES: 3", white);
|
||||
|
||||
// 5. Reactive ASCII Face
|
||||
String face = " :-) ";
|
||||
// FACE (With Reactive BJ Logic)
|
||||
drawBorderedPanel(offsetX + 58, viewHeight + 1, 14, 7);
|
||||
String face = " :-)";
|
||||
if (engine.player.health <= 0) {
|
||||
face = " X-x ";
|
||||
face = " X-x";
|
||||
} else if (engine.player.damageFlash > 0.1) {
|
||||
face = " :-O"; // Mouth open in pain!
|
||||
} else if (engine.player.health <= 25) {
|
||||
face = " :-( ";
|
||||
face = " :-(";
|
||||
} else if (engine.player.health <= 60) {
|
||||
face = " :-| ";
|
||||
face = " :-|";
|
||||
}
|
||||
_writeString(offsetX + 63, viewHeight + 4, face, yellow);
|
||||
|
||||
_writeString(62, textY, "[$face]", yellow);
|
||||
// HEALTH
|
||||
int healthColor = engine.player.health > 25 ? white : red;
|
||||
drawBorderedPanel(offsetX + 74, viewHeight + 2, 16, 5);
|
||||
_writeString(offsetX + 78, viewHeight + 3, "HEALTH", white);
|
||||
_writeString(
|
||||
offsetX + 79,
|
||||
viewHeight + 5,
|
||||
"${engine.player.health}%",
|
||||
healthColor,
|
||||
);
|
||||
|
||||
_writeString(78, textY, health, healthColor);
|
||||
_writeString(100, textY, ammo, white);
|
||||
// AMMO
|
||||
drawBorderedPanel(offsetX + 92, viewHeight + 2, 12, 5);
|
||||
_writeString(offsetX + 95, viewHeight + 3, "AMMO", white);
|
||||
_writeString(offsetX + 97, viewHeight + 5, "${engine.player.ammo}", white);
|
||||
|
||||
// WEAPON
|
||||
drawBorderedPanel(offsetX + 106, viewHeight + 2, 14, 5);
|
||||
String weapon = engine.player.currentWeapon.type.name.spacePascalCase!
|
||||
.toUpperCase();
|
||||
if (weapon.length > 12) weapon = weapon.substring(0, 12);
|
||||
_writeString(offsetX + 107, viewHeight + 4, weapon, white);
|
||||
}
|
||||
|
||||
void _drawFullVgaHud(WolfEngine engine) {
|
||||
@@ -355,6 +400,19 @@ class AsciiRasterizer extends Rasterizer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to fill a rectangular area with a specific char and background color
|
||||
void _fillRect(int startX, int startY, int w, int h, String char, int color) {
|
||||
for (int dy = 0; dy < h; dy++) {
|
||||
for (int dx = 0; dx < w; dx++) {
|
||||
int x = startX + dx;
|
||||
int y = startY + dy;
|
||||
if (x >= 0 && x < width && y >= 0 && y < height) {
|
||||
_screen[y][x] = ColoredChar(char, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic finalizeFrame() {
|
||||
if (_engine.player.damageFlash > 0.0) {
|
||||
|
||||
@@ -13,6 +13,7 @@ dependencies:
|
||||
wolf_3d_entities: any
|
||||
wolf_3d_data: any
|
||||
wolf_3d_input: any
|
||||
arcane_helper_utils: ^1.4.7
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^6.0.0
|
||||
|
||||
Reference in New Issue
Block a user