Replace the Godot loading screen with the Mat Games mascot on black

This commit is contained in:
enne2
2026-10-11 01:51:46 +02:00
parent 15efd03515
commit 4a04635f41
13 changed files with 471 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d0modgi3t42ij"
path="res://.godot/imported/boot_splash.png-72bba54fc454f72a9370bfb743edf121.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/branding/boot_splash.png"
dest_files=["res://.godot/imported/boot_splash.png-72bba54fc454f72a9370bfb743edf121.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+81
View File
@@ -0,0 +1,81 @@
# Loading screen branding
The stock Godot boot splash (logo plus "GODOT Game engine") is replaced by the
"Mat Games" mascot on a black background. This applies to both surfaces:
- the browser loading screen: the exported `index.png` referenced by
`<img id="status-splash">` in the HTML shell, drawn over `#status`;
- native startup: `application/boot_splash/image` in `project.godot`.
## Asset
`assets/branding/boot_splash.png`, 1024x1218, palette PNG with alpha
(256 colors, 95 alpha levels), about 150 KB. Subject: cartoon zombie head and bust,
unsettling grin, thumbs up, with "Mat Games" below in a phosphor-terminal typeface.
Provenance is recorded in `tools/branding/manifest.json`:
- mascot: generated with `agy_generate` (Antigravity direct API, model
`gemini-3.1-flash-image`) on 2026-10-11 from no third-party source material; the
provider terms do not claim ownership of the output. Raw source kept at
`tools/branding/raw/` with its SHA256. Note that an image generator does not emit
real alpha, so the flat magenta background is keyed out locally;
- lettering: drawn by script, not by the generator, because generated text is
unreliable. Font `tools/branding/fonts/VT323-Regular.ttf`, glyphs of the DEC VT320
terminal, licensed **SIL Open Font License 1.1** (license text kept next to it in
`OFL.txt`, downloaded from the `google/fonts` repository). OFL permits embedding
and redistribution, including commercially, as long as the font is not sold on its
own. SHA256 `cf4de751ada78ceac033dbe16a687742939995b77bc2a052ae17a4957958594d`.
Only the final PNG lives under `assets/`, so the raw source and the font are not
packed into the export (`tools/*` is already excluded by the export preset).
## Composition and keying
`tools/make_boot_splash.py`:
1. measures the background color from the four corners (here 250,4,247);
2. builds an anti-aliased mask by distance from that color (transparent below 55,
opaque above 130) and runs a small median filter;
3. removes magenta spill by subtracting `min(r, b) - g`, which does not harm the
pink tongue or the blue shirt because their red and blue are not both above green;
4. crops to the subject, applies a 50 px fade at the bottom to soften the frame cut
of the generated bust, and scales to 1024 px wide with 40 px side padding;
5. draws the title with VT323 in amber over a blurred glow layer;
6. quantizes to 256 colors (no dither) and writes the PNG plus the manifest.
```sh
python3 tools/make_boot_splash.py tools/branding/raw/agy_generate_20261010234423_0.jpg
```
`--colors 0` keeps 32-bit RGBA if a future artwork needs smoother gradients.
## Godot settings
```ini
boot_splash/bg_color=Color(0, 0, 0, 1)
boot_splash/image="res://assets/branding/boot_splash.png"
boot_splash/show_image=true
boot_splash/use_filter=true
```
The default stretch behavior is kept, so the image is scaled preserving its aspect
ratio; the exported shell confirms the result with the classes
`show-image--true fullsize--true use-filter--true` and `#status` background
`#000000`.
## Verification
- Exported `index.png` has the same 1024x1218 dimensions as the master. It is
re-encoded by the exporter to 32-bit RGBA (about 475 KB), so the bytes are not
identical; composited on black the two images differ by at most 6.4/255 on
0.14% of pixels, all with alpha below 20, i.e. invisible. The release keeps the
150 KB master in the repository and ships a gzip sidecar.
- The exported shell contains no "Game engine" text and the splash image has an
empty `alt`.
- `html/export_icon=false`, so no favicon is exported: the browser tab still shows
a default icon. Using the mascot as favicon is a possible follow-up.
- On a phone in landscape the splash is scaled to fit the height, so the mascot
appears fairly small; a landscape variant (mascot beside the title) would fill
more of the screen if that is wanted.
- All eleven test suites still pass; this change touches no gameplay code.
+12
View File
@@ -1,5 +1,17 @@
# Web build and compressed deployment # Web build and compressed deployment
## Loading screen branding release: 097e6c64b42640ad
See `docs/BRANDING.md`: black boot splash background and the "Mat Games" mascot in
place of the Godot logo; the browser progress bar is restyled to a thin amber line at
the bottom so it no longer crosses the artwork. PCK 4,330,608 bytes; gzip payload total
12,778,745 bytes. A first attempt without the bar fix was deployed as ddba14dd80539f19
and superseded minutes later; both deploys reused the backup name
`index-before-loading.html`, so that file now holds the ddba14dd80539f19 shell.
Releases on the bastion: 9a376a3dbf674069, 7ebf03fe3c88be15, ddba14dd80539f19, 097e6c64b42640ad
(retention policy keeps the live one plus the previous one).
## Aligned office surfaces release: 9a376a3dbf674069 ## Aligned office surfaces release: 9a376a3dbf674069
See `docs/OFFICE-SURFACES.md`: original FIFTIES_WALL14U and FIFTIES_CEIL5; See `docs/OFFICE-SURFACES.md`: original FIFTIES_WALL14U and FIFTIES_CEIL5;
+1 -1
View File
@@ -23,7 +23,7 @@ vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=true vram_texture_compression/for_mobile=true
html/export_icon=false html/export_icon=false
html/custom_html_shell="" html/custom_html_shell=""
html/head_include="<meta name=\"description\" content=\"Zombie Room FPS — prototipo Godot. WASD, mouse, R ricarica.\">" html/head_include="<meta name=\"description\" content=\"Zombie Room FPS — prototipo Godot. WASD, mouse, R ricarica.\"><style>/* La barra di progresso predefinita attraversa la scritta della splash: la rendo una linea ambra sottile in fondo allo schermo. */ #status-progress{appearance:none;-webkit-appearance:none;border:none;height:3px;width:22%;bottom:8px;background:rgba(255,196,64,.15);border-radius:2px} #status-progress::-moz-progress-bar{background:#ffc440} #status-progress::-webkit-progress-bar{background:rgba(255,196,64,.15)} #status-progress::-webkit-progress-value{background:#ffc440}</style>"
html/canvas_resize_policy=2 html/canvas_resize_policy=2
html/focus_canvas_on_start=true html/focus_canvas_on_start=true
progressive_web_app/enabled=false progressive_web_app/enabled=false
+8
View File
@@ -15,6 +15,14 @@ config/description="FPS survival: zombie di Half-Life in una stanza con finestre
run/main_scene="res://scenes/main.tscn" run/main_scene="res://scenes/main.tscn"
config/features=PackedStringArray("4.7", "Forward Plus") config/features=PackedStringArray("4.7", "Forward Plus")
; Schermata di caricamento: sfondo nero e mascotte "Mat Games" al posto del
; logo Godot, sia nell'HTML shell del browser sia all'avvio nativo. L'immagine
; si adatta conservando le proporzioni (comportamento predefinito).
boot_splash/bg_color=Color(0, 0, 0, 1)
boot_splash/image="res://assets/branding/boot_splash.png"
boot_splash/show_image=true
boot_splash/use_filter=true
[animation] [animation]
compatibility/default_parent_skeleton_in_mesh_instance_3d=true compatibility/default_parent_skeleton_in_mesh_instance_3d=true
+93
View File
@@ -0,0 +1,93 @@
Copyright 2011, The VT323 Project Authors (peter.hull@oikoi.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file not shown.
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://dl68sx8ti22de"
path="res://.godot/imported/VT323-Regular.ttf-bf92192fbafeb12c09857a075677f081.fontdata"
[deps]
source_file="res://tools/branding/fonts/VT323-Regular.ttf"
dest_files=["res://.godot/imported/VT323-Regular.ttf-bf92192fbafeb12c09857a075677f081.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=3
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+38
View File
@@ -0,0 +1,38 @@
{
"boot_splash": {
"file": "assets/branding/boot_splash.png",
"size": [
1024,
1218
],
"mode": "P",
"palette_colors": 256,
"sha256": "78524be4ba17ab04afe56d16b00954989457f9af247367f7c4b0f9ed8ea2dec4"
},
"mascot_source": {
"file": "tools/branding/raw/agy_generate_20261010234423_0.jpg",
"sha256": "5929495ff606fbcdd74f52a37304f3b569315bcd1fc0fef812b5fd7689dc1396"
},
"generator": {
"tool": "agy_generate (Antigravity direct API)",
"model": "gemini-3.1-flash-image",
"date": "2026-10-11",
"prompt": "single cartoon zombie head-and-bust mascot, unsettling wide grin, thumbs up, 2D cartoon style with bold outlines, flat magenta chroma-key background, no text and no logo",
"terms_note": "generated from no third-party source material; the provider terms do not claim ownership of the output. The generator emits no real alpha channel, so the background is keyed out locally by this script."
},
"chroma_key": {
"background_rgb": [
250,
4,
247
],
"transparent_below": 55,
"opaque_above": 130
},
"title": {
"text": "Mat Games",
"font": "tools/branding/fonts/VT323-Regular.ttf",
"license": "SIL Open Font License 1.1 (tools/branding/fonts/OFL.txt)"
},
"bottom_fade_px": 50
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 616 KiB

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c04sjmptejokb"
path="res://.godot/imported/agy_generate_20261010234423_0.jpg-9704405d701d25c0ec3a2821bf90d456.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://tools/branding/raw/agy_generate_20261010234423_0.jpg"
dest_files=["res://.godot/imported/agy_generate_20261010234423_0.jpg-9704405d701d25c0ec3a2821bf90d456.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+122
View File
@@ -0,0 +1,122 @@
"""Compose the boot splash: chroma-keyed mascot plus VT323 "Mat Games" lettering.
The raw mascot comes from an image generator on a flat magenta background (generators
do not emit real alpha). This script keys that background to transparency, removes
magenta spill, then draws the title with the OFL-licensed VT323 font and saves a
transparent PNG ready for application/boot_splash/image.
"""
import argparse
import hashlib
import json
import pathlib
from PIL import Image, ImageDraw, ImageFilter, ImageFont
parser = argparse.ArgumentParser()
parser.add_argument('raw', type=pathlib.Path, help='raw generated image (magenta background)')
parser.add_argument('--title', default='Mat Games')
parser.add_argument('--canvas', type=int, default=1024)
parser.add_argument('--title-height', type=int, default=190)
parser.add_argument('--bottom-fade', type=int, default=50,
help='soften the generator frame cut at the bottom of the bust')
parser.add_argument('--colors', type=int, default=256,
help='palette colors for the shipped PNG; 0 keeps 32-bit RGBA')
args = parser.parse_args()
args.raw = args.raw.resolve()
root = pathlib.Path(__file__).resolve().parents[1]
branding = root / 'assets/branding'
branding.mkdir(parents=True, exist_ok=True)
source_tools = root / 'tools/branding'
font_path = source_tools / 'fonts/VT323-Regular.ttf'
# ---------------------------------------------------------------- chroma key
source = Image.open(args.raw).convert('RGB')
corners = [source.getpixel(p) for p in
[(2, 2), (source.width - 3, 2), (2, source.height - 3), (source.width - 3, source.height - 3)]]
background = tuple(sorted(channel)[1] for channel in zip(*corners)) # median per channel
T0, T1 = 55, 130
alpha = Image.new('L', source.size)
spill = Image.new('L', source.size)
pixels = source.load()
alpha_pixels = alpha.load()
spill_pixels = spill.load()
for y in range(source.height):
for x in range(source.width):
r, g, b = pixels[x, y]
distance = ((r - background[0]) ** 2 + (g - background[1]) ** 2 + (b - background[2]) ** 2) ** 0.5
alpha_pixels[x, y] = max(0, min(255, round((distance - T0) / (T1 - T0) * 255)))
# Magenta contamination raises both red and blue above green.
spill_pixels[x, y] = max(0, min(r, b) - g)
mask = alpha.filter(ImageFilter.MedianFilter(3))
fixed = Image.new('RGB', source.size)
fixed_pixels = fixed.load()
for y in range(source.height):
for x in range(source.width):
r, g, b = pixels[x, y]
amount = spill_pixels[x, y]
fixed_pixels[x, y] = (max(0, r - amount), g, max(0, b - amount))
mascot = fixed.convert('RGBA')
mascot.putalpha(mask)
mascot = mascot.crop(mascot.getbbox())
if args.bottom_fade > 0:
fade = min(args.bottom_fade, mascot.height)
ramp = Image.new('L', (1, fade))
for y in range(fade):
ramp.putpixel((0, y), round(255 * (1.0 - y / fade)))
band = mascot.crop((0, mascot.height - fade, mascot.width, mascot.height))
band.putalpha(Image.composite(band.getchannel('A'), Image.new('L', band.size, 0), ramp.resize((1, fade)).resize(band.size, Image.NEAREST)))
mascot.paste(band, (0, mascot.height - fade))
# ---------------------------------------------------------------- composition
canvas_width = args.canvas
title_area = args.title_height
scale = (canvas_width - 2 * 40) / mascot.width
mascot = mascot.resize((round(mascot.width * scale), round(mascot.height * scale)), Image.LANCZOS)
height = mascot.height + title_area
canvas = Image.new('RGBA', (canvas_width, height), (0, 0, 0, 0))
canvas.alpha_composite(mascot, ((canvas_width - mascot.width) // 2, 0))
font_size = int(title_area * 0.95)
font = ImageFont.truetype(str(font_path), font_size)
text = args.title
while font.getbbox(text)[2] - font.getbbox(text)[0] > canvas_width - 60 and font_size > 8:
font_size -= 2
font = ImageFont.truetype(str(font_path), font_size)
box = font.getbbox(text)
text_width = box[2] - box[0]
position = ((canvas_width - text_width) // 2 - box[0], mascot.height + (title_area - box[3]) // 2 - box[1])
glow = Image.new('RGBA', canvas.size, (0, 0, 0, 0))
ImageDraw.Draw(glow).text(position, text, font=font, fill=(255, 150, 20, 190))
glow = glow.filter(ImageFilter.GaussianBlur(9))
canvas.alpha_composite(glow)
ImageDraw.Draw(canvas).text(position, text, font=font, fill=(255, 196, 64, 255))
out = branding / 'boot_splash.png'
if args.colors > 0:
# Flat cartoon art tolerates a palette well; keeps ~95 alpha levels for edges.
canvas = canvas.quantize(colors=args.colors, method=Image.FASTOCTREE, dither=Image.Dither.NONE)
canvas.save(out, optimize=True)
manifest = json.loads((source_tools / 'manifest.json').read_text()) if (source_tools / 'manifest.json').exists() else {}
manifest.update({
'boot_splash': {'file': str(out.relative_to(root)), 'size': list(canvas.size), 'mode': canvas.mode,
'palette_colors': args.colors,
'sha256': hashlib.sha256(out.read_bytes()).hexdigest()},
'mascot_source': {'file': str(args.raw.relative_to(root)),
'sha256': hashlib.sha256(args.raw.read_bytes()).hexdigest()},
'generator': {
'tool': 'agy_generate (Antigravity direct API)',
'model': 'gemini-3.1-flash-image',
'date': '2026-10-11',
'prompt': ('single cartoon zombie head-and-bust mascot, unsettling wide grin, thumbs up, '
'2D cartoon style with bold outlines, flat magenta chroma-key background, '
'no text and no logo'),
'terms_note': ('generated from no third-party source material; the provider terms do not claim '
'ownership of the output. The generator emits no real alpha channel, so the '
'background is keyed out locally by this script.'),
},
'chroma_key': {'background_rgb': list(background), 'transparent_below': T0, 'opaque_above': T1},
'title': {'text': args.title, 'font': 'tools/branding/fonts/VT323-Regular.ttf',
'license': 'SIL Open Font License 1.1 (tools/branding/fonts/OFL.txt)'},
'bottom_fade_px': args.bottom_fade,
})
(source_tools / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n')
print(out, canvas.size, canvas.mode, 'mascot', mascot.size)