Pixel-Art People: Characters and a Creator on iPhone

This post has not been translated yet, so you are reading the English original. Read it at the English URL

Pokémon Emerald’s Brendan is 14 by 21 pixels in a 16-by-32 cell, drawn in 13 colours, with two eyes of one pixel by two and no mouth; the Game Boy’s Red was 14 by 16 in three greys, with the same face.12 Stardew Valley’s farmer is seven layers on one body, and a table of 126 offsets moves the shirt, the hair and the hat with it.34 Mana Seed sells its character as a “paper doll” whose clothes, hair and tools are separate sheets “all with identical layouts so they can be swapped out at runtime.”5 Those three facts are most of the craft of a pixel person: a cell and a face budget, a stack of layers on one grid, and a rule for what moves with what. Our app’s collector failed on each (ten pixels wide, one-pixel eyes, clothes painted onto one body; the owner’s word was “Roblox”), so we measured the canon, read the paper-doll systems and rebuilt the character from the cell up: a 26-pixel figure with a face, 47 pieces on one body’s grid, the garments derived from the body so every one covers every frame, 52 dye ramps, a figure string the app and the server repair rather than reject, and a creator that previews the real sprite. This is the guide, with the numbers, the Apple pipeline we measured, and what shipped.

TL;DR

  • A pixel person is a head budget first. The measured sprites fall into three bands: the chibi band at 60 to 67 percent head with 1-by-2 eyes and no mouth (every 2D Pokémon overworld sprite I measured, from Red to Emerald), the RPG band at 38 to 54 percent (Final Fantasy VI, Chrono Trigger, Stardew, Octopath), whose eyes grow to 2 by 2 once the cell reaches 16 by 32, and the heroic band under 35 percent where a cape carries the silhouette (Hyper Light Drifter). Slynyrd’s rule of thumb, “the head usually takes up a third to half of the total sprite,” is the RPG band in one sentence.167
  • Clothes are layers on one grid, not paint on one body. The Liberated Pixel Cup generator, Terraria and Celeste split what hangs behind the body from what sits in front, Stardew draws the arms as their own top layer, Mana Seed moves props in front of or behind the body per frame, and the systems with hats solve the hat-over-hair problem with a rule (Stardew’s per-hat show real hair flag, Starbound’s per-hat mask) rather than by drawing every combination.38910
  • The good creators offer fewer things, all of them to everyone. The Mii team “removed a lot of facial parts,” Animal Crossing: New Horizons made every hairstyle and face “gender-free” from its first day and lets you change them at a mirror, and Larian widened its swatch palette “so that there is something for everybody.” Pokémon GO’s 2024 body sliders are the cautionary tale: within days players were reporting hairstyles clipping through heads.11121314
  • Cosmetics in a free app for a nine-year-old have rules with dates on them. Apple requires odds for any randomised paid item; PEGI has rated paid random items 16 and expiring log-in streaks 7 since June 2026; the FTC fined Epic $275 million under COPPA and ordered $245 million in refunds partly for a button that charged players who were only trying to preview an item.151617
  • On Apple platforms, compose index planes, not RGBA layers, and stop creating textures. We measured the pipeline on a Mac (an M2 Max, swiftc -O; no iPhone has been timed yet): composing a look is tens of microseconds, 27 on the shipped sheets with thirteen planes worn; creating a TextureResource is about half a millisecond (0.4 to 0.7 ms with the .color semantic, a third with .raw) with a long tail, and a room of 40 eight-layer looks arriving at once is about 28 milliseconds on the main actor, about two frames at 60 Hz and three or more at 120 Hz. An 8-bit index plane per layer and a 256-entry table per look replace marker-colour swapping exactly, and a LowLevelTexture atlas is the next step the measurements point to.1819
  • What shipped: a 32-by-32 cell with a 26-pixel figure (27 with hair), four facings, three drawn and one mirrored, 17 frames (breath, blink, a six-frame walk, the card raise, a wave, a stretch), 47 wearable pieces and 52 dyes, a figure string like 2.sk4.hr3-7.tp3-8-12 that is the saved value, the wire value and the cache key, a server that repairs it, and a creator that previews the real sprite at a whole number of device pixels per texel. The before and after is at the end.

1. What a pixel person is made of

Start with the cell, because everything else is divided by it. Pokémon Emerald’s object-event table gives Brendan a 16-by-32 object and a 16-by-32 sprite, and the walking sheet in the decompilation is 144 by 32: nine 16-by-32 frames, three facings by three poses, the east-facing frames made by flipping west with .hFlip = TRUE.120 Inside that cell the figure is 14 wide and 21 tall; I counted the opaque pixels of the standing frame this morning, and the face is two 1-by-2 eyes three columns apart with no mouth. Red, from 1996, is 14 by 16 in a 16-by-16 cell with three shades of grey and exactly the same face; Crystal’s Chris is the same again.2 Game Freak kept one face for eight years and three consoles; my reading of why is that a one-by-two mark is the smallest thing that reads as an eye at any distance, and that a mouth at that size reads as a moustache.

The Super Nintendo RPGs chose a taller cell and spent it on the face. Final Fantasy VI’s party sprites are 16 by 24, one set of poses “used mainly in the event code (as well as the battle module and the world map module).”21 Chrono Trigger has no fixed cell; its frames are assembled from 16-by-16 blocks, and Crono stands 16 by 35 with a 2-by-2 eye that has a white column in it. Lucca’s archive at videogamesprites.net holds 72 GIFs, among them “Glasses”, a two-frame tic at 200 milliseconds in which her hand rises to her face and 35 pixels change, all of them in rows eight to sixteen; among the rest are Nod, Shake Head, Ponder, Finger, Laugh, Shocked and Ready, a library of expressions on a 16-by-32 body.22 Kazuko Shibuya, who drew the first six Final Fantasys’ sprites, explained the budget in one sentence: “Players have to tell the characters apart, so I look at the design and include only the most distinctive features.”23 Her remaster note is the other half of the lesson: in the SNES Final Fantasy VI “the height of the head was prevented from fully being shown,” and in the Pixel Remaster “my wish came true” of “just one more pixel on top,” with leeway added at the sides so arms and capes could move.24

Three bands, measured

I measured a standing frame of each of these from the public rips and repositories, at native scale, head from the top of the hair or hat to the chin; the boundaries are ±1 row, which moves a percentage by three to five points at these sizes.7

Sprite Cell Figure Head Heads tall Eyes Mouth Colours
Pokémon Red (Game Boy) 16×16 14×16 ~62% 1.6 1×2 none 3 shades
Pokémon Crystal, Chris 16×16 14×16 ~62% 1.6 1×2 none 3 shades
Pokémon Emerald, Brendan 16×32 14×21 ~62% 1.6 1×2 none 13
Pokémon Emerald, May 16×32 14×20 ~60% 1.7 1×2 none 14
Cassette Beasts, Kayleigh (overworld) 17×25 17×24 ~67% 1.5 1×2 none 22
Final Fantasy VI, Terra 16×24 15×24 ~54% 1.8 1×2 none 11
EarthBound, Ness 16×24 16×24 ~54% 1.8 1×2 none 10
Secret of Mana, Randi 16×32 16×32 ~47% 2.1 2×2 with white none 14
Stardew Valley, Abigail 16×32 14×27 ~48% 2.1 2×2 with white 2 px 29
Chrono Trigger, Crono 16×16 blocks 16×35 ~43% 2.3 2×2 with white none 12
Octopath Traveler, Ophilia 18×32 18×32 ~41% 2.4 2×2 none 30
Mana Seed base 64×64 14×29 ~38% 2.6 2×2 with white none 5 (body)
Hyper Light Drifter 32×32 12×28 ~29% 3.5 hood marks none 11

Read down the head column and three bands appear. The chibi band, 60 to 67 percent head, with 1-by-2 eyes and no mouth: the four Pokémon sprites, whatever their cell, and Cassette Beasts, which follows them on purpose. The RPG band, 38 to 54 percent: FF VI and Ness at 16 by 24 still with 1-by-2 eyes, and then, once the cell is 16 by 32 or more, a 2-by-2 eye, with a white highlight in Mana, Stardew, Chrono and the Mana Seed base and without one in Octopath. The heroic band, under 35 percent, where the head is a hood and the silhouette is a cape: the Drifter, whose 32-by-32 cell holds no eye at all. Octopath Traveler II’s developers moved their own cast down the table on purpose; its characters “have a smaller head-to-body ratio, which allowed us to fit more action into events and battles,” while the faces stayed “similarly pixelated.”25 Raymond Schlitter’s rule for the RPG band is the one to remember: “When working with limited size the head usually takes up a third to half of the total sprite,” because the big head is there “to emphasize the expressive features of the character, which helps the player form an emotional connection.”6 His own top-down hero is 26 wide by 32 tall, which he says “roughly conforms to 1x2 16x16px tiles”; ours came out 26 tall, 1.6 tiles.26

What moves

The second budget is frames, and the masters spend them on character before locomotion. Pedro Medeiros’s two-frame idle is “move down one pixel; open arms; bend knees,” then “move up one pixel; arms move down,” with the rule that the “character doesn’t change mass”; add a third frame and “that middle frame adds a lot to the idle”; a six-frame idle is where “secondary animations: like the hair lagging behind the head” live; and “vertical movement alone is boring,” so an idle is the place for a blink, a yawn, a look around, a scratch (his tutorial’s own list).27 Schlitter’s six-frame walk bounces rather than sines: “one stride of this 6 frame cycle, in relation to the previous frame, goes down 1px, down 1px, and up 2px,” with the up faster than the down, and “the hair shifts in frames 2 and 4, while all the rest are the same.”26 He draws “the cape and gear on a separate layer that can overlay the basic costume,” and animates “the base character with armor, but without the sword, shield and cape,” because that is what lets one body wear many things.2628

Celeste is the extreme case of a layer that moves on its own. Noel Berry, who coded Madeline’s hair: “The character sprite is drawn without her hair, and then we add it in afterwards in real time. The hair is a list of about 5 or 6 points that follow each other with an offset and maximum distance, with the first point being anchored to her head. Each point just draws a simple circle, reducing in size the further away it is.” The hair “gets drawn behind her sprite, except for her bangs, which get drawn on top,” and “each animation has metadata associated with it on where to render the hair.”29 In the released source the normal hair colour is a constant, NormalHairColor is #AC3232, with a second colour for two dashes; at zero dashes the hair blends toward UsedHairColor instead, and while dashes remain it flashes white for 0.12 seconds when the count changes.30 Sea of Stars went the other way and spent frames: “We probably have about 60 navigation animations per character,” Thierry Boulanger said, “eight angles instead of four,” and the studio’s gate before any of them is approved is “just the idle frames turnaround, from the concept.”3132 The Dead Cells pipeline is the same discipline in 3D: “Once, and only once, the animation is convincing and correctly timed with the least amount of frames possible, I add interpolation frames.”33

2. The paper doll: how a sprite gets dressed

Every customisable pixel character in a shipped game is a stack of sheets on one grid. The differences are in the order of the stack, where the placement data lives, and how colour is changed.

Stardew Valley

The farmer is “16 pixels wide by 32 pixels tall,” and “The player facing to the right is the unflipped sprite, while facing left is flipped.”3 The draw order, bottom to top, is “Head/Torso/Boots” first, then “Pants,” “Shirt,” “Accessories (e.g., glasses, makeup, earrings, facial hair),” “Hair,” “Hat,” and “Arms” on top.3 Shirts “are only 8x8 and unable to fully-cover a torso wider than that,” so a torso drawn wider than eight pixels shows skin past its shirt; hats are “20x20 hat sprites” in a 20-by-80 block, “facing down, right, left, and up,” four images per hat rather than one per frame.334 The placement of those small pieces is not in the art: “The placement of layers stored in other files (such as the height of a shirt on the body) is dependent upon the animation, and cannot be modified by editing png files.”3 In the decompiled renderer that placement is two arrays, featureXOffsetPerFrame and featureYOffsetPerFrame, each new int[126], one entry per body frame, added to the shirt, accessory, hair and hat draws, plus a 16-entry hairstyleHatOffset.4 Hair under a hat is a per-hat flag with three values, “show real hair” as true, change “the hairstyle to fit the hat” as false, or hide, and a lookup that maps hairstyles onto a few shapes drawn to sit under a brim: “Hairstyle 3 will change to hairstyle 11,” “Hairstyles 22 and 26 will change to hairstyle 7,” and so on.343 Recolouring is by marker: “The game identifies skin, eyes, boots, pants, arms, and shirt sleeves in the farmer base using the color.”3 That is the system our first collector copied, and it is a good one until a garment needs a shape of its own.

Mana Seed and the Liberated Pixel Cup

Seliel the Shaper’s Mana Seed is the cleanest statement of the other way: “a ‘paper doll’ style layered sprite system that uses separate sheets for clothes, hair, tools, etc. all with identical layouts so they can be swapped out at runtime.” The character is “around 32 pixels high” in a “64x64 pixel cell,” with “10 different skin tones” and hair in “13 color swaps.”5 Because every hair and clothing sheet has the body’s layout, none of them is offset at runtime (props and effects are aligned by hand); the cost moves into the sheets, every garment shipped covering every frame, which is why the Farmer system advertises “ALL HAIR AND CLOTHING COVERS ALL ANIMATIONS!” and warns that “You may need as many as 20 ‘paper doll’ layers on your sprite to use everything as intended.”8 Its colour rule is the one we adopted: “The outfits and hairstyles in this pack only come in one universal color palette to make runtime palette swapping easy.”8

The Liberated Pixel Cup’s generator is the open-source version of the same idea, with the stack written down as numbers. Each layer has a z-position, and a piece that hangs can have two: in the generator’s z table the lizard tail is layer_1 at 85, in front, and layer_2 at 5, behind, so the same item draws under the body and over it.9 Recolouring is a palette mapping with “tolerance = 1 // ±1 per channel,” and “All variants must have the same number of colors.”35 The style guide’s proportions are the RPG band stated as a rule, “Bases are approximately two and a half heads tall,” with “The base should fit in a 32x48 space and the clothing should fit in 48x64 space,” and its outline rule is the strict one: “black or near black, no selective outlining.”36

The others, and what they agree on

Starbound dyes four fixed key colours, “Light Tan (#ffca8a), Dark Tan (#e0975c), Light Brown (#a85636), and Dark Brown (#6f2919),” and solves hats with a per-hat mask.png in which “white portions of the image will allow hair to display, and transparent portions will prevent hair from displaying”; “This file ONLY affects hair.”3710 Terraria splits the player into named draw layers, HairBack and HeadBack behind the skin, ArmOverItem and HandOnAcc in front, and applies its dyes as shader passes through an ArmorShaderData.38 Habbo’s avatar is a string: the renderer splits a figure on . into parts and each part on - into a type, a set id and colour ids, with two-letter types (hd head, hr hair, ch chest, lg legs, sh shoes), and a placeholder figure, hd-99999-99999, drawn while a figure’s assets are still downloading.3940 An open-source Habbo emulator repairs rather than rejects: replacing an invalid, club-only or unowned set with getFirstNonHCSetForGender, and reads colours only if (set.colorable).41

Put side by side, the systems agree on five things.

Rule Who does it
Every layer sheet shares one grid Mana Seed, LPC, Stardew’s body layers
Small rigid pieces are drawn per facing and placed by a table the body owns Stardew’s hats and the 126-entry offsets; Fashion Sense’s HeadPosition and per-frame Offset42
Anything that hangs has a back part and a front part LPC’s zPos pairs, Terraria’s HairBack, Celeste’s bangs over and hair behind
Colour is a mapping from a fixed source palette Mana Seed’s universal palette, LPC’s ±1 mapping, Starbound’s four tans, Stardew’s markers
One rule governs hats and hair Stardew’s flag and lookup, Starbound’s mask, Habbo’s hiddenlayers on a set43

The last rule is the one newcomers skip and then pay for in every hat-times-hair combination. We skipped it in our first build too: the Buns hairstyle poked out of the Cap and the Beanie on both sides because nothing said it should not.

3. What the good creators let you choose

The temptation, once the paper doll works, is to ship everything. The games people love did the opposite, and they are explicit about why.

The Mii Channel’s director, Hisashi Nogami, on the Wii’s face maker: “We also removed a lot of facial parts as we were trying to be careful not to put in too many options.” Satoru Iwata, in the same conversation: “if there are hundreds of different options to choose from, you can be at a total loss over which one to pick.” The DS prototype had “only programmed in facial components for Japanese people,” and Nogami’s fix was to ask “non-Japanese people” what was missing.11 Animal Crossing: New Horizons starts a player with “eight hairstyles and eight hair colors,” unlocks six more styles “by interacting with a vanity for the first time,” redeems further packs of six and eight for Nook Miles, offers “eight skin tones at the beginning of the game,” and lets all of it be changed “at any time by using a mirror.”4445 Aya Kyogoku said at E3 2019, before release: “All the facial parts or hairstyles are all gender-free,” and “if you feel like a certain way one day, then you can make that change pretty easily.”12 Nookipedia’s history of the series is the arc in one line: in New Leaf “Face and hair styles are still locked by gender,” and in New Horizons “no clothing or other visible aspects of the player’s appearance are locked by gender.”46

Pokémon walked the same road more slowly. X and Y offered three preset looks per gender and “The choice cannot be changed once selected”; Sword and Shield’s boutique menus cover “tops, overwear, bottoms, dresses, socks, shoes, bags, hats, glasses, gloves, and uniforms,” with eyelashes and lipstick marked “(Female Only)”; in Scarlet and Violet “all customisation options can be used by all players” and “Any hairstyle can be selected regardless of gender,” but the skin tone still cannot be changed after the start.474849 Pokémon GO let players “choose a ‘style’ not a ‘gender’” at its 2016 launch; its April 2024 overhaul added sliders for “weight, muscle, shoulders, chest, and hips,” and within the week TheGamer was reporting clothing “bugging out and clipping through avatars” and players “demanding that Niantic bring old avatars back.”505114 Every garment has to fit every body you offer; a slider multiplies the fitting work by its range.

Stardew Valley is the generous end: “24 skin tones, 74 hairstyles, 112 shirts, 4 pants, and 31 accessories. All of them can be used by either gender, with the option to randomize appearance,” and “eye color, hair color, and pants color” set by sliders.52 Those sliders are “Hue, Saturation, and Value (HSV) sliders,” and the Dyeing page notes they “allow any color.”53 Any colour is the problem for a pixel world: a slider leaves the palette, and a shirt dyed one hue off its neighbour’s loses the coherence that makes a cast look like one cast. Larian’s answer in Baldur’s Gate 3 was swatches, not sliders. Alena Dubrovina expanded the palette “so that there is something for everybody,” warned that “there is a risk of faces being a bit blank and characterless if the character creator is heavily dependent on the sliders,” and hired consultants for textured hair because “Black hairstyles consist of coils and require more volume.”13 Jay Baylis kept Cassette Beasts’ 120 monsters coherent “by sharing the same pool of around 20 colours across all 120 monsters,” and describes the result as “an action figure set that was limited in the amount of plastic colours.”54

Counts, side by side

System Skin Hair styles Hair colours Clothing Colour method
Stardew Valley 24 74 HSV slider 112 shirts, 4 pants, 31 accessories sliders for eyes, hair, pants5253
Animal Crossing: New Horizons, day one 8 8, then 6 more at the first vanity 8 the wardrobe you buy and craft swatches4445
Pokémon X/Y 3 presets, fixed per gender n/a gender-split boutiques swatches47
Pokémon Scarlet/Violet fixed after the start any, regardless of gender n/a uniform plus seven slots swatches4849
Habbo n/a by set palette ids two-letter part types in a figure string palette ids, club-gated3955
Club Penguin a body colour n/a n/a one item per slot: head, face, neck, body, hand, feet, pins “Most clothes can only be worn by members”56
Mana Seed Character Base 10 2 (+5 in a pack) 13 swaps outfits by ramp ramp swap5

The pattern that survives every one of these is that identity is free and plentiful (skin tones, hair, faces), clothing is where the counting happens, and colour is a pick from a palette the artist made. Apple’s own guidance for games says the same thing from the other direction: “Give players the tools they need to represent themselves,” “support the spectrum of self-identity,” “Avoid stereotypes,” and, for the first run, “People appreciate being able to start playing without first having to change a lot of settings.”57 The onboarding guidance is blunter: “Postpone nonessential setup flows or customization steps.”58

4. Cosmetics, money and children: the rules with dates on them

A character creator in a free app is also a shop, or is soon asked to become one, and the rules for that have hardened in the last four years.

Apple’s App Review Guidelines, 3.1.1: apps “offering ‘loot boxes’ or other mechanisms that provide randomized virtual items for purchase must disclose the odds of receiving each type of item to customers prior to purchase,” and “Any credits or in-game currencies purchased via in-app purchase may not expire.”15 App Store Connect’s age-rating definitions list loot boxes as a chance-based activity, “Virtual containers that provide players with randomized virtual items for purchase,” and give as examples “randomized functional cards or cosmetic items for purchase.”59 For a subscription, 3.1.2(a) requires “ongoing value to the customer” over a period of “at least seven days,” and 3.1.2(c) says “Before asking a customer to subscribe, you should clearly describe what the user will get for the price.”15

PEGI changed its rules in June 2026. “Video games with paid random items that are submitted to PEGI since June 2026, will be PEGI 16 or PEGI 18 (for social casino games).” “Time-limited offers” that create “a sense of urgency” rate a game PEGI 12, or 7 “if the game has built-in parental control tools with spending turnd off by default” (sic). Play-by-appointment mechanics such as “daily quests, log-in streak or event-based rewards that expire after a while” rate PEGI 7, and PEGI 12 where “players are punished by losing rewards or game status when they do not return in time.”16 The UK’s Children’s Code names the same mechanics as “‘sticky’ features,” listing “reward loops, continuous scrolling, notifications and auto-play features which encourage users to continue playing a game.”60

The enforcement case every creator should read is the FTC’s December 2022 settlement with Epic: “a $275 million penalty for violating children’s privacy law” and “$245 million in refunds for tricking users into making unwanted charges,” among them charges made “by pressing an adjacent button while attempting simply to preview an item.”17 The 2025 COPPA amendments then required “separate verifiable parental consent to disclose children’s personal information to third-party companies related to targeted advertising.”61 Three design rules fall out of that record, and we wrote them into the plan before drawing a single hat: preview and purchase are never adjacent buttons; a locked item can be tried on but a try-on never charges; and a free item and a paid item use different verbs, as Pokémon GO does (“For free items: tap Choose,” “For Premium Items: tap Exchange”).62

The healthier model is the one Innersloth describes for Among Us: “All cosmetics are purely visual and do not have any effect on gameplay or gameplay options,” and the reason for selling any is stated plainly, “To keep the game going, servers running, and give everyone more free cosmetic options.”63 The older model is Club Penguin’s, where “Most clothes can only be worn by members,” and Habbo’s, whose club offered “A larger selection of clothing styles and colors.”5655 Kiradex is free, and the plan is to keep it free; what its patrons get is flair, a crown and a star pin, and what levels earn, a jacket at 10, a backpack at 20, a cape at 50, cannot be bought at any price. That last rule is Stardew’s Hat Mouse, who sells the hats the player’s achievements have earned, made explicit:64 the flaunt that money can’t buy is what keeps the paid flaunt from becoming a caste.

Two findings from the research literature shaped the body rules. A 2014 experiment with 140 overweight children aged nine to twelve found that those given normal-size avatars did better on its measures, and its authors recommended “designing avatars that are slim and toned,” a recommendation we read as a warning about what a default body teaches rather than guidance.65 A 2025 study of 495 young MOBA players found avatar attractiveness predicting self-objectification, with customisation moderating the link; and a 2025 study of 68 children aged eight to thirteen found a health app’s acceptability “driven by gamified features, proportional rewards, and avatar customization,” with the children asking for “more personalization to promote cultural inclusion.”6667 So: no body sliders at launch, one build every garment fits, ten skin tones from porcelain to ebony, each with its own warmth (Unicode’s emoji modifiers are “based on the six tones of the Fitzpatrick scale”; we wanted finer steps), textured hair drawn with the volume Larian’s consultants asked for, and a hijab in the hat slot that hides the hair as a hat should.6813

5. The craft, as rules with numbers

Here is the character specification we wrote from the record above and then built. Each line names the game or the practitioner it comes from, so you can disagree with the source rather than with us.

The cell is 32 by 32; the figure is 26 tall to the crown of the head, 27 with most hair (28 with buns, spikes or the puff), and about 14 wide at the shoulders; the feet stand on row 29. Stardew’s hats alone are 20 pixels wide, which a 16-wide cell cannot hold; Shibuya’s remaster fix was “leeway” above and at the sides; Schlitter’s hero is 26 wide by 32 tall; Mana Seed and LPC put a 29-to-47-pixel figure in a 64 cell for the same reason.3424265 Two rows under the feet keep the engine’s placement arithmetic from the tile post unchanged, and the rows above the hair hold a crown.

The head is 12 rows bald, 13 with hair: 46 to 48 percent of the figure, about 2.1 to 2.2 heads tall. That is the RPG band where Stardew, Chrono Trigger, Octopath and the Mana Seed base sit, near the LPC guide’s “approximately two and a half heads tall.”736 Octopath II’s move down the table bought action; we wanted the opposite, a face a nine-year-old can read across a plaza.

The eye is 2 by 2 with a highlight pixel, in its own layer, with its own dye. Every RPG-band sprite I measured with a cell of 16 by 32 or more has the 2-by-2 eye, and all but Octopath’s the highlight; the LPC generator treats eye colour as a recolourable channel; one extra frame with the eyes shut is a blink, Medeiros’s first suggestion for an idle.727 A mouth appears only in expression frames, never in the standing one.

Four facings, three drawn: right is left mirrored for symmetric pieces, and an asymmetric piece may draw its own right row. Emerald mirrors with .hFlip = TRUE; Stardew flips too; the card in a raised hand is the asymmetric case, and ours is drawn for both sides.203

The outline is selective: each material is outlined in its own darkest ramp step. Chrono Trigger’s edge is half black and half not (measured in the first guide), and LPC’s “black or near black, no selective outlining” is the other legitimate school, closest to what we had and were leaving.6936

Every dye is a four-step ramp, outline, shade, base, light, and the steps turn hue. Schlitter’s ramps use “20 degrees of positive hue shift between each swatch”; Medeiros shades “a little more blue and less saturated” and lights “a little more yellow and saturated”; the LPC guide pushes shadows toward purple and highlights toward yellow.707136 Our palette already did this for tiles; the dyes share its hue-turning helper, turned(), with saturation steps of their own, so a scarlet tee’s shadow is crimson-violet and its light leans orange, which a flat multiply (0.8, or 0.75 for the hair, in the first collector) can never give.

Players choose ramps, not colours. No HSV slider, no picker: the Mii team’s restraint, Larian’s swatches over sliders, Baylis’s twenty shared colours, and Apple’s HIG line that we deliberately broke, “If your app lets people choose colors, prefer system-provided color controls,” because a system colour picker would let any of 16 million colours into a world drawn from fixed ramps.11135472

Seventeen frames per facing. A two-frame breath (the shoulders settle one pixel), a blink, a six-frame walk whose body goes down a pixel on the recoil and up a pixel on the pass with the arms swinging opposite the legs, a three-frame card raise (anticipation, raise, hold), a three-frame wave, and a two-frame stretch for an idle tic. Schlitter’s bounce, Medeiros’s “move down one pixel” idle, Lucca’s two-frame tic at 200 milliseconds.262722

Thirteen draw layers, in a different order per facing. Bottom to top facing down: hair back, back under (a pack, a cape), body, shoes, bottom, top, neck, back over (straps, a clasp), eyes, face (glasses), hair front, hat, held. Facing up, the held card goes first, the eyes and the face drop out, and the back layers draw after the hair and before the hat, so a cape covers the shoulders and a backpack covers the back. Facing left and right, as facing down. This is LPC’s zPos table written as a list per facing, with Celeste’s rule that the bangs are over and the length is behind.929

One grid for everything, and the body owns the geometry. Every sheet has the body’s layout (Mana Seed’s “identical layouts”), so the runtime never offsets a thing.5 Where Stardew keeps 126 offsets per feature and the mod Fashion Sense exposes a HeadPosition and a per-frame Offset, we moved the placing into the forge: a hat is drawn once per facing and stamped at the head’s position in every frame, and the manifest ships the head and hand anchors for the things placed at runtime, the bubble and the 3D card, though both still take their place from the cell’s height for now.442

Garments are derived from the body, then given silhouette. This is the rule that made the wardrobe affordable. The body is drawn as skin with a region map (head, neck, torso, each arm, legs) and a row index inside each part, so a tee is “the torso below the neck plus the arms’ first three rows, in the top’s channel,” a long sleeve is seven rows, trousers are “the legs’ first five rows,” a boot is the last five. Mana Seed ships every garment as a full sheet laid out like the body’s, so that “ALL HAIR AND CLOTHING COVERS ALL ANIMATIONS”; how its artist produces those sheets is not documented. Deriving from the body gets the same guarantee from one rule, and the artist draws only what changes the silhouette: a hood, a collar, a hem, a skirt, a pocket, a strap.8

One rule governs hats and hair: show, trim or hide. Stardew’s three-valued flag, Starbound’s mask. A trim hat carries eraser pixels above its brim, which the composer applies to the hair layers only; hide leaves the hair out (the hijab, a hood); show draws over it (a visor, a crown, headphones).3410 A piece may also cover another slot: a dress covers the bottom, a hijab the neck, as New Horizons’ helmets count “as both a hat and glasses.”73

The look is a string. 2.sk4.hr3-7.tp3-8-12.bt1-9.sh1-0: the manifest version, then each slot in manifest order as a two-letter code, the piece and up to two dyes (skin 4, hair 3 in hair dye 7, top 3 in cloth 8 with trim 12, bottom 1 in cloth 9, shoes 1 in leather 0), a slot at its default left out. Habbo’s figure string is the model, split on . and -, and the emulator’s getFirstNonHCSetForGender, swapping in a wearable set for one that is not, is the rule that unknown means default.3941 Ids are append-only; the forge’s checks refuse a renumbering against the manifest in git.

6. The Apple way: composing, caching and the creator

The first guide in this series set the rendering recipe: RealityKit used as a 2D engine with an orthographic camera, nearest sampling, no mipmaps, an opacityThreshold cut-out and a textureCoordinateTransform per frame, with the AR defaults switched off.69 A dressed character adds three problems that recipe does not answer: how to compose a look, what it costs to put the result on the GPU, and how to preview it in SwiftUI without a second renderer.

Markers versus index planes

Our first collector was composed the Stardew way: RGBA layers drawn into a CGContext, then every opaque pixel compared against a list of marker colours (pure magenta for skin, pure cyan for hair, and so on) within a tolerance of ±8 per channel, “a little slack” in case a colour space had moved a marker. The swap was half the compose time, and the tolerance was a confession that the method could mismatch a pixel.

The replacement is older than any of the games above: an indexed image. The forge writes every layer as an 8-bit plane in which 0 is clear, 63 is an eraser and from 64 upward each dyeable material owns four consecutive indices (outline, shade, base, light); the app composes the planes a figure wears in the manifest’s order with “last non-zero wins,” then expands the composed plane through one 256-entry table built from the figure’s dyes. Aseprite’s indexed mode is the same idea, “each pixel has a number that references a palette color,” and the LPC generator’s recolouring is a palette mapping; Core Graphics can even build an indexed colour space, CGColorSpace(indexedBaseSpace:last:colorTable:), with a last index of at most 255.743575 We ship the planes as greyscale PNGs whose value is the index times two; the app reads the decoded bytes and halves them with a round-up, (v + 1) / 2, so a value that decodes one low still lands on its index, and a Swift Testing case holds every sheet to the indices the manifest means and the app’s composite to the forge’s own composite pixel for pixel, so the plaza can only show what the forge drew.

What it costs, measured

We timed the pieces on an Apple M2 Max under macOS 27 with swiftc -O, 400 runs after 20 warm-ups, median and p95, against the shipped layer sheets. These are Mac numbers, not iPhone numbers; the iPhone figures are the next measurement to make.18

Operation Median p95
Compose a look the old way, four RGBA layers plus the marker swap, 144×128 94.5 µs 157 µs
The marker swap alone 45.6 µs 52 µs
Compose from 8-bit index planes and expand through a table, four planes 18.4 µs 20 µs
The same expansion as a vImage float lookup, vImageLookupTable_Planar8toPlanarF, with each RGBA entry stored as a float bit pattern (bit-exact on the M2 Max, not promised by Apple) 6.1 µs 8.9 µs
TextureResource(image:options:) for the result, .color semantic 410 to 742 µs 0.8 to 2.4 ms
TextureResource.replace(withImage:options:) 1,011 µs 3.9 ms
Forty distinct eight-layer looks composed and uploaded as forty textures, serially 28.2 ms n/a
Writing one look into a shared MTLTexture atlas with replace(region:…) 3.3 µs 4.1 µs
Blitting that atlas into a LowLevelTexture 23 µs CPU 126 µs

The composition was never the cost. Texture creation is: 0.4 to 0.7 milliseconds per TextureResource with the .color semantic, about a third of a millisecond with .raw, whatever its size, with a long tail, so a room of forty collectors in eight-layer looks arriving in one welcome message is about 28 milliseconds on the main actor on the Mac, about two frames at 60 Hz and three or more at 120 Hz. Apple’s own documentation points at the fix. TextureResource.replace(withImage:options:) “blocks until the resource updates. Don’t use this method for updates at frame-rate frequency.”76 LowLevelTexture, from iOS 18, provides “the same fast resource update semantics as LowLevelMesh, but for texture assets,” in Apple’s words at WWDC24; its replace(using:) hands back a Metal texture to write with a command buffer, with the caveat that “The buffer’s contents are in an uninitialized state,” so every update rewrites the whole texture.7719 One 2304-by-1024 atlas holds 128 of our old 144-by-128 sheets, or 32 of the new 544-by-128 ones; on the older R8 prototype, one 144-by-128 look was a 3.3-microsecond write into a shared Metal texture and a 22.9-microsecond encode-and-commit on the CPU for the blit (34 microseconds of GPU time), with no TextureResource created after start-up. The RGBA atlas the new sheets would need is not measured yet. That is the next step the numbers point to, with instanced shadows alongside it: MeshInstancesComponent in iOS 26 “performs GPU instancing on the model of the same entity,” and forty identical shadow blobs are its documented case exactly.78 Apple’s CPU guide is the general principle, “RealityKit invokes a draw call for each mesh,” so “merge meshes that share a material when possible.”79 What shipped keeps one texture per look and caches it by the figure string, letting go of sheets nobody in the room wears; the atlas is on the roadmap with the on-device timings.

The creator in SwiftUI

The preview is the plaza’s own composite, not a second RealityKit scene. The composed sheet is cut into frames with cropping(to:), an Image(decorative:scale:) shows one with .resizable().interpolation(.none).antialiased(false), SwiftUI’s interpolation(.none) being the value that “indicates SwiftUI doesn’t interpolate image data,” and a TimelineView(.periodic(from:by:)) at an eighth of a second steps the breath, the blink and, after a change of clothes, two walk cycles, so a garment is seen moving.8081 The frame is derived from the timeline’s date rather than counted, because “The system might use a cadence that’s slower than the schedule’s update rate.”81 The scale is a whole number of device pixels per texel, as the first guide insisted: k = floor(pixelsTall ÷ (cellHeight + 8)), and the image’s size in points is cell × k ÷ displayScale, fractional points, whole pixels. Reduce Motion stops it at the standing frame.

The layout is the one the good creators converge on: the figure on top with a Turn button, a row of plain nouns (Skin, Eyes, Hair, Top, Bottom, Shoes, Hat, Face, Neck, Back), the chosen slot’s pieces each shown as the collector’s own figure wearing it, and a grid of named swatches for each dye the piece takes. Every swatch is a 44-point button, Apple’s minimum hit region, ringed in the ramp’s outline colour and marked with a check when chosen, so the choice never rests on hue alone; VoiceOver reads the dye’s name and the figure as a sentence (“Your collector: sand skin, brown eyes, brown short hair, scarlet tee, navy trousers…”).82 A locked piece is browsable and worn while browsing, with a note saying what earns it, and Done saves only what the patronage and the level have earned. Composing on every tap is safe: the composer walks each layer’s opaque pixels rather than the whole sheet (a cached list per plane), and on the shipped 544-by-128 sheets with thirteen planes worn it is 27 microseconds to compose and 72 with the table expansion on an idle Mac, swiftc -O; the same code in a Debug build on the iPhone simulator is 5 milliseconds for the plane and 11 with the table and the CGImage. The first version walked every pixel of every layer and was rewritten once its own timing test showed it far slower; the numbers, the harness and the caveats are in the research record.18 Creating textures or writing to SwiftData on every tap is not safe, so the creator does neither until Done.

The string, the record and the server

The figure string is the saved value, the wire value and the cache key, and it is always canonical, so equal looks give equal strings. Reading one repairs rather than rejects: an unknown slot is ignored, an unknown or unearned piece becomes the slot’s default, an unknown dye the slot’s default dye. The profile record keeps the string beside the old eight integer fields, so an older build on the same iCloud account still decodes a look it understands (its decoder reads each key with decodeIfPresent and ignores the rest, which is also what stopped the first build’s synthesized Codable from wiping every saved look the day a slot was added). The wire carries both, figure and the nearest look.

The server loads the same manifest, hash-checked against the app’s copy in its test suite, and applies the same repair for unknown ids and patron tiers before broadcasting (levels stay the app’s to check: the server has no collection to count), so every client draws what the server accepted. The two repairs agree on any string that fits the grammar; on one that does not fit it at all, the server answers with the default figure where the app salvages the fields it can read. That is the Habbo emulator’s habit, replacing what cannot be worn with getFirstNonHCSetForGender, applied to a patron gate: a Founder’s crown comes off at the server when the hello says the account is free. The tier itself is the client’s word for now, flair the server has no receipt to check; the App Store Server API can confirm it later.41 A figure never causes a rejected hello; that stays reserved for malformed fields such as the id or the handle. Nothing in a figure can spell anything: the canonical form is the manifest’s slot codes and numbers, nothing else, so free text has nowhere to go.

7. The case study: diagnosing our collector, then rebuilding it

The diagnosis

Kiradex is a collector’s app for Pokémon cards with a pixel plaza where collectors walk, talk in preset lines and hold their cards up. Its first collector was built in a morning, by rule, and looked it. Measured against the table in section 1 it was a 10-by-21 figure (12 by 22 with a cap) in a 16-by-32 cell, in the RPG band by proportion, 43 percent head, but with the smallest face budget in the sample: 1-by-1 eyes in the outline colour, below even the Game Boy’s 1-by-2. It had two shades per material, eight colours on its body sheet, where the SNES casts have ten to fifteen and the modern ones twenty to thirty. Its top, bottom and shoes were marker colours inside one body drawing, so every outfit had the same silhouette, which is the thing the owner’s word “Roblox” was pointing at: a rigid body with texture skins. Roblox’s avatar body is “15 separate mesh objects,” and Roblox’s answer was layered accessories that “stretch and wrap over a target.”8384 It used ten of sixteen columns, so hair had nowhere to have volume and a hat could not overhang. And its right-facing row was a mirror of its left, so any asymmetry would have flipped when it turned.

Before and after at eight times: the first collector (left, 10 by 21 pixels with one-pixel eyes and marker-coloured clothes) beside the rebuilt figure (26 pixels, a face, a scarlet tee with its own outline, a cap in two dyes, the Founder's crown).

The rig

The forge draws the collector from parts now rather than from one grid per frame: a head, a torso, two arms and a block of legs per facing, each a text grid with a position in the cell. A frame is a recipe, the body’s vertical offset (down one on the walk’s recoil, up one on the pass and the stretch), a legs variant (stand, contact left, contact right), an arms variant (hang, swing, raise, wave, stretch) and whether the eyes are open. Seventeen recipes, three drawn facings and a mirrored fourth make 68 cells of body. As the parts are stamped they write two more maps beside the pixels: the region each pixel belongs to and its row inside its part, which is what lets a sleeve be “the arm’s first three rows from the shoulder” whether the arm hangs or waves (a raised arm’s rows are counted from its shoulder at the bottom).

The naked rig, facing down and facing left, six of the seventeen frames at eight times: standing, four frames of the walk, and the wave. The head is twelve of 26 rows; the eyes are two by two with a highlight; the profile has a nose.

Sabotage’s gate, approve “just the idle frames turnaround” before animating, became our gate too: the first build of the rig was a boxy head on a boxy body, and three rounds of looking at it at ten times fixed the torso’s width (the arms had been overwriting its outline and merging with it), rounded the head into an oval, gave the profile a nose and the side arm its own inner outline, and rewrote the strides.32 All of that is grids in a Python file; the render-and-look loop is the whole method.

The wardrobe

A piece is a slot, an id, a name, one or more layers, a dye channel (and sometimes a second), and for a hat a hair rule. Its art on each layer is a list of two kinds of thing: Derived(region, rows), the body’s own pixels in that region between those rows recoloured into the piece’s channel at the same step, and Stamp({facing: grid at x, y}), pixels of the piece’s own placed on the standing figure and moved with the head and torso by the frame’s offset. A tee is one Derived of the torso below the neck and one of the arms’ first three rows. A hoodie is the long-sleeve derivation plus a stamped hood at the collar and a stamped front: two drawstrings in the second channel and a pouch pocket in the shade. A dress is the torso plus a stamped skirt block anchored to the ground, and it declares that it covers the bottom slot. Overalls are the inverse: the torso and the arms’ first three rows derived into the second channel as an undershirt, then the legs’ first five rows and a stamped bib with straps in the first.

That gives 47 wearable pieces in eight slots, ten counting skin and eyes, for the launch (51 manifest entries, counting “None” in the four slots that may be empty): ten hairstyles (short, crop, swept, long, buns, spikes, puff, locs, ponytail, bob; the long three split into a front and a back layer), eight hats (cap, beanie, visor, crown, bucket hat, headphones, hijab, bandana), eleven tops, four bottoms, four shoes, three pairs of glasses, four neck pieces and three back pieces; the held card is drawn for everyone in the raise frames and is not a piece. The counts are closer to New Horizons’ first day than to Stardew’s 74 hairstyles, on purpose; New Horizons grew its wardrobe by free updates, and that is the plan here.4452

Thirty-two looks rolled from one seed by the forge, every slot and dye at random, facing whichever way the dice said: the outfit-level check that no per-piece sheet can make.

Every hairstyle under every hat, facing down, at four times. Rows are hats (none, cap, beanie, visor, crown, bucket hat, headphones, hijab, bandana); columns are the ten hairstyles. The cap, beanie, bucket hat and bandana trim the hair above their brims; the hijab hides it; the visor, crown and headphones show it.

The hat rule is explicit art. A trim hat’s sheet carries eraser pixels, index 63, over everything above its brim within its span plus a one-pixel margin, written by the forge from the hat’s own silhouette; the app clears the hair planes wherever the hat plane says 63 before it lays the hat. The forge’s first contact sheet showed why the rule matters: without it, the buns’ side puffs stood out past the cap and the beanie on both sides.

Dyes

Fifty-two ramps in five families, skin (10), eyes (6), hair (12), cloth (16) and leather (8), each four steps, outline, shade, base, light; 32 of them are generated by one rule in the forge’s ramp(): the shade turns nine degrees toward violet at 68 percent of the value with a touch more saturation (times 1.05), the outline turns eighteen and drops to 40 percent, and the light turns nine degrees toward yellow, brighter and duller (saturation times 0.72); ten greys and near-blacks take a ramp of their own, a faint violet in the shadow and a faint warmth in the light; and the ten skin ramps are tuned by hand, each with its own warmth. Skin is hand-tuned per step so the light and deep tones keep their warmth. Every piece names its family, so a crown cannot be dyed denim (it is gold and takes no dye at all), and the hat and the top each take a second channel for trim. A check refuses any ramp that does not climb in CIE lightness by at least four L* per step.

The 52 dye ramps: five families, four steps each, from the forge's swatch sheet.

The manifest, the composer and the proof

figure.py writes 55 sheets (the body, the eyes, the held card, and one per piece per layer) and characters.json: the cell, the frames and the cycles the rig plays, the draw order per facing, the channels and dye families, every slot with its pieces and their art, hair rule, covers, tier and level, the head and hand anchors per frame, and the tables that turn the first build’s eight-integer look into a figure and back. The same file is copied into the server, whose tests hold the two copies to one SHA-256. Its checks run before anything ships: every sheet is the cell times the frames and facings, every index is one the manifest means, the outer ring of every cell is clear so an atlas can never bleed, the body’s lowest row is the sole row in every standing frame, names are unique per slot, and ids are append-only against the manifest in git.

The app’s CollectorComposer reads the planes once, composes a figure in the manifest’s order, applies the erasers to the hair and the hide rule to the hat, and expands through the table. The Swift test suite has a case that composes one figure (long hair, a hoodie, boots, a backpack) and compares every pixel with the image the forge composed for the same figure with its own Python composer: zero differing pixels, or the test fails. Everything else about the figure is tested in the same suite: the string’s canon and repair, the tier and level gates, the look bridge in both directions, that a cap trims the buns and a hijab hides them, that a dress covers trousers. One hundred and seventy-six tests passed in the app at build 21, the TestFlight build that shipped the character, fourteen in the server; build 22, uploaded the same day, carries the composer’s rewrite and its timing test (commit 4f7ff35, where the suite is 177) and a test added since for the show hall, 178 in all.

One figure through every frame, four facings by seventeen: the breath, the blink, the six-frame walk, the card raise with the card in the hand, the wave, the stretch. Long hair falls behind the shoulders facing down and over them facing up; the backpack's straps show from the front and the pack from behind.

The creator and the plaza

The creator replaced a 3D toy figure, a RealityView of spheres and boxes that previewed the look in a language the plaza never spoke, and a List of steppers in which the seventh of eight choices was six blind taps away. What a collector edits now is what walks.

The creator on an iPhone 18 Pro Max: the figure on lawn at a whole number of device pixels per texel, a chip per slot, the hats each shown on the collector's own figure with a lock on the Founder's crown, and swatches with spoken names for the cap's colour and trim.

In the plaza, the rig plays the breath at two frames a second, a blink every few seconds for an eighth of one, a stretch after five to fourteen seconds of standing, the walk at eight frames a second, and a wave when a line is said. The server’s four townsfolk were redressed in figures of their own, Moss in round glasses with a satchel, Prism in a cap and sunglasses, Comet in overalls with a backpack, Dawn in headphones and a scarf, and the capture below is the walk that passed against the live server, the figure repaired on the way in and the nearest old-style look sent back beside it for any build that still needs one.

The plaza on the iPhone 18 Pro Max, an unscaled capture, one image pixel per device pixel: the new figure standing on the stone square, the shadow under its feet, after saying a line.

What this build does not do yet

The honest list. The timings are Mac timings; the on-device numbers for forty walkers, and the LowLevelTexture atlas they would probably justify, are next. Asymmetric pieces (a side-swept fringe, a shoulder bag) still mirror when the collector turns; the forge supports a drawn right row and only the held card uses it so far. There is one idle tic, the stretch; the plan has four, chosen in the creator. There are no presets on first run, no saved outfits, and no mirror in the plaza that opens the creator where New Horizons would put one. Hair textures are drawn, not simulated; Madeline’s five-or-six-point chain stays a Celeste thing. And the figure is 26 pixels on 16-pixel tiles, 1.6 tiles tall where the first collector was 1.3; the houses, single tiles at build 21, got their own post later the same day: Pixel-Art Structures: Houses, Halls and Interiors on iPhone, with builds 22 and 23.

Key Takeaways

If you draw the people

  • Decide the band before the first pixel: chibi (60 to 67 percent head, 1-by-2 eyes, no mouth) for a handheld’s world or a 16-by-16 cell; RPG (38 to 54 percent, and a 2-by-2 eye once the cell is 16 by 32 or bigger); heroic (under 35 percent) only when a cape or a coat carries the silhouette.76
  • Approve the naked turnaround before any garment, as Sabotage does, because every piece inherits its grid; then draw the body as skin with a region map and derive clothes from it, so the artist draws only what changes a silhouette.328
  • Split what hangs into a back layer and a front layer, and write the hat rule down as data: show, trim or hide. The hat-times-hair contact sheet is the first thing to render and the last thing to look at.93410
  • Ship ramps, not colours: four steps per material, hue turning toward violet in the shadow and yellow in the light, picked from swatches.707136

If you build it on Apple platforms

  • Compose index planes and expand through one table; it is exact and it is a fifth of the cost of the old four-layer composition (two fifths of the marker-swap pass alone). Then measure texture creation, not composition: on a Mac a TextureResource is about half a millisecond, and forty at once is two frames at 60 Hz or three at 120; the iPhone numbers are still to be taken.18
  • Preview the real composite in SwiftUI with Image(decorative:), .interpolation(.none) and a TimelineView, at a whole number of device pixels per texel, and derive the frame from the timeline’s date.8081
  • Make the look a canonical string, repair it on read everywhere (app, record, server), keep ids append-only, and carry the old format beside the new until the old builds are gone.394041
  • Put the atlas (LowLevelTexture) and instanced shadows (MeshInstancesComponent) on the roadmap the day the room gets crowded, not before the on-device timing says so.1978

If you run the studio

  • Offer fewer things, all of them to everyone, and let identity change at a mirror: the Mii team removed parts on purpose, New Horizons was gender-free from day one, and GO’s body sliders drew clipping complaints within the week.111214
  • Keep every cosmetic purely visual, never random, never on a countdown, and never a button away from a preview: our rules, drawn from the FTC’s 2022 settlement with Epic, what PEGI has rated since June 2026, and the 2025 COPPA rule on sharing a child’s data for ads; none of the three bans random cosmetics or countdown offers outright, which is why these are rules we set rather than rules we were set.63176116
  • Let levels earn what money cannot buy. It is the one thing that keeps a patron tier from becoming a membership caste.5655

FAQ

How big should a pixel-art character be?

Pick the cell from the tile: the handheld Pokémon games put a 14-by-21 figure in a 16-by-32 cell on 16-pixel tiles; the SNES RPGs used 16 by 24 to 16 by 35; Stardew’s farmer is 16 by 32; Slynyrd’s hero is 26 wide by 32 tall, two 16-pixel tiles; our collector is 26 tall in a 32-by-32 cell, 1.6 tiles. Give the cell more width than the figure needs, because hats are wider than heads (Stardew’s are 20 pixels) and capes need room.12132634

How do you keep hair from poking through hats?

With a rule, not with art for every combination: Stardew’s per-hat flag (true, false, hide) and a lookup from hairstyles to a few under-the-brim shapes; Starbound’s per-hat mask.png; ours, eraser pixels baked into a trim hat’s sheet that the composer applies to the hair layers only.3410

Should a character creator use colour sliders or swatches?

Swatches, if the world has a palette. Stardew’s HSV sliders “allow any color,” which is fine for Stardew and fatal for a world drawn from fixed ramps; Larian expanded its swatches “so that there is something for everybody” rather than adding sliders, and the Mii team removed options so players would not be “at a total loss over which one to pick.”531311

What is the cheapest way to animate clothes on a sprite?

Derive them from the body. If the body carries a region map and a row index per part, a sleeve is “the arm’s first three rows from the shoulder” in every frame, including the raised arm, and the artist draws only the silhouette: a hood, a hem, a strap. Mana Seed gets the same guarantee by shipping every garment as a full sheet laid out like the body’s.8

Can you sell cosmetics in an app for children?

You can sell fixed, visible ones with the price and the contents stated first, and in Apple’s Kids Category only in a designated area behind a parental gate; you cannot sell random ones without disclosing odds on Apple, and a game with paid random items submitted to PEGI since June 2026 rates PEGI 16 (18 for social casino games); expiring log-in-streak rewards rate PEGI 7, and losing earned rewards or status for not returning rates PEGI 12; and tricking players into unwanted purchases is what the FTC made Epic refund $245 million for, beside a $275 million penalty for the privacy violations.151617

Why a figure string instead of a JSON object?

Because a canonical string is one value for three jobs, the saved record, the wire and the cache key, and because it can be repaired against the manifest without a change to the saved record’s shape: unknown slot ignored, unknown piece defaulted, unknown dye defaulted, ids never reused. Habbo’s avatars are type-set-colour strings, and the open-source emulator of its server repairs rather than rejects.3941

Related on this site: Pixel-Art Worlds on iPhone is the first guide in this series, with the tile systems, the palette rules and the RealityKit recipe this post builds on; iPhone Duo for Developers derives the inner display’s point size that the preview’s integer scale has to respect; Prepare Your App for iPhone Duo is the worked example of the fold and the HUD rules the plaza follows; RealityKit and the Spatial Mental Model is the grounding for the texture and material APIs in section 6; Metal 4 Essentials covers the API a LowLevelTexture atlas is written through; and Recreating MacPaint in the Browser is the last time I rebuilt a pixel renderer from a primary source.

Sources


  1. pret, pokeemerald/graphics/object_events/pics/people/brendan/walking.png and pokeemerald/src/data/object_events/object_event_graphics_info.h (.width = 16, .height = 32), accessed October 3, 2026, https://github.com/pret/pokeemerald/blob/master/graphics/object_events/pics/people/brendan/walking.png and https://github.com/pret/pokeemerald/blob/master/src/data/object_events/object_event_graphics_info.h. The figure size, the eye marks and the colour count are the author’s measurement of the first frame of the sheet (opaque = palette index ≠ 0), October 3, 2026. ↩↩↩↩

  2. pret, pokered/gfx/sprites/red.png and pokecrystal/gfx/sprites/chris.png, accessed October 3, 2026, https://github.com/pret/pokered/blob/master/gfx/sprites/red.png and https://github.com/pret/pokecrystal/blob/master/gfx/sprites/chris.png. Measured by the author from the first 16-by-16 frame (opaque = not white), October 3, 2026. ↩↩

  3. Stardew Valley Wiki, “Modding:Farmer sprite,” accessed October 3, 2026, https://stardewvalleywiki.com/Modding:Farmer_sprite. ↩↩↩↩↩↩↩↩↩↩

  4. veywrn, StardewValley/FarmerRenderer.cs (a third-party decompilation of the pre-1.6 game; featureYOffsetPerFrame = new int[126], featureXOffsetPerFrame = new int[126], hairstyleHatOffset = new int[16]), accessed October 3, 2026, https://github.com/veywrn/StardewValley/blob/3ff171b6e9e6839555d7881a391b624ccd820a83/StardewValley/FarmerRenderer.cs. ↩↩↩

  5. Seliel the Shaper, “Mana Seed Character Base,” itch.io, accessed October 3, 2026, https://seliel-the-shaper.itch.io/character-base. ↩↩↩↩↩

  6. Raymond Schlitter, “Pixelblog 22: Top-Down Character Sprites,” Slynyrd, October 21, 2019, accessed October 3, 2026, https://www.slynyrd.com/blog/2019/10/21/pixelblog-22-top-down-character-sprites. ↩↩↩

  7. Author’s measurements, October 2 and 3, 2026, from public rips and repositories at native scale (each file checked for exact integer upscaling and reduced by nearest neighbour; head counted from the top of the hair or hat to the chin, ±1 row): Terra, Crono and Lucca from the standing frames at videogamesprites.net (https://www.videogamesprites.net/FinalFantasy6/Party/Terra/, https://www.videogamesprites.net/ChronoTrigger/Party/Crono/, https://www.videogamesprites.net/ChronoTrigger/Party/Lucca/); Ness and Randi from the same archive’s EarthBound and Secret of Mana party pages; Abigail from the Stardew Valley Wiki’s sprite sheet (https://stardewvalleywiki.com/mediawiki/images/7/71/Abigail-sprite-sheet.png); Kayleigh from the Cassette Beasts wiki (https://wiki.cassettebeasts.com/images/e/e5/Kayleigh_world_idle_down.png); Ophilia from the Octopath Traveler wiki (https://static.wikia.nocookie.net/octopath-traveler/images/e/e1/Ophilia.png/revision/latest?format=original); the Drifter from the Hyper Light Drifter wiki (https://static.wikia.nocookie.net/hyperlightdrifter/images/b/bf/Drifter_Walking.gif/revision/latest?format=original); the Mana Seed base from its free demo. The Pokémon rows are notes 1 and 2. Rip timings reflect how each archivist built the GIF, not the game’s own tables. ↩↩↩↩↩

  8. Seliel the Shaper, “Mana Seed Farmer System,” itch.io, accessed October 3, 2026, https://seliel-the-shaper.itch.io/farmer-base. ↩↩↩↩↩↩

  9. Liberated Pixel Cup, Universal-LPC-Spritesheet-Character-Generator/scripts/zPositioning/z_positions.csv (tail_lizard,layer_1,85 and tail_lizard,layer_2,5), accessed October 3, 2026, https://github.com/LiberatedPixelCup/Universal-LPC-Spritesheet-Character-Generator/blob/master/scripts/zPositioning/z_positions.csv. ↩↩↩↩

  10. Starbounder, “Modding:Items/Armors,” accessed October 3, 2026, https://starbounder.org/Modding:Items/Armors. ↩↩↩↩↩

  11. Nintendo, “Iwata Asks: Wii Channels,” page 4 (the Mii Channel), accessed October 3, 2026, https://iwataasks.nintendo.com/interviews/wii/wii_channels/0/3/. ↩↩↩↩↩

  12. Chelsea Stark, “Animal Crossing: New Horizons includes skin tone options, gender-neutral hairstyles,” Polygon, June 12, 2019 (Wayback Machine capture of June 14, 2019), accessed October 3, 2026, https://web.archive.org/web/20190614010114/https://www.polygon.com/e3/2019/6/12/18662401/animal-crossing-new-horizons-e3-2019-character-customization-skin-tone-nintendo-switch. ↩↩↩

  13. Chris Kerr, “How the Baldur’s Gate 3 character creator brings modern flair to old school fantasy,” Game Developer, November 17, 2023, accessed October 3, 2026, https://www.gamedeveloper.com/art/building-an-inclusive-character-creator-for-the-fantasy-world-of-baldur-s-gate-3. ↩↩↩↩↩

  14. Joshua Robertson, “Pokemon Go Fans Are Furious Over Player Avatar Changes,” TheGamer, April 21, 2024, accessed October 3, 2026, https://www.thegamer.com/pokemon-go-player-avatar-update-bad/. ↩↩↩

  15. Apple, “App Review Guidelines,” sections 3.1.1 and 3.1.2, accessed October 3, 2026, https://developer.apple.com/app-store/review/guidelines/. ↩↩↩↩

  16. PEGI, “What do the labels mean?,” accessed October 3, 2026, https://pegi.info/what-do-the-labels-mean. ↩↩↩↩

  17. Federal Trade Commission, “Fortnite Video Game Maker Epic Games to Pay More Than Half a Billion Dollars over FTC Allegations of Privacy Violations and Unwanted Charges,” press release, December 19, 2022, accessed October 3, 2026, https://www.ftc.gov/news-events/news/press-releases/2022/12/fortnite-video-game-maker-epic-games-pay-more-half-billion-dollars-over-ftc-allegations. ↩↩↩↩

  18. Author’s benchmark, October 3, 2026: a Swift command-line harness compiled with swiftc -O on an Apple M2 Max under macOS 27 (Swift 6.4), 400 timed runs after 20 warm-ups, median and p95, run against Kiradex’s shipped layer PNGs at commit e7be8bd (144-by-128 sheets of 16-by-32 cells). “Today” is a line-for-line copy of the app’s marker-swapping composer; “index planes” compose 8-bit planes and expand them through a 256-entry table; the texture rows time TextureResource(image:options:), TextureResource.replace(withImage:options:), MTLTexture.replace(region:mipmapLevel:withBytes:bytesPerRow:) into a 2304-by-1024 shared atlas, and LowLevelTexture.replace(using:) with a blit. The harness and its output are in the project’s research record (docs/research/characters/02). These are Mac numbers; no iPhone was timed. The shipped-sheet composer timing is a second harness of the same kind, run the same day against Resources/World/fig-*.png (544-by-128 sheets, thirteen planes worn, 56,085 opaque pixels across them, 400 runs after 20 warm-ups) on the same Mac while idle: compose 26.5 to 26.8 µs median across three runs (p95 31 to 32 µs), compose and table expansion 71.5 µs (p95 81 µs); an earlier run, run 1 in the record, taken while Xcode was compiling alongside gave 72.7 and 207.5 µs, which is why the machine’s state is recorded. The Debug-build simulator figures are the medians of 20 from CharacterTests.theComposerIsCheapOnTheShippedSheets on an iPhone 18 Pro Max simulator. The harness’s code, every run’s output and the record of the first, slower composer are in the project’s research record (docs/research/characters/03-composer-timings.md). ↩↩↩↩

  19. Apple Developer Documentation, “LowLevelTexture.replace(using:),” accessed October 3, 2026, https://developer.apple.com/documentation/realitykit/lowleveltexture/replace(using:). ↩↩↩

  20. pret, pokeemerald/src/data/object_events/object_event_anims.h (.hFlip = TRUE on the east-facing frames), accessed October 3, 2026, https://github.com/pret/pokeemerald/blob/master/src/data/object_events/object_event_anims.h. ↩↩

  21. FF6hacking Wiki, “Sprites (FF3us tutorial),” accessed October 3, 2026, https://www.ff6hacking.com/wiki/doku.php?id=ff3%3Aff3us%3Atutorial%3Asprites. ↩↩

  22. videogamesprites.net, “Chrono Trigger: Lucca” (72 GIF files, including Lucca - Glasses (Front).gif, two frames of 200 milliseconds each, 16 by 32 at native scale by the author’s measurement, October 3, 2026), accessed October 3, 2026, https://www.videogamesprites.net/ChronoTrigger/Party/Lucca/. ↩↩

  23. UNIQLO, “A Conversation with 6 Creators on the 35th Anniversary of the Final Fantasy series, Part 1,” UT magazine, accessed October 3, 2026, https://www.uniqlo.com/jp/en/contents/feature/ut-magazine/s134/. ↩

  24. Jenni Lada, “Interview: Discussing Final Fantasy Pixel Remaster Sprites and Designs,” Siliconera, August 31, 2021, accessed October 3, 2026, https://www.siliconera.com/interview-discussing-final-fantasy-pixel-remaster-sprites-and-designs/. ↩↩

  25. Epic Games, “Octopath Traveler II builds a bigger, bolder world in its stunning HD-2D style,” developer interview with Acquire (Wayback Machine capture, 2023), accessed October 3, 2026, https://web.archive.org/web/2023/https://www.unrealengine.com/en-US/developer-interviews/octopath-traveler-ii-builds-a-bigger-bolder-world-in-its-stunning-hd-2d-style. ↩

  26. Raymond Schlitter, “Pixelblog 55: Top-Down Character Animation,” Slynyrd, March 31, 2025, accessed October 3, 2026, https://www.slynyrd.com/blog/2025/3/24/pixelblog-55-top-down-character-animation. ↩↩↩↩↩↩

  27. Pedro Medeiros (saint11), “Character Idle,” pixel-art tutorial (an image; the quoted lines are its captions, lower-cased here), from the tutorials index at https://saint11.art/blog/pixel-art-tutorials/, image at https://saint11.art/img/pixel-tutorials/characterIdle.gif, accessed October 3, 2026. ↩↩↩

  28. Raymond Schlitter, “Pixelblog 58: Top-Down Character Animation, Part 3,” Slynyrd, October 4, 2025, accessed October 3, 2026, https://www.slynyrd.com/blog/2025/10/2/pixelblog-58-top-down-character-animation-part-3. ↩

  29. Noel Berry (NoelFB), comments in the r/gamedev thread “Celeste’s hair” (Reddit id 9a0cfr), read through the PullPush archive API, accessed October 3, 2026, https://www.reddit.com/comments/9a0cfr/ and https://api.pullpush.io/reddit/search/comment/?link_id=9a0cfr&size=100. ↩↩

  30. Noel Berry, Celeste/Source/Player/Player.cs (NormalHairColor, UsedHairColor, TwoDashesHairColor, the 0.12-second flash), accessed October 3, 2026, https://github.com/NoelFB/Celeste/blob/master/Source/Player/Player.cs. ↩

  31. Alana Hagues, “‘I Don’t Want To Copy’ - Paying Homage To Childhood RPGs With Sea Of Stars,” Nintendo Life, August 26, 2023, accessed October 3, 2026, https://www.nintendolife.com/features/i-dont-want-to-copy-paying-homage-to-childhood-rpgs-with-sea-of-stars. ↩

  32. Ben Brosofsky, “Sea of Stars Thierry Boulanger Interview: Aiming At ‘Holding Up Amidst All These Classics’,” Screen Rant, August 29, 2023, accessed October 3, 2026, https://screenrant.com/sea-stars-interview-thierry-boulanger/. ↩↩↩

  33. Thomas Vasseur, “Art Design Deep Dive: Using a 3D pipeline for 2D animation in Dead Cells,” Game Developer, accessed October 3, 2026, https://www.gamedeveloper.com/production/art-design-deep-dive-using-a-3d-pipeline-for-2d-animation-in-i-dead-cells-i-. ↩

  34. Stardew Valley Wiki, “Modding:Hats,” accessed October 3, 2026, https://stardewvalleywiki.com/Modding:Hats. ↩↩↩↩↩↩↩

  35. Liberated Pixel Cup, PALETTE_RECOLOR_GUIDE.md, accessed October 3, 2026, https://github.com/LiberatedPixelCup/Universal-LPC-Spritesheet-Character-Generator/blob/master/PALETTE_RECOLOR_GUIDE.md. ↩↩

  36. Liberated Pixel Cup, “LPC Style Guide,” accessed October 3, 2026, https://lpc.opengameart.org/static/LPC-Style-Guide/build/styleguide.html. ↩↩↩↩↩

  37. Starbounder, “Dye,” accessed October 3, 2026, https://starbounder.org/Dye. ↩

  38. tModLoader, patches/tModLoader/Terraria/DataStructures/PlayerDrawLayers.tML.cs (branch 1.4.4) and the ArmorShaderData class reference, accessed October 3, 2026, https://github.com/tModLoader/tModLoader/blob/1.4.4/patches/tModLoader/Terraria/DataStructures/PlayerDrawLayers.tML.cs and https://docs.tmodloader.net/docs/stable/class_armor_shader_data.html. ↩

  39. billsonnn, nitro-renderer/src/nitro/avatar/AvatarFigureContainer.ts (figure.split('.'), part.split('-')) and src/api/nitro/avatar/enum/AvatarFigurePartType.ts, accessed October 3, 2026, https://github.com/billsonnn/nitro-renderer/blob/main/src/nitro/avatar/AvatarFigureContainer.ts and https://github.com/billsonnn/nitro-renderer/blob/main/src/api/nitro/avatar/enum/AvatarFigurePartType.ts. ↩↩↩↩↩

  40. billsonnn, nitro-renderer/src/nitro/avatar/AvatarRenderManager.ts (hd-99999-99999), accessed October 3, 2026, https://github.com/billsonnn/nitro-renderer/blob/main/src/nitro/avatar/AvatarRenderManager.ts. ↩↩

  41. duckietm, Polaris-Emulator/.../clothingvalidation/ClothingValidationManager.java (a fan emulator, not Habbo’s own server), accessed October 3, 2026, https://github.com/duckietm/Polaris-Emulator/blob/34bc0d49511c659fd0054d35d957669ebd6ce9ed/Emulator/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/ClothingValidationManager.java. ↩↩↩↩↩

  42. Floogen, Fashion Sense wiki, “Hat Model Properties” and “Animation Properties,” accessed October 3, 2026, https://github.com/Floogen/FashionSense/wiki/Hat-Model-Properties and https://github.com/Floogen/FashionSense/wiki/Animation-Properties. ↩↩

  43. Habbo, figuredata (the live XML; <hiddenlayers> on sets), accessed October 3, 2026, https://www.habbo.com/gamedata/figuredata/1. ↩

  44. Nookipedia, “Hairstyle,” accessed October 3, 2026, https://nookipedia.com/wiki/Hairstyle. ↩↩↩

  45. Nookipedia, “Skin tone,” accessed October 3, 2026, https://nookipedia.com/wiki/Skin_tone. ↩↩

  46. Nookipedia, “Player,” accessed October 3, 2026, https://nookipedia.com/wiki/Player. ↩

  47. Serebii, “Pokémon X & Y: Trainer Customisation,” accessed October 3, 2026, https://www.serebii.net/xy/customisation.shtml. ↩↩

  48. Bulbapedia, “Boutique” (Wayback Machine capture of February 29, 2024), accessed October 3, 2026, https://web.archive.org/web/20240229231843/https://bulbapedia.bulbagarden.net/wiki/Boutique. ↩↩

  49. Serebii, “Pokémon Scarlet & Violet: Trainer Customisation,” accessed October 3, 2026, https://www.serebii.net/scarletviolet/customisation.shtml. ↩↩

  50. Jess Denham, “Pokémon Go praised by gamers for introducing gender fluid avatars,” The Independent, July 12, 2016 (Wayback Machine capture of July 15, 2016), accessed October 3, 2026, https://web.archive.org/web/20160715141358/http://www.independent.co.uk/arts-entertainment/pokemon-go-praised-by-gamers-for-introducing-gender-fluid-avatars-characters-players-lgbt-style-a7132536.html. ↩

  51. Niantic, “Rediscover GO” (Wayback Machine capture of August 17, 2024), accessed October 3, 2026, https://web.archive.org/web/20240817154334/https://pokemongolive.com/rediscovergo?hl=en. ↩

  52. Stardew Valley Wiki, “The Player,” accessed October 3, 2026, https://stardewvalleywiki.com/The_Player. ↩↩↩

  53. Stardew Valley Wiki, “Dyeing,” accessed October 3, 2026, https://stardewvalleywiki.com/Dyeing. ↩↩↩

  54. Ben Johnson, “Making monsters out of myths with the Cassette Beasts dev,” Pocket Tactics, March 16, 2023, accessed October 3, 2026, https://www.pockettactics.com/cassette-beasts/interview. ↩↩

  55. Habbo Wiki (Fandom), “Habbo Club” (Wayback Machine capture of August 7, 2025), accessed October 3, 2026, https://web.archive.org/web/20250807073545/https://habbo.fandom.com/wiki/Habbo_Club. ↩↩↩

  56. Club Penguin Wiki (Fandom), “Clothing” (Wayback Machine capture of December 22, 2024), accessed October 3, 2026, https://web.archive.org/web/20241222055028/https://clubpenguin.fandom.com/wiki/Clothing. ↩↩↩

  57. Apple, Human Interface Guidelines, “Designing for games,” accessed October 3, 2026, https://developer.apple.com/design/human-interface-guidelines/designing-for-games. ↩

  58. Apple, Human Interface Guidelines, “Onboarding,” accessed October 3, 2026, https://developer.apple.com/design/human-interface-guidelines/onboarding. ↩

  59. Apple, App Store Connect Help, “Age ratings values and definitions,” accessed October 3, 2026, https://developer.apple.com/help/app-store-connect/reference/app-information/age-ratings-values-and-definitions/. ↩

  60. Information Commissioner’s Office, “Age appropriate design: a code of practice for online services,” standard 5, “Detrimental use of data,” accessed October 3, 2026, https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/5-detrimental-use-of-data/. ↩

  61. Federal Trade Commission, “FTC Finalizes Changes to Children’s Privacy Rule Limiting Companies’ Ability to Monetize Kids’ Data,” press release, January 2025, accessed October 3, 2026, https://www.ftc.gov/news-events/news/press-releases/2025/01/ftc-finalizes-changes-childrens-privacy-rule-limiting-companies-ability-monetize-kids-data. ↩↩

  62. Niantic, Pokémon GO Help Center, “How do I customize my Avatar?,” accessed October 3, 2026, https://niantic.helpshift.com/hc/en/6-pokemon-go/faq/2376-customizing-your-avatar/. ↩

  63. Innersloth, “New Roles & Cosmicubes - Out Now | Emergency Meeting #33,” November 9, 2021, accessed October 3, 2026, https://www.innersloth.com/new-roles-cosmicubes-out-now-emergency-meeting-33/. ↩↩

  64. Stardew Valley Wiki, “Hat Mouse” (“A new hat will appear in the shop whenever an achievement is earned”), accessed October 3, 2026, https://stardewvalleywiki.com/Hat_Mouse. ↩

  65. Li BJ, Lwin MO, Jung Y, “Wii, Myself, and Size: The Influence of Proteus Effect and Stereotype Threat on Overweight Children’s Exercise Motivation and Behavior in Exergames,” Games for Health Journal (2014), PubMed 26197254, abstract accessed October 3, 2026, https://pubmed.ncbi.nlm.nih.gov/26197254/. ↩

  66. Hao L, Su Y, Jiang Q, “Avatar identification mediates the relationship between avatar attractiveness and self-objectification among young MOBA players,” BMC Psychology 13 (2025), PubMed 41088483, abstract accessed October 3, 2026, https://pubmed.ncbi.nlm.nih.gov/41088483/. ↩

  67. Frazer MT et al., “Active Play in a Digital Age, Exploring Children’s (Aged 8-13 Years) Views of a Physical Activity App: Qualitative Formative Study,” JMIR Formative Research 9 (2025), PubMed 41218109, abstract accessed October 3, 2026, https://pubmed.ncbi.nlm.nih.gov/41218109/. ↩

  68. Unicode Consortium, “Unicode Technical Standard #51: Unicode Emoji,” section on emoji modifiers, accessed October 3, 2026, https://www.unicode.org/reports/tr51/. ↩

  69. Blake Crosley, “Pixel-Art Worlds on iPhone: What the 16-Bit Masters Knew,” blakecrosley.com, October 3, 2026, https://blakecrosley.com/blog/pixel-art-world-on-iphone. ↩↩

  70. Raymond Schlitter, “Pixelblog 1: Color Palettes,” Slynyrd, January 16, 2018, accessed October 3, 2026, https://www.slynyrd.com/blog/2018/1/10/pixelblog-1-color-palettes. ↩↩

  71. Pedro Medeiros (saint11), “6 - Basic Color Theory,” pixel art articles, accessed October 3, 2026, https://saint11.art/pixel_art_articles/article6/. ↩↩

  72. Apple, Human Interface Guidelines, “Color,” accessed October 3, 2026, https://developer.apple.com/design/human-interface-guidelines/color. ↩

  73. Nookipedia, “Clothing,” accessed October 3, 2026, https://nookipedia.com/wiki/Clothing. ↩

  74. Aseprite, “Color Mode,” documentation, accessed October 3, 2026, https://www.aseprite.org/docs/color-mode/. ↩

  75. Apple Developer Documentation, “CGColorSpace.init(indexedBaseSpace:last:colorTable:),” accessed October 3, 2026, https://developer.apple.com/documentation/coregraphics/cgcolorspace/init(indexedbasespace:last:colortable:). ↩

  76. Apple Developer Documentation, “TextureResource.replace(withImage:options:),” accessed October 3, 2026, https://developer.apple.com/documentation/realitykit/textureresource/replace(withimage:options:). ↩

  77. Apple, “Build a spatial drawing app with RealityKit,” WWDC24 session 10104, transcript, accessed October 3, 2026, https://developer.apple.com/videos/play/wwdc2024/10104/. ↩

  78. Apple Developer Documentation, “MeshInstancesComponent,” accessed October 3, 2026, https://developer.apple.com/documentation/realitykit/meshinstancescomponent. ↩↩

  79. Apple Developer Documentation, “Reducing CPU utilization in your RealityKit app,” accessed October 3, 2026, https://developer.apple.com/documentation/realitykit/reducing-cpu-utilization-in-your-realitykit-app. ↩

  80. Apple Developer Documentation, “Image.Interpolation.none,” accessed October 3, 2026, https://developer.apple.com/documentation/swiftui/image/interpolation/none. ↩↩

  81. Apple Developer Documentation, “TimelineView,” accessed October 3, 2026, https://developer.apple.com/documentation/swiftui/timelineview. ↩↩↩

  82. Apple, Human Interface Guidelines, “Buttons,” accessed October 3, 2026, https://developer.apple.com/design/human-interface-guidelines/buttons. ↩

  83. Roblox Creator Documentation, “Character specifications,” accessed October 3, 2026, https://create.roblox.com/docs/art/characters/specifications. ↩

  84. Roblox Creator Documentation, “Layered clothing,” accessed October 3, 2026, https://create.roblox.com/docs/art/accessories/layered-clothing. ↩

相关文章

Pixel-Art Structures: Houses, Halls and Interiors on iPhone

How Pokémon, the SNES RPGs and Stardew build houses, interiors and floors, measured from source, and how Kiradex's town …

73 分钟阅读

Pixel-Art Worlds on iPhone: What the 16-Bit Masters Knew

How Final Fantasy VI, Pokémon and today's best pixel-art games were made, the rules that follow, and a tested recipe for…

61 分钟阅读

Designing for iPhone Duo: What Moves, Splits, and Stays

Apple's iPhone Duo design guide and three Tech Talks, read as rules: two size classes instead of poses, displacement at …

23 分钟阅读