P12.2: candy HUD & win/lose banner restyle (sx / iOS)
Restyle the code-drawn UI toward the candy look — colours, corner-rounding and glossy feel only; no rect geometry moves. - HUD: grape candy card with a glossy top sheen, a bright rounded rim and warm cream text on a soft purple shadow (was a flat dark translucent panel). - Banner panel: grape candy fill under a sheen + bright rim, rounder corners. - Titles: celebratory candy gold YOU WIN! / punchy coral OUT OF MOVES, each on a tinted drop shadow for pop. - PLAY AGAIN: bubblegum candy button with a glossy sheen, bright rim and a darker bevel lip for a 3D candy edge. BannerLayout rects (panel/title/button) and the restart hit-test are untouched, so tests/banner_layout still passes. Refresh the p4_hud / p7_win / p7_lose goldens.
This commit is contained in:
111
board_view.sx
111
board_view.sx
@@ -46,24 +46,42 @@ SELECT_RIM :: Color.{ r = 255, g = 234, b = 92, a = 255 }; // bright candy
|
||||
SELECT_RIM_HI :: Color.{ r = 255, g = 255, b = 232, a = 220 }; // glossy inner highlight ring
|
||||
SELECT_GLOSS :: Color.{ r = 255, g = 255, b = 255, a = 96 }; // wet sheen on the selected gem
|
||||
|
||||
// HUD: a translucent card with the score and remaining moves, in the loaded Lato
|
||||
// font. Placed in the empty band above the centered grid (inside the safe area).
|
||||
HUD_FONT :f32: 34.0;
|
||||
HUD_PAD :f32: 14.0;
|
||||
HUD_LINE_GAP :f32: 6.0;
|
||||
HUD_TEXT :: Color.{ r = 255, g = 255, b = 255, a = 255 };
|
||||
HUD_PANEL :: Color.{ r = 12, g = 14, b = 22, a = 185 };
|
||||
// HUD (P12.2): a glossy candy card with the score and remaining moves, in the
|
||||
// loaded Lato font. Placed in the empty band above the centered grid (inside the
|
||||
// safe area). The fill is a bright grape candy, lifted by a translucent top sheen
|
||||
// and a bright rounded rim; cream text rides a soft purple shadow for punch.
|
||||
HUD_FONT :f32: 34.0;
|
||||
HUD_PAD :f32: 14.0;
|
||||
HUD_LINE_GAP :f32: 6.0;
|
||||
HUD_RADIUS :f32: 20.0;
|
||||
HUD_TEXT :: Color.{ r = 255, g = 252, b = 245, a = 255 }; // warm cream text
|
||||
HUD_TEXT_SH :: Color.{ r = 56, g = 18, b = 80, a = 150 }; // soft purple text shadow
|
||||
HUD_PANEL :: Color.{ r = 92, g = 46, b = 150, a = 224 }; // bright grape candy fill
|
||||
HUD_PANEL_HI :: Color.{ r = 196, g = 138, b = 240, a = 92 }; // glossy top sheen
|
||||
HUD_PANEL_RIM:: Color.{ r = 236, g = 204, b = 255, a = 150 }; // bright candy rim
|
||||
|
||||
// Win/lose banner (P7.2): a dim over the board, an opaque panel, the win/lose
|
||||
// headline, and a restart button. Built from text + rects only — the engine's
|
||||
// image path can't tint/fade at draw time (issue 0002), but rects and text DO
|
||||
// honour colour + alpha, so the whole overlay is drawn with them.
|
||||
BANNER_DIM :: Color.{ r = 6, g = 8, b = 14, a = 188 };
|
||||
BANNER_PANEL :: Color.{ r = 20, g = 24, b = 38, a = 240 };
|
||||
BANNER_WIN_TEXT :: Color.{ r = 120, g = 240, b = 150, a = 255 };
|
||||
BANNER_LOSE_TEXT :: Color.{ r = 255, g = 120, b = 110, a = 255 };
|
||||
BANNER_BTN :: Color.{ r = 64, g = 132, b = 224, a = 255 };
|
||||
BANNER_BTN_TEXT :: Color.{ r = 255, g = 255, b = 255, a = 255 };
|
||||
// Win/lose banner (P12.2): a warm dim over the board, a glossy candy panel, the
|
||||
// win/lose headline, and a playful restart button. Built from text + rects only —
|
||||
// the engine's image path can't tint/fade at draw time (issue 0002), but rects and
|
||||
// text DO honour colour + alpha, so the whole overlay is drawn with them. Each
|
||||
// candy surface is a fill + a top sheen + a bright rounded rim; titles and the
|
||||
// button label ride a tinted drop shadow so they pop off the panel.
|
||||
BANNER_DIM :: Color.{ r = 26, g = 10, b = 44, a = 184 }; // warm purple dim
|
||||
BANNER_PANEL :: Color.{ r = 96, g = 50, b = 156, a = 244 }; // grape candy panel
|
||||
BANNER_PANEL_HI :: Color.{ r = 198, g = 140, b = 242, a = 110 }; // glossy panel sheen
|
||||
BANNER_PANEL_RIM :: Color.{ r = 240, g = 208, b = 255, a = 168 }; // bright panel rim
|
||||
BANNER_WIN_TEXT :: Color.{ r = 255, g = 220, b = 96, a = 255 }; // celebratory candy gold
|
||||
BANNER_WIN_SH :: Color.{ r = 120, g = 56, b = 8, a = 220 }; // warm amber shadow
|
||||
BANNER_LOSE_TEXT :: Color.{ r = 255, g = 104, b = 104, a = 255 }; // punchy candy coral
|
||||
BANNER_LOSE_SH :: Color.{ r = 92, g = 14, b = 32, a = 220 }; // deep berry shadow
|
||||
BANNER_BTN :: Color.{ r = 255, g = 120, b = 178, a = 255 }; // bubblegum candy CTA
|
||||
BANNER_BTN_HI :: Color.{ r = 255, g = 198, b = 222, a = 150 }; // glossy button sheen
|
||||
BANNER_BTN_RIM :: Color.{ r = 255, g = 226, b = 240, a = 184 }; // bright button rim
|
||||
BANNER_BTN_SHADE :: Color.{ r = 198, g = 52, b = 120, a = 210 }; // darker bevel lip (3D)
|
||||
BANNER_BTN_TEXT :: Color.{ r = 255, g = 255, b = 255, a = 255 };
|
||||
BANNER_BTN_TEXT_SH:: Color.{ r = 120, g = 20, b = 64, a = 200 }; // button label shadow
|
||||
BANNER_PANEL_RADIUS :f32: 24.0;
|
||||
BANNER_BTN_RADIUS :f32: 16.0;
|
||||
BANNER_TITLE_FONT :f32: 52.0;
|
||||
BANNER_BTN_FONT :f32: 30.0;
|
||||
|
||||
@@ -537,25 +555,38 @@ BoardView :: struct {
|
||||
ctx.add_rect(self.layout.grid_frame(), BANNER_DIM);
|
||||
|
||||
bl := self.layout.banner();
|
||||
ctx.add_rounded_rect(bl.panel, BANNER_PANEL, 18.0);
|
||||
|
||||
// Candy panel: grape fill under a glossy top sheen and a bright rounded rim.
|
||||
// Geometry is the shared bl.panel — only colour / rounding / gloss change.
|
||||
ctx.add_rounded_rect(bl.panel, BANNER_PANEL, BANNER_PANEL_RADIUS);
|
||||
ctx.add_rounded_rect(top_sheen(bl.panel, 0.42, BANNER_PANEL_RADIUS * 0.6), BANNER_PANEL_HI, BANNER_PANEL_RADIUS * 0.8);
|
||||
prim := max(2.0, BANNER_PANEL_RADIUS * 0.12);
|
||||
ctx.add_stroked_rect(bl.panel, BANNER_PANEL_RIM, BANNER_PANEL_RIM, prim, BANNER_PANEL_RADIUS);
|
||||
|
||||
title := if status == .won then "YOU WIN!" else "OUT OF MOVES";
|
||||
tcol := if status == .won then BANNER_WIN_TEXT else BANNER_LOSE_TEXT;
|
||||
tsh := if status == .won then BANNER_WIN_SH else BANNER_LOSE_SH;
|
||||
tfont := fit_font(title, BANNER_TITLE_FONT, bl.title.size.width);
|
||||
tsz := measure_text(title, tfont);
|
||||
ctx.add_text(
|
||||
Frame.make(bl.title.mid_x() - tsz.width * 0.5, bl.title.mid_y() - tsz.height * 0.5, tsz.width, tsz.height),
|
||||
title, tfont, tcol
|
||||
);
|
||||
tfr := Frame.make(bl.title.mid_x() - tsz.width * 0.5, bl.title.mid_y() - tsz.height * 0.5, tsz.width, tsz.height);
|
||||
ctx.add_text(Frame.make(tfr.origin.x + 2.0, tfr.origin.y + 3.0, tfr.size.width, tfr.size.height), title, tfont, tsh);
|
||||
ctx.add_text(tfr, title, tfont, tcol);
|
||||
|
||||
// Candy button: a darker bevel lip peeks under the bubblegum fill for a 3D
|
||||
// candy edge, lifted by a glossy sheen and a bright rim. The fill / hit rect
|
||||
// is the shared bl.button, so the restart hit-test is byte-for-byte unchanged.
|
||||
ctx.add_rounded_rect(Frame.make(bl.button.origin.x, bl.button.origin.y + 3.0, bl.button.size.width, bl.button.size.height), BANNER_BTN_SHADE, BANNER_BTN_RADIUS);
|
||||
ctx.add_rounded_rect(bl.button, BANNER_BTN, BANNER_BTN_RADIUS);
|
||||
ctx.add_rounded_rect(top_sheen(bl.button, 0.46, BANNER_BTN_RADIUS * 0.5), BANNER_BTN_HI, BANNER_BTN_RADIUS * 0.8);
|
||||
brim := max(2.0, BANNER_BTN_RADIUS * 0.14);
|
||||
ctx.add_stroked_rect(bl.button, BANNER_BTN_RIM, BANNER_BTN_RIM, brim, BANNER_BTN_RADIUS);
|
||||
|
||||
ctx.add_rounded_rect(bl.button, BANNER_BTN, 12.0);
|
||||
btxt := "PLAY AGAIN";
|
||||
bfont := fit_font(btxt, BANNER_BTN_FONT, bl.button.size.width * 0.86);
|
||||
bsz := measure_text(btxt, bfont);
|
||||
ctx.add_text(
|
||||
Frame.make(bl.button.mid_x() - bsz.width * 0.5, bl.button.mid_y() - bsz.height * 0.5, bsz.width, bsz.height),
|
||||
btxt, bfont, BANNER_BTN_TEXT
|
||||
);
|
||||
bfr := Frame.make(bl.button.mid_x() - bsz.width * 0.5, bl.button.mid_y() - bsz.height * 0.5, bsz.width, bsz.height);
|
||||
ctx.add_text(Frame.make(bfr.origin.x + 1.5, bfr.origin.y + 2.0, bfr.size.width, bfr.size.height), btxt, bfont, BANNER_BTN_TEXT_SH);
|
||||
ctx.add_text(bfr, btxt, bfont, BANNER_BTN_TEXT);
|
||||
}
|
||||
|
||||
// Restart action behind the banner's button: reseed the SAME starting level
|
||||
@@ -583,6 +614,13 @@ fit_font :: (text: string, base: f32, max_w: f32) -> f32 {
|
||||
base * max_w / sz.width
|
||||
}
|
||||
|
||||
// A rounded rect covering the top `frac` of `f`, inset by `pad` on the sides and
|
||||
// top — the glossy candy sheen sat over a panel/button fill. The renderer has no
|
||||
// gradient, so a single brighter translucent cap fakes the gloss.
|
||||
top_sheen :: (f: Frame, frac: f32, pad: f32) -> Frame {
|
||||
Frame.make(f.origin.x + pad, f.origin.y + pad, f.size.width - pad * 2.0, f.size.height * frac)
|
||||
}
|
||||
|
||||
impl View for BoardView {
|
||||
size_that_fits :: (self: *BoardView, proposal: ProposedSize) -> Size {
|
||||
Size.{ width = proposal.width ?? 0.0, height = proposal.height ?? 0.0 }
|
||||
@@ -738,11 +776,24 @@ render_hud :: (ctx: *RenderContext, board: *Board, avail: Frame) {
|
||||
panel_h := score_sz.height + HUD_LINE_GAP + moves_sz.height + HUD_PAD * 2.0;
|
||||
panel_x := avail.origin.x + (avail.size.width - panel_w) * 0.5;
|
||||
panel_y := avail.origin.y + HUD_PAD;
|
||||
ctx.add_rounded_rect(Frame.make(panel_x, panel_y, panel_w, panel_h), HUD_PANEL, 12.0);
|
||||
panel := Frame.make(panel_x, panel_y, panel_w, panel_h);
|
||||
|
||||
// Candy card: grape fill, a glossy top sheen, then a bright rounded rim.
|
||||
ctx.add_rounded_rect(panel, HUD_PANEL, HUD_RADIUS);
|
||||
ctx.add_rounded_rect(top_sheen(panel, 0.46, HUD_RADIUS * 0.5), HUD_PANEL_HI, HUD_RADIUS * 0.8);
|
||||
rim := max(2.0, HUD_RADIUS * 0.12);
|
||||
ctx.add_stroked_rect(panel, HUD_PANEL_RIM, HUD_PANEL_RIM, rim, HUD_RADIUS);
|
||||
|
||||
tx := panel_x + HUD_PAD;
|
||||
ty := panel_y + HUD_PAD;
|
||||
ctx.add_text(Frame.make(tx, ty, score_sz.width, score_sz.height), score_str, HUD_FONT, HUD_TEXT);
|
||||
hud_line(ctx, Frame.make(tx, ty, score_sz.width, score_sz.height), score_str);
|
||||
ty += score_sz.height + HUD_LINE_GAP;
|
||||
ctx.add_text(Frame.make(tx, ty, moves_sz.width, moves_sz.height), moves_str, HUD_FONT, HUD_TEXT);
|
||||
hud_line(ctx, Frame.make(tx, ty, moves_sz.width, moves_sz.height), moves_str);
|
||||
}
|
||||
|
||||
// One HUD text row: a soft purple shadow under the warm cream text, so the line
|
||||
// stays legible over the grape card. Geometry is the caller's row frame.
|
||||
hud_line :: (ctx: *RenderContext, f: Frame, text: string) {
|
||||
ctx.add_text(Frame.make(f.origin.x + 1.5, f.origin.y + 2.0, f.size.width, f.size.height), text, HUD_FONT, HUD_TEXT_SH);
|
||||
ctx.add_text(f, text, HUD_FONT, HUD_TEXT);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.2 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.4 MiB |
Reference in New Issue
Block a user