Files
clod/generate_textures.py
2026-02-15 10:50:17 +01:00

220 lines
6.9 KiB
Python

"""Generate clod.png and clod_eyes.png textures for the Clod entity."""
from PIL import Image, ImageDraw
OUTPUT_DIR = "src/main/resources/assets/clod/textures/entity"
# Colors
TERRACOTTA = (212, 132, 91) # #D4845B
CREAM = (245, 230, 211) # #F5E6D3
DARK_TRIM = (61, 61, 61) # #3D3D3D
AMBER_EYES = (232, 168, 76) # #E8A84C
TRANSPARENT = (0, 0, 0, 0)
# ============================================================
# clod.png (64x64 main texture)
# ============================================================
# UV layout (matches ClodModel):
# Head (10x10x10): texOffs(0,0)
# - top/bottom: U=10..20, V=0..10 and U=20..30, V=0..10
# - front: U=10, V=10, 10x10
# - back: U=30, V=10, 10x10
# - left: U=0, V=10, 10x10
# - right: U=20, V=10, 10x10
#
# Body (10x8x6): texOffs(0,20)
# - top/bottom: U=6..16, V=20..26 and U=16..26, V=20..26
# - front: U=6, V=26, 10x8
# - back: U=22, V=26, 10x8
# - left: U=0, V=26, 6x8
# - right: U=16, V=26, 6x8
#
# Right arm (4x8x4): texOffs(40,20)
# - top/bottom: U=44..48, V=20..24 and U=48..52, V=20..24
# - front: U=44, V=24, 4x8
# - back: U=52, V=24, 4x8
# - left: U=40, V=24, 4x8
# - right: U=48, V=24, 4x8
#
# Left arm (4x8x4): texOffs(40,32)
# - Same layout offset to (40,32)
#
# Right leg (4x8x4): texOffs(0,34)
# - top/bottom: U=4..8, V=34..38 and U=8..12, V=34..38
# - front: U=4, V=38, 4x8
# - back: U=12, V=38, 4x8
# - left: U=0, V=38, 4x8
# - right: U=8, V=38, 4x8
#
# Left leg (4x8x4): texOffs(16,34)
# - Same layout offset to (16,34)
#
# Antenna (1x3x1): texOffs(0,46)
# - top/bottom: U=1..2, V=46..47 and U=2..3, V=46..47
# - front: U=1, V=47, 1x3
# - back: U=3, V=47, 1x3
# - left: U=0, V=47, 1x3
# - right: U=2, V=47, 1x3
img = Image.new("RGBA", (64, 64), TRANSPARENT)
draw = ImageDraw.Draw(img)
# ---- HEAD ----
# Top face
draw.rectangle([10, 0, 29, 9], fill=TERRACOTTA)
# Bottom face
draw.rectangle([20, 0, 29, 9], fill=TERRACOTTA)
# Front face (U=10, V=10, 10x10)
draw.rectangle([10, 10, 19, 19], fill=TERRACOTTA)
# Cream face area (inner 6x6)
draw.rectangle([12, 12, 17, 17], fill=CREAM)
# Eyes — amber 2x2 squares on front face
# Left eye (from viewer perspective): around U=13-14, V=14-15
draw.rectangle([13, 14, 14, 15], fill=AMBER_EYES)
# Right eye: around U=16-17, V=14-15
draw.rectangle([16, 14, 17, 15], fill=AMBER_EYES)
# Back face
draw.rectangle([30, 10, 39, 19], fill=TERRACOTTA)
# Dark trim stripe on back
draw.rectangle([34, 12, 35, 17], fill=DARK_TRIM)
# Left face
draw.rectangle([0, 10, 9, 19], fill=TERRACOTTA)
# Right face
draw.rectangle([20, 10, 29, 19], fill=TERRACOTTA)
# Top face (head top)
draw.rectangle([10, 0, 19, 9], fill=TERRACOTTA)
# Dark trim on top edge
draw.rectangle([10, 0, 19, 0], fill=DARK_TRIM)
# ---- BODY ----
# Front face (U=6, V=26, 10x8)
draw.rectangle([6, 26, 15, 33], fill=TERRACOTTA)
# Cream chest starburst/asterisk pattern
# Vertical line
draw.rectangle([10, 27, 11, 32], fill=CREAM)
# Horizontal line
draw.rectangle([8, 29, 13, 30], fill=CREAM)
# Diagonal hints
draw.point((9, 28), fill=CREAM)
draw.point((12, 28), fill=CREAM)
draw.point((9, 31), fill=CREAM)
draw.point((12, 31), fill=CREAM)
# Back face
draw.rectangle([22, 26, 31, 33], fill=TERRACOTTA)
# Side faces
draw.rectangle([0, 26, 5, 33], fill=TERRACOTTA)
draw.rectangle([16, 26, 21, 33], fill=TERRACOTTA)
# Top face
draw.rectangle([6, 20, 15, 25], fill=TERRACOTTA)
# Bottom face
draw.rectangle([16, 20, 25, 25], fill=TERRACOTTA)
# ---- RIGHT ARM ----
# All faces terracotta with dark trim edges
# Front
draw.rectangle([44, 24, 47, 31], fill=TERRACOTTA)
# Back
draw.rectangle([52, 24, 55, 31], fill=TERRACOTTA)
# Left
draw.rectangle([40, 24, 43, 31], fill=TERRACOTTA)
# Right
draw.rectangle([48, 24, 51, 31], fill=TERRACOTTA)
# Top
draw.rectangle([44, 20, 47, 23], fill=TERRACOTTA)
# Bottom
draw.rectangle([48, 20, 51, 23], fill=TERRACOTTA)
# Dark trim on edges
draw.rectangle([44, 31, 47, 31], fill=DARK_TRIM)
draw.rectangle([52, 31, 55, 31], fill=DARK_TRIM)
# ---- LEFT ARM ----
# Front
draw.rectangle([44, 36, 47, 43], fill=TERRACOTTA)
# Back
draw.rectangle([52, 36, 55, 43], fill=TERRACOTTA)
# Left
draw.rectangle([40, 36, 43, 43], fill=TERRACOTTA)
# Right
draw.rectangle([48, 36, 51, 43], fill=TERRACOTTA)
# Top
draw.rectangle([44, 32, 47, 35], fill=TERRACOTTA)
# Bottom
draw.rectangle([48, 32, 51, 35], fill=TERRACOTTA)
# Dark trim
draw.rectangle([44, 43, 47, 43], fill=DARK_TRIM)
draw.rectangle([52, 43, 55, 43], fill=DARK_TRIM)
# ---- RIGHT LEG ----
# Front
draw.rectangle([4, 38, 7, 45], fill=TERRACOTTA)
# Back
draw.rectangle([12, 38, 15, 45], fill=TERRACOTTA)
# Left
draw.rectangle([0, 38, 3, 45], fill=TERRACOTTA)
# Right
draw.rectangle([8, 38, 11, 45], fill=TERRACOTTA)
# Top
draw.rectangle([4, 34, 7, 37], fill=TERRACOTTA)
# Bottom
draw.rectangle([8, 34, 11, 37], fill=TERRACOTTA)
# Dark trim at bottom
draw.rectangle([4, 45, 7, 45], fill=DARK_TRIM)
draw.rectangle([12, 45, 15, 45], fill=DARK_TRIM)
draw.rectangle([0, 45, 3, 45], fill=DARK_TRIM)
draw.rectangle([8, 45, 11, 45], fill=DARK_TRIM)
# ---- LEFT LEG ----
# Front
draw.rectangle([20, 38, 23, 45], fill=TERRACOTTA)
# Back
draw.rectangle([28, 38, 31, 45], fill=TERRACOTTA)
# Left
draw.rectangle([16, 38, 19, 45], fill=TERRACOTTA)
# Right
draw.rectangle([24, 38, 27, 45], fill=TERRACOTTA)
# Top
draw.rectangle([20, 34, 23, 37], fill=TERRACOTTA)
# Bottom
draw.rectangle([24, 34, 27, 37], fill=TERRACOTTA)
# Dark trim at bottom
draw.rectangle([20, 45, 23, 45], fill=DARK_TRIM)
draw.rectangle([28, 45, 31, 45], fill=DARK_TRIM)
draw.rectangle([16, 45, 19, 45], fill=DARK_TRIM)
draw.rectangle([24, 45, 27, 45], fill=DARK_TRIM)
# ---- ANTENNA ----
# Front (U=1, V=47, 1x3)
draw.rectangle([1, 47, 1, 49], fill=DARK_TRIM)
# Back (U=3, V=47, 1x3)
draw.rectangle([3, 47, 3, 49], fill=DARK_TRIM)
# Left (U=0, V=47, 1x3)
draw.rectangle([0, 47, 0, 49], fill=DARK_TRIM)
# Right (U=2, V=47, 1x3)
draw.rectangle([2, 47, 2, 49], fill=DARK_TRIM)
# Top (U=1, V=46, 1x1)
draw.point((1, 46), fill=AMBER_EYES) # Glowing tip
# Bottom
draw.point((2, 46), fill=DARK_TRIM)
img.save(f"{OUTPUT_DIR}/clod.png")
print(f"Saved {OUTPUT_DIR}/clod.png")
# ============================================================
# clod_eyes.png (64x64 emissive overlay)
# ============================================================
# Fully transparent except amber pixels at eye UV positions
# on the head front face.
# Head front face: texOffs(0,0) means front starts at U=10, V=10
# Eyes at (13,14)-(14,15) and (16,14)-(17,15)
eyes = Image.new("RGBA", (64, 64), TRANSPARENT)
eyes_draw = ImageDraw.Draw(eyes)
# Left eye (amber, full opacity)
eyes_draw.rectangle([13, 14, 14, 15], fill=(232, 168, 76, 255))
# Right eye (amber, full opacity)
eyes_draw.rectangle([16, 14, 17, 15], fill=(232, 168, 76, 255))
eyes.save(f"{OUTPUT_DIR}/clod_eyes.png")
print(f"Saved {OUTPUT_DIR}/clod_eyes.png")