fuzzyworld

explodorama / files / tools / compose-icons.sh

compose-icons.sh

Blame: the commit that last changed each line · file · history

99869630 2026-10-23 Pavel Safronov1#!/bin/sh
2# Builds the power-up icons that are a known sprite plus a modifier badge in the upper right
3# (user request, 2026-10-22): a green disc with a dark rim, the modifier's white symbol on it.
4# Sources are the Kenney files already in assets/; the results go to assets/composed/ and are
5# committed, so the build needs nothing extra. Needs ImageMagick 7 (`magick`).
6#
7# sh tools/compose-icons.sh
8set -e
9cd "$(dirname "$0")/.."
10K=assets/kenney
11I=assets/kenney-icons/White
12B=assets/kenney-board-icons
13OUT=assets/composed
14mkdir -p "$OUT"
15
16# ink <white icon> <name>: the same shape in the UI's ink colour, for light backgrounds (CSS
17# turns it white again where the background is dark: class "mono" in controls.ts).
52d68b59 2026-10-24 Pavel Safronov18# Always 128 × 128, like every board sprite: LittleJS cuts tiles of 128 out of each texture, and a
19# 100 px Game Icons file (the padlock) made its tile invalid, which crashed the game (2026-10-23).
99869630 2026-10-23 Pavel Safronov20ink() {
52d68b59 2026-10-24 Pavel Safronov21 magick "$1" -resize 128x128 -fill '#353541' -colorize 100 "$OUT/$2.png"
99869630 2026-10-23 Pavel Safronov22 echo " $OUT/$2.png"
23}
24
25# The Move and Wait buttons (user request, 2026-10-22: the astronaut was confusing next to the
26# player). Wait is the hourglass (it was the figure with an ✕ for a while).
27ink "$B/character.png" icon_move
28ink "$B/hourglass.png" icon_wait
29# The fuse in the top bar and its info: the timer of the Fuse +1 badge (user request, 2026-10-22).
30ink "$B/timer_CW_75.png" icon_fuse
31
32# badge <base sprite> <symbol> <name>: 128 × 128, the badge 56 px across at the top right.
33badge() {
34 magick "$1" \
35 \( -size 128x128 xc:none -fill '#2cc987' -stroke '#353541' -strokewidth 6 -draw 'circle 96,32 96,4' \) -composite \
36 \( "$2" -resize 36x36 \) -geometry +78+14 -composite \
37 "$OUT/$3.png"
38 echo " $OUT/$3.png"
39}
40
41badge "$K/bomb.png" "$I/plus.png" powerup_bomb_plus
42badge "$K/bomb.png" "$I/larger.png" powerup_fire_plus
43badge "$K/bomb.png" "$B/timer_CW_75.png" powerup_fuse_plus
44badge "$OUT/icon_move.png" "$I/fastForward.png" powerup_run
45badge "$K/bomb.png" "$I/arrowRight.png" powerup_kick
46badge "$K/bomb.png" "$I/upRight.png" powerup_throw
47badge "$OUT/icon_move.png" "$I/export.png" powerup_teleport
52d68b59 2026-10-24 Pavel Safronov48# Diagonal: the Move figure with four diagonal arrows (a charge until 2026-10-23).
49badge "$OUT/icon_move.png" "$B/arrow_diagonal_cross.png" powerup_diagonal
99869630 2026-10-23 Pavel Safronov50badge "$K/bomb.png" "$I/exclamation.png" powerup_detonator
51badge "$K/block_planks.png" "$I/cross.png" powerup_wall_pass
52badge "$K/bomb.png" "$B/shield.png" powerup_bomb_pass
53badge "$K/fireball.png" "$B/shield.png" powerup_flame_pass
52d68b59 2026-10-24 Pavel Safronov54
55# The charges (user request, 2026-10-23: they work on pickup now). Pierce and Power reuse the
ebcd0a8f 2026-11-02 Pavel Safronov56# Crate Pass and Fire+ icons above; the rest:
52d68b59 2026-10-24 Pavel Safronov57badge "$K/bomb.png" "$B/skull.png" charge_nuke
58ink "$I/locked.png" charge_freeze
59ink "$B/pawns.png" charge_decoy
7f242d36 2026-10-25 Pavel Safronov60# The power-ups and charge added 2026-10-24 (user request): RPG, a bomb with a forward arrow;
61# Proximity alert, a bomb with a warning sign; Slide, the Move figure with a two-way arrow; the
62# ICBM charge, a bomb with a target.
63badge "$K/bomb.png" "$I/forward.png" powerup_rpg
64badge "$K/bomb.png" "$I/warning.png" powerup_proximity
65badge "$OUT/icon_move.png" "$B/arrow_horizontal.png" powerup_slide
66badge "$K/bomb.png" "$I/target.png" charge_icbm
e6bb7c42 2026-10-25 Pavel Safronov67# TNT (user request, 2026-10-25): Fire +2 — the fireball itself with the Fire +1 "larger" badge.
68badge "$K/fireball.png" "$I/larger.png" powerup_tnt
5f066960 2026-10-26 Pavel Safronov69# Acid (PLAN.md §19.4, 2026-10-25): a bomb with a flask.
70badge "$K/bomb.png" "$B/flask_full.png" charge_acid
71
72# A metal crate (PLAN.md §19.3): the strong crate in steel grey.
73magick "$K/block_strong_empty.png" -modulate 165,6 -fill '#9fb4cc' -tint 70 "$OUT/block_metal.png"
74echo " $OUT/block_metal.png"
75
76# Oil (PLAN.md §19.3): a splat from the Splat Pack, near black, with a glossy highlight, so it
77# can't be taken for a stain.
78magick assets/kenney-splat/splat05.png -fill '#2b2631' -colorize 100 \
79 -fill 'rgba(190,200,230,0.55)' -stroke none -draw 'ellipse 52,46 16,7 0,360' \
80 -fill 'rgba(190,200,230,0.35)' -draw 'ellipse 76,70 7,3 0,360' \
81 \( assets/kenney-splat/splat05.png -alpha extract \) -compose copyopacity -composite PNG32:"$OUT/oil.png"
82echo " $OUT/oil.png"
7f242d36 2026-10-25 Pavel Safronov83
05e79f5f 2026-10-27 Pavel Safronov84# Bushes (user request, 2026-10-26): Foliage Sprites' white shaded shapes, tinted green (its shading
85# kept by multiplying) and given the platformer art's dark outline, at 128 × 128. Tall grass tufts,
86# and round canopies; a few of each, so a clump doesn't repeat one picture.
87FOL=assets/kenney-foliage
88foliage() {
89 magick "$FOL/sprite_00$1.png" -colorspace sRGB -type TrueColorAlpha -resize 112x112 -background none -gravity center -extent 128x128 PNG32:"$TMPF/shape.png"
90 magick "$TMPF/shape.png" \( +clone -fill "$2" -colorize 100 \) -compose multiply -composite \
91 \( "$TMPF/shape.png" -alpha extract \) -compose copyopacity -composite PNG32:"$TMPF/tinted.png"
92 magick "$TMPF/tinted.png" \( +clone -alpha extract -morphology dilate disk:5 -blur 0x0.6 -level 40%,60% \
93 -background '#353541' -alpha shape \) +swap -compose over -composite PNG32:"$OUT/$3.png"
94 echo " $OUT/$3.png"
95}
96TMPF=$(mktemp -d)
97foliage 52 '#45c060' grass_a
98foliage 53 '#3db457' grass_b
99foliage 62 '#4cc866' grass_c
100foliage 63 '#41b85b' grass_d
101foliage 90 '#45c060' canopy_a
102foliage 91 '#3db457' canopy_b
103rm -r "$TMPF"
104
52d68b59 2026-10-24 Pavel Safronov105# Shield: the Move figure inside an empty ring (the board-game timer at 0).
106magick "$B/timer_0.png" -fill '#353541' -colorize 100 \
107 \( "$OUT/icon_move.png" -resize 84x84 \) -gravity center -composite \
108 "$OUT/charge_shield.png"
109echo " $OUT/charge_shield.png"
110
6e94f995 2026-10-24 Pavel Safronov111# Developer mode's extra gem (user request, 2026-10-24: a very special gem, so it can't be taken
112# for the level's own): the green gem's body in a rainbow, red to violet from left to right,
113# blended over its own shading in grey (Overlay keeps the facets); the dark outline stays as it is.
114TMP=$(mktemp -d)
115magick "$K/gem_green.png" -modulate 100,0 "$TMP/grey.png"
116magick -size 24x128 xc:'#ff4848' \
117 \( -size 128x20 gradient:'#ff4848'-'#ffd23b' -rotate -90 \) \
118 \( -size 128x20 gradient:'#ffd23b'-'#3bd96b' -rotate -90 \) \
119 \( -size 128x20 gradient:'#3bd96b'-'#3ba8ff' -rotate -90 \) \
120 \( -size 128x20 gradient:'#3ba8ff'-'#c060ff' -rotate -90 \) \
121 -size 24x128 xc:'#c060ff' +append \
122 "$TMP/grey.png" -compose overlay -composite "$TMP/rainbow.png"
123magick "$K/gem_green.png" "$TMP/rainbow.png" \( "$TMP/grey.png" -alpha off -threshold 30% \) -compose over -composite \
124 \( "$K/gem_green.png" -alpha extract \) -compose copyopacity -composite PNG32:"$OUT/gem_rainbow.png"
125rm -r "$TMP"
126echo " $OUT/gem_rainbow.png"
127
52d68b59 2026-10-24 Pavel Safronov128# The app's icons for installing it (user request, 2026-10-23): the bomb on the sky blue, in
129# static/icons/. "Maskable" keeps the bomb inside the middle 60%, so any mask shape fits round it.
130mkdir -p static/icons
131appicon() {
132 magick -size "$1x$1" xc:'#c3e3ff' \( "$K/bomb.png" -resize "$2x$2" \) -gravity center -composite "static/icons/$3.png"
133 echo " static/icons/$3.png"
134}
135appicon 192 150 icon-192
136appicon 512 400 icon-512
137appicon 512 300 icon-maskable-512
138appicon 180 140 apple-touch-icon