Emoji Aimer 4
Summary
Built out the entire shop UI for Emoji Aimer iteratively, element by element, culminating in wired-up buy logic with full game-state integration. Worked entirely in emoji-aimer/main.lua (Anchor 2 framework). The session followed a "tune each element in isolation/context, then move to the next" pattern.
Initial scoping & shop mockup critique:
- User shared a Pixel Mart UI mockup (Deadlock-inspired). Provided detailed critique on density vs action-pause context, three-panel chrome consumption, ambiguous "Your Items" vs "Backpack" distinction, redundant compare/detail panels, etc.
- Established design constraints: click-to-continue (no time pressure), no rerolls, no compare panel, no rarity, no selling, all items available from start (price-gated), no actives (all passive items), no inventory hierarchy.
Shop state machine refactor:
- Refactored game state to cleanly separate round vs shop. Extracted
clear_entities()helper. Addedstart_shop()mirroringstart_round(idx).advance_round()now delegates tostart_shop(). - Bootstrap replaced inline
try_spawn_targetloop withround_index = 0; start_shop(). Convention:round_index = 0means "before round 1" (shop UI readsround_index + 1as upcoming round). - Removed the fullscreen dim overlay from the shop draw block (was
color(0,0,0,180)). - Gated wall rendering on
game_state ~= 'shop'so walls don't appear during shop.
Emoji asset download (28 emojis @ 512x512 Twemoji):
- Emojipedia CDN (
em-content.zobj.net) returned 403 to all probes. Discovered wsrv.nl image proxy works as an SVG-to-PNG rasterizer:https://wsrv.nl/?url=https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/<hex>.svg&w=512&h=512&output=png. - Downloaded 16 new shop emojis: shield, crossed_swords, bow_and_arrow, magic_wand, red_heart, four_leaf_clover, magnet, skull, bomb, feather, eye, test_tube, coffee, hot_pepper, bone, locked.
- Re-downloaded coin/gem/crown at 512x512 (were 256). Later also loaded sparkles, collision as items.
UI kit element implementation:
- Item tile (48x48 initially, then 48x56, then 48x48 with banner): rounded card frame, emoji, banner (yellow/green/gray for available/owned/unaffordable). Banner uses notch-fill trick because
layer_rounded_rectangledoesn't support per-corner radius. - Tooltip: yellow header band with name + right-aligned price chip, body with stat lines + description. Same notch-fill on header's bottom corners. Uses dedicated
ui_top_panel_layer/ui_top_content_layerso outline shader treats tooltip as separate silhouette from tile beneath. - Tier selector: evolved from 4 individual button-style tabs into single strip with internal segment dividers (segmented-control style). Active segment uses notch-fill to round outer corners on first/last segments. Dividers adjacent to active segment hidden so the active fill reads as continuous.
- Owned-items column: 2x6 = 12 slots of 28x28 with 16x16 emoji inside. Each filled slot has level badge (blue keycap digit) at top-left corner.
- Button: rounded rect with primary (green) / secondary (fg) variants and default/hovered/disabled states.
Hover interaction system:
- Each hover-able element (tile, slot, button, tab) has
shake(handcam for continuous wobble),spring(hover-enter scale pulse),hover_amount(smooth 0..1 lerp). - Shared
init_hover_state(el)helper sets up all three. Sharedupdate_hover_element(el, mx, my, dt)ticks them and returns hovered state. - Cursor gets sympathetic
flash_hover()(spring pulse 0.05) on any hover-enter event. Later addedflash_error()(swap to x_mark_img + spring pulse 0.3 + 0.4s timer revert). - Wobble mode
SHOP_KIT_WOBBLE_MODE = 'card' | 'emoji'controls whether the whole tile wobbles or just the icon. Settled on 'card'.
Pixel-art rendering fixes:
- Subpixel text rendering bug: "SWORD" and "OWNED" displayed with broken glyph spacing. Root cause:
font_get_text_widthreturns integer widths, but odd widths divided by 2 (-lbl_w/2) produce fractional positions. Each glyph snapped to a different integer column with nearest-neighbor sampling. Fix:math.floor(-lbl_w/2). - Banner text +1 vertical nudge: combined with LanaPixel's "high in its box" +1 to produce text_y =
math.floor(banner_y + banner_h/2 - 11/2 + 1) + 1(effectively +2 from raw center). - Spring scale on text caused choppy rendering during pulse. Solution: scale only the panel push, draw text at absolute integer positions outside the push. Applied to tabs, buttons, level badges.
Custom shaders:
assets/grayscale.frag: luminance-based desaturation (0.299*r + 0.587*g + 0.114*b), preserves alpha. Createdgrayscale_layerintermediate. Unaffordable tile emojis routed there, thenlayer_draw_from(ui_content_layer, grayscale_layer, grayscale_shader)in the draw pipeline before outline derivation. Heart emoji turns true gray (not just dimmed red).- Level-badge recolor pass: reuses existing
recolor_shaderwith blue target color (palette(83,175,239)). Keycap digit emojis drawn toshop_level_layer, pulled through with blue uniform ontoui_content_layer.
Layout evolution:
- Started with stacked elements in scattered positions.
- Grid evolved: 4 forced-state tiles, then 9x4 = 36 grid, then 9x3 = 27, then 7x3 = 21, then 5x4 = 20 with larger gaps (4 to 8). Settled on 5x4 with 8px gap.
- Owned column moved from left to right side (centered in x=368..480 area at x=393, mirroring slot placement).
- Shop/gold elements moved from right to left side. Center at x=48 (full left-area midpoint, not the original x=52 which was asymmetric with the slots' centering).
- Tier strip moved from y=4 to y=8 so strip-to-grid gap matches grid cell gap of 8.
- Shop frame: rounded rect at (13, 8) with width 70, height 34, containing "SHOP" title (mid font) and dynamic "ROUND 1/5" subtitle (reads
round_index + 1and#ROUNDS). - NEXT ROUND button moved to right at y=244 (8px from screen bottom matches 8px from screen top to frame top). Width 70.
Top UI layer separation:
- Created
ui_top_panel_layer/ui_top_content_layer(and outline derivatives) for elements that render above regular UI. Currently used by tooltip. Composite order:ui_panel, ui_content, ui_top_panel, ui_top_content, overlay, cursor, transition. Camera attach mirrors regular UI layers (gated ongame_state ~= 'shop').
Final buy logic implementation:
- Removed all hardcoded demo data:
SHOP_KIT_OWNED,SHOP_KIT_UNAFFORDABLE,SHOP_OWNED_DEMO,SHOP_OWNED_LEVELS, and thebase_statefield on tiles. - Tile state now derived per frame:
affordable = gold >= t.item.pricedrives banner color, frame color, grayscale routing. - New helper functions:
shop_kit_find_owned_slot_with(item),shop_kit_find_empty_owned_slot(),shop_kit_error(tile),shop_kit_level_up_effect(slot),shop_kit_try_buy(tile). - Buy flow: skip if sold; find existing slot (level-up) or empty slot (new); error if no slot or insufficient gold; deduct gold, set/increment level, init_hover_state on freshly-filled slot, mark tile sold.
- Error feedback: red frame flash (0.3s), horizontal decaying sine shake (
sin(p*pi*8)*decay*5px, 4 oscillations), cursor X-mark swap. - Level-up effect: 8 blue
hit_particlesspawn at the slot's badge position with random velocity 40-100 and duration 0.3-0.5s. Reuses existingspawn_hit_particleinfrastructure. - Gold chip binds to real
goldglobal via newformat_with_commas(n)helper. Bootstrap setsgold = 5000for kit testing. - Sold tiles render as
fg_darkrounded rect (matchesSHOP_KIT_EMPTY_CELLSstyle). Switching tiers rebuilds grid, resetting sold state.
User feedback / notable corrections:
- "FatFont at size 8 is actually very big" -> switched OWNED label from
fonts.big(FatPixelFont @ 8) tofonts.main(LanaPixel @ 11). - "Use a shader to turn the heart into actual grayscale" -> created the grayscale.frag shader instead of relying on multiplicative tint.
- "Lower width on shop frame, move tier tab down such that distance between its bottom and the top of the start of the grid is the same as the spacing between grid units" -> tier strip moved to y=8, grid spacing math unified at 8px.
- "Move shop and gold frame to the left, they don't seem to be centered like the slots are" -> discovered the slots were centered in x=368..480 (full right area) while the left elements were centered in x=8..96 (with margin). Fixed by moving left center from 52 to 48 to mirror the slot centering.
- "The text inside each tier has the same problem as the text inside buttons had before" -> fixed by drawing labels at absolute integer positions outside the spring-scaled push.
Let's continue with Emoji Aimer. I added an UI mockup to reference/ called ui_shop. Read it and tell me what you think about it. It's based on Deadlock's shop UI and I think it looks reasonably OK for what we'll probably want to achieve. But tell me more.
Glob (/emoji-aimer/)
emoji-aimer\anchor\class.lua
emoji-aimer\anchor\object.lua
emoji-aimer\anchor\spring.lua
emoji-aimer\anchor\timer.lua
emoji-aimer\anchor\math.lua
emoji-aimer\anchor\color.lua
emoji-aimer\anchor\camera.lua
emoji-aimer\anchor\shake.lua
emoji-aimer\anchor\image.lua
emoji-aimer\anchor\spritesheet.lua
emoji-aimer\anchor\helpers.lua
emoji-aimer\anchor\animation.lua
emoji-aimer\anchor\input.lua
emoji-aimer\anchor\layer.lua
emoji-aimer\anchor\init.lua
emoji-aimer\anchor\physics.lua
emoji-aimer\anchor\collider.lua
emoji-aimer\anchor\memory.lua
emoji-aimer\anchor\font.lua
emoji-aimer\anchor\array.lua
emoji-aimer\anchor.exe
emoji-aimer\assets\shadow.frag
emoji-aimer\assets\outline.frag
emoji-aimer\assets\LanaPixel.ttf
emoji-aimer\assets\star.png
emoji-aimer\assets\collision.png
emoji-aimer\assets\sparkles.png
emoji-aimer\run.bat
emoji-aimer\assets\direct_hit.png
emoji-aimer\assets\backhand_index_pointing_up.png
... [71 more lines]
Glob (emoji-aimer/reference/ui_shop*)
No files found
Glob (emoji-aimer/reference/shop)
emoji-aimer\reference\ ui_shop.png
There's a stray leading space in the filename — " ui_shop.png". Reading it now.
Read (E:\a327ex\emoji-aimer\reference\ ui_shop.png)
[
{
"type": "image",
"source": {
"type": "base64",
"data": "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",
"media_type": "image/jpeg"
}
}
]
Let me also peek at the existing UI mockup and any design notes so my critique is grounded.
Read (E:\a327ex\emoji-aimer\reference\ui_mockup.html)
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>Emoji Aimer — UI Mockup</title>
6 <link rel="preconnect" href="https://fonts.googleapis.com">
7 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
8 <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Pixelify+Sans:wght@400;600&display=swap" rel="stylesheet">
9 <style>
10 /* ===========================================================================
11 CANONICAL PALETTE (matches main.lua exactly — these are the ground truth)
12 ----------------------------------------------------------------------------
13 Source-of-truth: emoji-aimer/main.lua palette block. Image-derived additions
14 noted with "* added".
15 =========================================================================== */
16 :root {
17 /* core neutrals */
18 --c-white: #ffffff; /* white (255, 255, 255) */
19 --c-black: #000000; /* black ( 0, 0, 0) */
20 --c-gray: #808080; /* gray (128, 128, 128) */
21 --c-bg: #303132; /* bg_color (dark bg) ( 48, 49, 50) */
22 --c-fg: #e7e8e9; /* fg (panel) (231, 232, 233) */
23 --c-fg-dark: #c9cacb; /* fg_dark (secondary) (201, 202, 203) */
24
25 /* hue families (Twitter-emoji aligned) */
26 --c-yellow: #fdcd56; /* yellow (253, 205, 86) */
27 --c-orange: #f49200; /* orange (244, 146, 0) */
28 --c-red: #df2540; /* red (223, 37, 64) */
29 --c-blue: #53afef; /* blue ( 83, 175, 239) */
30 --c-green: #7ab357; /* green (122, 179, 87) */
... [90 more lines]
Glob (emoji-aimer/design*.md)
No files found
Glob (emoji-aimer/*.md)
No files found
Glob (emoji-aimer/reference/*.md)
No files found
The image came through. Quick read of the layout before I get into the critique: three columns — Filters / Shop grid (Tier 1–4 tabs, 4×3 cards, selected-item detail strip below) / Inventory (Your Items 4×2, Backpack 6/8, Compare panel, Sell button, Total Value). Gold counter top-left, Reroll bottom-left, locked tiers 3–4. The Deadlock DNA is obvious and it reads cleanly. Here's the longer take.
What works
The three-pane mental model is the right pick. Filters | shop | inventory-with-compare is a convention literally every shop-game player has internalized (Dota, Deadlock, Diablo, STS shops). You get free legibility just by following it. People will know where to look on first sight.
Tier tabs with locks are doing real work. They double as pacing gates (you can't impulse-buy Tier 3 in round 2), as a forced-relevance filter (only items appropriate to current power level shown by default), and as a teaching surface (locks tell new players "more is coming"). Cheap and strong.
The Candidate / Equipped compare block at the bottom-right is the single most important element on the screen, and you've given it real estate. Surfacing the delta (or at least the side-by-side) is what separates a good shop from one where players just pick whatever has the highest number. Deadlock does this well; you're aimed at it.
Filter set is exactly the three that earn their keep. Show Owned / Affordable Only / On Sale. Resist adding a fourth.
Palette discipline. Yellow gold, blue accents, FG panel cards, black outlines, drop shadows — reads as a continuous artifact with the rest of the game. Nothing looks pasted in from another aesthetic.
What I'd push back on
Density vs. session length. Deadlock's shop is a full-screen modal opened while you stand on the shop pad with seconds-to-minutes of breathing room. If Emoji Aimer's shop appears between short waves, this is a wall of information to parse cold. What's the expected shop-session duration? If it's "until the player clicks Continue" you're fine. If it's a ~10s breather, this density will feel like homework. Worth deciding before you build it because it cascades into card size, default sort, and whether the filter rail is even visible by default.
The Filters/Categories column eats screen budget for something the player touches rarely. Most players will use the tier tabs and ignore Categories 80% of the time. Consider making the left rail a collapsible drawer that defaults closed once the player has played past tutorial — that buys you a wider shop grid (maybe 5–6 cards per row instead of 4) which is where the eye actually lives.
"Your Items" vs "Backpack" — what's the gameplay distinction? From the mockup alone it's not legible. Is backpack a stash? Loadout-but-inactive? Held-but-disabled-during-fight? If it's a real mechanic it needs a label that earns itself; if it's stash, just call it Stash. If it's "purchased but not equipped to an active slot", that's a deep system and I'd want to know it's worth the complexity for the scope of this game. Right now both grids look identical visually, which means the player will assume they're the same thing and be confused when one of them does something different.
Quick Buy looks tacked on. Two slots squeezed next to the title, no clear function shown. Either give it a row of its own (4–6 slots, a recognizable affordance) or cut it. Half-committed UI tells the player "we weren't sure either."
Reroll is buried. Bottom-left corner is the lowest-traffic zone on the screen. Reroll is a high-frequency action in this genre — players reroll constantly. Put it near the shop grid (top-right of the middle column, mirror-symmetrical to the Tier tabs maybe?) and give the price a state when the player can/can't afford it.
Categories axis competes with Tiers axis. Right now they're both equal-weight navigation. If a player wants "Damage tier 2" they're clicking twice. Deadlock's trick is to encode category as a color/badge on the item itself (purple/orange/green) and let Tier be the only tab. Worth considering whether Category should retire from the sidebar and become a corner stripe on each card.
Selected-item card at the bottom of the middle column duplicates the right-side Compare panel. Both show SMILE + utility tag + description + buy. Pick one source of truth for "what is this item I'm looking at." Recommendation: kill the middle-column detail card, let the compare panel on the right be the single canonical "tell me about this hovered item" surface. That also frees a full row of grid space — you go from 12 items shown to 16 or so.
Compare panel is text-heavy. Five stats × two columns × labels is a lot of tokens to parse fast. A single Δ column (
Heal +2,Shield Gain +5,Damage 0, color-coded green/red/gray) reads in a third the time. Or tiny inline bar deltas. The current layout makes the player do subtraction in their head, which is exactly what compare UIs exist to eliminate.All prices are 200 or 300 in the mockup. Likely placeholder, but it means you haven't pressure-tested the layout against "1,250" or "10". When you drop in real numbers, check that the gold chip still fits without shrinking text or breaking the card.
No rarity, no build-marker / favorite affordance. Two questions worth deciding now: (a) Do items have rarity (common/rare/legendary) visualized? (b) Can the player favorite / wishlist items to plan a build? Both are common in this shape of game and both want a place in the card design. If the answer to both is "no, that's not the design," fine — but worth saying out loud so the mockup is intentionally that lean and not just unfinished.
Open questions I'd want answered before I'd build this
- How long is a shop session and what triggers it (between waves, between runs, manual)?
- What's the actual distinction between Your Items and Backpack?
- How many items per tier exist in the pool? (Affects whether rerolls + filters make sense, or whether the whole tier fits on screen.)
- Is the shop appearing during a paused game, or in a meta-screen?
- Is there a build/loadout concept that the inventory should hint at (e.g., this slot is "weapon", this slot is "passive")?
Bottom line
The mockup is solid as a first pass — it picks the right conventions and the right palette, and the bones (tier tabs + compare panel) are correct. My main worry is that it's currently designed as a Deadlock-scale shop (lots of chrome, lots of axes) for what I assume is a much smaller, faster game. The interesting work is in cutting — figuring out which 3 of those 5 sub-panels actually earn their pixels in your specific game loop, and making those bigger. Right now everything is "fine" and nothing is "the thing your eye is supposed to land on first."
Want me to mock up a leaner variant (one collapsed rail, no duplicate detail card, reroll moved up, Δ-style compare) so we can A/B it against this?
[Pasted image/jpeg]
- You click to continue and take as long as you want.
- It's fine for the UI to be a bit cluttered with lots of options that most players won't use.
- I don't think there's a distinction, we should have the shop and then the items you own in a smaller view than the current inventory takes. Like in Deadlock, let me paste you one of the reference images, it's just a bunch of slots on the bottom left of the screen. Ours doesn't need to be on the bottom left, but it similarly can be less invasive than a whole inventory section.
- Yea we can remove that, no need for it in this game.
- There will be no reroll, we can also remove it.
- For now we can just have tiers and then worry about simplifying things once we actually have lots of items implemented.
- I think it will make more sense to make it like Deadlock, where items are just symbols/emojis and then you hover over each and it shows the full description. This allows us to add more emojis to the screen at once. I also think there might not be a need for any compare panel or anything like that, as the game doesn't work like that, you just buy items and don't really change them.
- Yea, placeholder.
- I don't think rarity makes sense, we want all items in the shop from the get go, gated by price. But wishlisting might make sense, but that's a feature for later.
Good. The Deadlock reference clarifies a lot — that "compact owned-strip + dense catalog page + hover-only details" model is significantly leaner than what my first read of your mockup encoded. Let me play back what the revised mockup should look like, and surface the 2–3 questions that are still load-bearing.
What I'm taking from your answers
- All four tiers visible at once on one page, not tabbed. Following Deadlock's 2×2 quadrant catalog. Locked tiers still get a visual lock state, but you can see what's coming.
- Items collapse to icon + tiny name label. Hover = the only place full description / stats appear. This is a big win — you go from ~12 items visible to ~24–30 per page, and the cards stop competing with the tooltip for the same information.
- No compare panel. Hover tooltip is the single source of truth for "what is this item."
- No filter rail, no reroll, no quick-buy. The whole left column you sketched is essentially deleted.
- No categories for now. Tier is the only navigation axis. You can re-add category if/when the pool grows.
- No rarity. All items available from the start, gated by price tier. Wishlist deferred.
- Compact owned-items strip replaces the full inventory panel. Deadlock puts it bottom-left as ~12 small slots, value readout nearby. Yours can sit wherever, but it's a strip not a panel.
What the revised layout probably looks like
Rough proportions for a 600×360-ish reference frame:
- Top bar (thin): Gold counter on one side, Item Value on the other. That's it.
- Main area (catalog): 2×2 grid of tier sections, each with its price tag header (Tier 1 $X, Tier 2 $Y, Tier 3 $Z, Tier 4 $W). Each tier section holds 6–10 item icons + name labels in a grid. Locked tiers are visually dimmed with a lock badge but still occupy space.
- Floating tooltip on hover: name, price, full description, any active/passive flags, current → next-stack stat preview if relevant.
- Owned strip: horizontal row of ~10–16 small slots showing what you've bought. Empty slots are just outlined squares. If you click an owned item, same hover-tooltip content shows up.
- Footer: Back / Continue button, maybe nothing else.
That's it. The whole left rail from your first mockup is gone. The middle "selected item" card is gone. The right panel's compare block is gone. You're left with: top bar, catalog, owned strip, footer. Easily 2–3× less chrome.
Questions that I think still matter
Does Emoji Aimer have active items (player-triggered abilities) or are all items passive stat boosters? Deadlock's screenshot has a Z/X/C/V/E hotbar at the bottom because actives need slottable hotkeys. If Emoji Aimer has actives, the owned strip needs to distinguish active slots (probably 4–6 hotbar slots with keybinds shown) from passive items (just inventory icons). If everything is passive, the owned strip can be one undifferentiated row. This is the single biggest open question — it changes the bottom-of-screen layout meaningfully.
Does selling exist? Your first mockup had a "SELL PURR CAT +150" button as a prominent action. In the new lean layout, where does sell live? Options: (a) right-click an owned item, (b) hover an owned item and a small sell button appears in the tooltip, (c) drag to a sell bin, (d) no sell at all — purchases are permanent. Pick one before I mock it up.
The catalog as a "page" — paper-grain aesthetic, or your existing white-panel-with-black-outline aesthetic? Deadlock leans hard into the parchment/curiosity-shop framing (paper grain, tier tags as torn-paper labels, decorative № 777, hand-drawn icons). It's charming but it's also a strong style commitment that needs to play with your emoji icons. Your current palette/style is much more clean-pixel-flat. I think the flat style is probably the right call for Emoji Aimer (emojis already carry visual personality), but it's worth a beat of decision before I draw it.
Once you've answered those three (especially #1 — active vs passive), I'll do a revised mockup. Want it as an HTML iteration on ui_mockup.html, or as a fresh standalone file?
There are no active items, selling doesn't exist, use the emoji aesthetic, but also, let's not do any mockups, let's just do things directly in the game itself. For now, we have the shop view when we finish a round. Let's start the game there now. If the previous instances didn't divide the game into clean states between round/shop, then do so now. You should be able to do something like call a function (or equivalent) to start the game in a round or a shop simply.
Let me read the current state of the game to understand what's there.
Read (E:\a327ex\emoji-aimer\main.lua)
File content (35688 tokens) exceeds maximum allowed tokens (25000). Use offset and limit parameters to read specific portions of the file, or search for specific content instead of reading the whole file.
Bash (wc -l E:/a327ex/emoji-aimer/main.lua)
2041 E:/a327ex/emoji-aimer/main.lua
Read (E:\a327ex\emoji-aimer\main.lua)
1 --[[
2 Emoji Aimer — Anchor 2.
3
4 Click-to-damage aim trainer scaffold. Single 3-HP target at center; click
5 within its radius to damage. On hit: spring squash, white flash, hit_circle
6 ring, hit_particles + sparkle emoji_particles, camera shake. On death: bigger
7 ring, more particles (collision + sparkle emojis), bigger shake. New target
8 respawns at center after a short delay.
9
10 Visual style ported from emoji-ball-bounce (Twitter emoji palette, 480x270
11 at scale 3, sky gradient bg, layer pipeline with shadow + outline shaders).
12 ]]
13
14 require('anchor')({
15 width = 480,
16 height = 270,
17 title = 'Emoji Aimer',
18 scale = 3,
19 filter = 'rough',
20 })
21
22 gw, gh = width, height
23
24 -- -----------------------------------------------------------------------------
25 -- palette (Twitter emoji / Emoji Ball Battles)
26 -- -----------------------------------------------------------------------------
27 white = color(255, 255, 255)
28 black = color(0, 0, 0)
29 gray = color(128, 128, 128)
30 bg_color = color(48, 49, 50)
... [170 more lines]
Read (E:\a327ex\emoji-aimer\main.lua)
200 bind('spawn_gem', 'key:x')
201 bind('spawn_crown', 'key:c')
202
203 -- -----------------------------------------------------------------------------
204 -- layers
205 -- -----------------------------------------------------------------------------
206 bg_layer = layer_new('bg')
207 game_layer = layer_new('game')
208 effects_layer = layer_new('effects')
209 shadow_layer = layer_new('shadow')
210 game_outline = layer_new('game_outline')
211 effects_outline = layer_new('effects_outline')
212
213 -- UI is split into two layers, both outlined by the same shader:
214 -- ui_panel_layer — structural fills (panel rects, tag rects, cost dots,
215 -- mana pip frames, slot frames). The shader produces
216 -- the chunky black outline around each panel.
217 -- ui_content_layer — text + icons. Drawn in WHITE so the shader's black
218 -- halo reads as a black outline around white interior
219 -- (matches the reference look). Icons get outlined too.
220 -- Both have a derived <layer>_outline pass that runs outline_shader on them.
221 ui_panel_layer = layer_new('ui_panel')
222 ui_panel_outline = layer_new('ui_panel_outline')
223 ui_content_layer = layer_new('ui_content')
224 ui_content_outline = layer_new('ui_content_outline')
225
226 -- Fullscreen dim for ROUND END. Not outlined — outlining a fullscreen rect
227 -- produces a fully-black screen.
228 overlay_layer = layer_new('overlay')
229
... [170 more lines]
Let me find the key game-state machinery — where it transitions to shop, where it starts.
Grep (game_state\s=\s')
342:game_state = 'playing'
1573: game_state = 'playing' -- crucial when advancing from 'cleared': without
1584: game_state = 'won'
1586: game_state = 'shop'
1609: game_state = 'playing'
1692: game_state = 'cleared'
1710: game_state = 'lost'
Grep (^function |^local function )
320:local function create_wall(x, y, w, h)
389:function hit_circle:new(x, y, args)
406:function hit_circle:update(dt) timer_update(self.timer, dt) end
408:function hit_circle:draw()
413:function hit_circle:destroy() end
423:function hit_effect:new(x, y, args)
433:function hit_effect:update(dt)
438:function hit_effect:draw()
447:function hit_effect:destroy() end
455:function hit_particle:new(x, y, args)
478:function hit_particle:update(dt)
488:function hit_particle:draw()
496:function hit_particle:destroy() end
506:function emoji_particle:new(x, y, image, args)
543:function emoji_particle:update(dt)
560:function emoji_particle:draw()
567:function emoji_particle:destroy() end
582:function damage_number:new(x, y, amount, args)
616:function damage_number:update(dt)
626:function damage_number:draw()
639:function damage_number:destroy() end
653:function tier_color_for(amount)
714:function combo_tier()
722:function on_combo_break()
731:function on_miss(mx, my)
745:function target:new(x, y)
789:function target:contains(px, py)
794:function target:hit(mx, my)
839:function target:die(mx, my)
872:function target:update(dt)
... [43 more lines]
Read (E:\a327ex\emoji-aimer\main.lua)
1530 function start_round_end_transition()
1531 transition.phase = 'circle_in'
1532 transition.radius = 0
1533 transition.origin_x, transition.origin_y = mouse_position()
1534
1535 timer_tween(transition.timer, TRANSITION_IN_DURATION, transition,
1536 { radius = TRANSITION_FINAL_RADIUS }, math.linear, function()
1537 transition.phase = 'mid'
1538 advance_round() -- kills alive targets/effects + swaps bg to shop
1539
1540 timer_after(transition.timer, TRANSITION_MID_DURATION, function()
1541 transition.phase = 'circle_out'
1542 -- Recenter on the current cursor position so the wipe-out feels
1543 -- rooted to where the player is.
1544 transition.origin_x, transition.origin_y = mouse_position()
1545
1546 timer_tween(transition.timer, TRANSITION_OUT_DURATION, transition,
1547 { radius = 0 }, math.cubic_out, function()
1548 transition.phase = nil
1549 end)
1550 end)
1551 end)
1552 end
1553
1554
1555 -- start_round(idx) — clean slate for round idx. Kills any in-flight targets
1556 -- and effects, drains the destroy queue immediately so colliders/timers/
1557 -- springs are finalized before we replace the arrays, then re-seeds. Used
1558 -- both by run_reset() (round 1) and advance_round() (rounds 2..N). Use the
1559 -- F3/F4 memory tracker to verify a fresh round returns deltas to zero.
... [190 more lines]
Read (E:\a327ex\emoji-aimer\main.lua)
1750 end
1751
1752 -- Resource ↔ target collisions — small spring pulse on both bodies so
1753 -- the contact reads visually. Resources keep their physics bounce; the
1754 -- target wobbles in place (it's static).
1755 for _, ev in ipairs(collision_entities_begin('resource', 'target')) do
1756 spring_pull(ev.a.spring, 'main', 0.15)
1757 spring_pull(ev.b.spring, 'hit', 0.15)
1758 end
1759
1760 -- Effects (particles, hit_effects, damage_numbers) keep updating across
1761 -- state boundaries so in-flight animations finish cleanly when the round
1762 -- transitions or the run ends.
1763 collection_update(targets, dt)
1764 collection_update(effects, dt)
1765
1766 camera_update(main_camera, dt)
1767 process_destroy_queue()
1768 memory_tracker_update(mem_tracker)
1769 end
1770
1771 function draw()
1772 layer_rectangle_gradient_v(bg_layer, 0, 0, gw, gh, sky_top(), sky_bottom())
1773
1774 camera_attach(main_camera, game_layer)
1775 camera_attach(main_camera, effects_layer)
1776 -- Side walls — visible cream columns flanking the square play area. UI
1777 -- chips sit on top of the LEFT wall. Both bleed past their outer screen
1778 -- edge so the camera handcam can't expose the sky behind them. Drawn
1779 -- first so resources/targets render above. The outline shader gives the
... [262 more lines]
Got it. I have the full picture now. State machine is mostly there but with three smells:
- Entity cleanup is duplicated between
start_roundandadvance_round. - No dedicated
start_shop()function — shop entry is inline insideadvance_round. - Bootstrap (lines 1642–1645) doesn't use
start_round; it inlines its own target-spawn loop.
Plan:
- Extract a
clear_entities()helper. - Add
start_shop()mirroringstart_round(idx). - Refactor
advance_round()to delegate. - Replace bootstrap with a single call —
start_shop()to start in the shop, orstart_round(1)to start at round 1. Comment explains the swap.
round_index = 0 becomes the convention for "before round 1" (shop UI already displays round_index + 1 as the upcoming round; exit_shop bumps to 1 and starts round 1 — no other code path touches ROUNDS[0]).
Making the edits now.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the bootstrap — replace the inline target-spawn with a clean state entry.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Quick sanity check — make sure no stale references remain.
Grep (for i = 1, TARGETS_INITIAL)
1581: for i = 1, TARGETS_INITIAL do try_spawn_target() end
Grep (game_state\s=\s')
342:game_state = 'playing'
1578: game_state = 'playing' -- crucial when advancing from 'cleared': without
1593: game_state = 'shop'
1602: game_state = 'won'
1618: game_state = 'playing'
1708: game_state = 'cleared'
1726: game_state = 'lost'
Grep (ipairs(targets) do if not t._dead)
1560: for _, t in ipairs(targets) do if not t._dead then entity_kill(t) end end
1803: for _, t in ipairs(targets) do if not t._dead then t:draw() end end
All clean. The two remaining matches are the helper itself (line 1560) and the draw iteration (line 1803, not a kill).
Summary
Refactored the state machine in main.lua:
clear_entities()(main.lua:1556) — extracted helper; kills + drains + replaces the targets/effects arrays in one place.start_round(idx)(main.lua:1568) — now delegates toclear_entities(); rest unchanged.start_shop()(main.lua:1590) — new, symmetric tostart_round. Wipes entities, resets combo, setsgame_state = 'shop'.advance_round()(main.lua:1600) — now just decides 'won' vs.start_shop(). No more inline cleanup.- Bootstrap (main.lua:1664) — replaced the inline
try_spawn_targetloop with a single boot call. Currently set toround_index = 0; start_shop()so the game opens in the shop. Swap tostart_round(1)to play from round 1.
The round_index = 0 convention works because the shop UI already reads round_index + 1 as the upcoming round, and exit_shop bumps it before calling start_round. No other code path indexes ROUNDS[round_index] in a way that would touch index 0 (HUD chips are hidden during 'shop', and advance_round's >= #ROUNDS check only fires from 'cleared').
When you launch you'll drop straight into the current shop overlay — the old single-item-card placeholder. Ready to start replacing that with the real shop view. Want to start with the catalog page (tier quadrants + emoji-icon grid + hover tooltip), or the compact owned-items strip first?
Great, the current shop view has for some reason some kind of dark overlay over it, please remov eit.
Read (E:\a327ex\emoji-aimer\main.lua)
1862 -- Shop overlay. Single placeholder item for now ("+1 score per kill"),
1863 -- buyable as many times as the player can afford. NEXT ROUND advances
1864 -- to the next round; END ROUND button is suppressed during shop.
1865 if game_state == 'shop' then
1866 -- Dim background so the shop reads clearly over the empty arena.
1867 layer_rectangle(overlay_layer, 0, 0, gw, gh, color(0, 0, 0, 180)())
1868
1869 -- Header: "SHOP" + a line about the next round's target.
1870 local header = 'SHOP'
1871 local header_w = font_get_text_width('mid', header)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Removed the fullscreen dim rect at main.lua:1866. Shop now draws directly over the sky-gradient background.
OK, now remove the current contents of the shop, as well as the walls. The shop should be its own "state", and thus we should not be seeing state from the round. The walls that are there belong to a round, not the shop.
Read (E:\a327ex\emoji-aimer\main.lua)
1085 function combo_display:draw()
1086 if combo_count <= 0 then return end
1087 local tier = combo_tier()
1088 local s = self.spring.main.x
1089 local r = self.base_rotation + self.spring.r.x
1090 local text = tostring(combo_count)
1091 local text_w = font_get_text_width('mid', text)
1092
1093 -- Decay-based jitter — fired on each new count, linearly decays over
1094 -- shake_dur. Higher tiers carry both bigger amp and longer dur so a fresh
1095 -- gold hit reads as a much bigger event than a fresh yellow hit.
1096 local jx, jy = 0, 0
1097 if self.shake_remaining > 0 and self.shake_dur > 0 then
1098 local sk = self.shake_amp * (self.shake_remaining/self.shake_dur)
1099 jx = random_float(-sk, sk)
1100 jy = random_float(-sk, sk)
1101 end
1102
1103 -- Tier icons — gem appears whenever the current tier drops gems (green+,
1104 -- combo 10), crown when crowns drop (red+, combo 35). Lays out as
1105 -- [gem?][crown?] <number> so the player sees what's about to drop right
1106 -- next to the combo count. Read tier.drops dynamically rather than
1107 -- hardcoding so adding a new resource type later only touches the table.
1108 local has_gem, has_crown = false, false
1109 for _, drop in ipairs(tier.drops) do
1110 if drop[1] == 'gem' then has_gem = true
1111 elseif drop[1] == 'crown' then has_crown = true end
1112 end
1113
1114 local icon_size = 8
... [45 more lines]
Read (E:\a327ex\emoji-aimer\main.lua)
1788 layer_rectangle_gradient_v(bg_layer, 0, 0, gw, gh, sky_top(), sky_bottom())
1789
1790 camera_attach(main_camera, game_layer)
1791 camera_attach(main_camera, effects_layer)
1792 -- Side walls — visible cream columns flanking the square play area. UI
1793 -- chips sit on top of the LEFT wall. Both bleed past their outer screen
1794 -- edge so the camera handcam can't expose the sky behind them. Drawn
1795 -- first so resources/targets render above. The outline shader gives the
1796 -- inner edge a black border that reads as the wall surface.
1797 layer_rectangle(game_layer,
1798 -WALL_BLEED, -WALL_BLEED,
1799 SIDE_WALL_W + WALL_BLEED, gh + 2*WALL_BLEED, fg())
1800 layer_rectangle(game_layer,
1801 gw - SIDE_WALL_W, -WALL_BLEED,
1802 SIDE_WALL_W + WALL_BLEED, gh + 2*WALL_BLEED, fg())
1803 for _, t in ipairs(targets) do if not t._dead then t:draw() end end
1804 -- Skip damage_numbers in this pass — they draw to digit_layer and get
1805 -- recolored + merged into effects_layer below so the recolor shader can
1806 -- tint them per-rarity.
1807 for _, fx in ipairs(effects) do
1808 if not fx._dead and not fx.rarity_color then fx:draw() end
1809 end
1810 camera_detach(main_camera, effects_layer)
1811 camera_detach(main_camera, game_layer)
1812
1813 -- UI is camera-attached so the chips wobble with the side walls under
1814 -- the handcam. overlay_layer / cursor_layer / transition_layer stay in
1815 -- screen space so the dim, the cursor, and the wipe circle don't shake.
1816 camera_attach(main_camera, ui_panel_layer)
1817 camera_attach(main_camera, ui_content_layer)
... [120 more lines]
Let me check what other code touches the soon-to-be-dead shop bits before I delete them.
Grep (items_owned|ITEM_BONUS|ITEM_COST|shop_buy|shop_next|SHOP_BUY|SHOP_NEXT)
118:SHOP_BUY_BTN_W = 70
119:SHOP_BUY_BTN_H = 22
120:SHOP_BUY_BTN_X = gw/2 - SHOP_BUY_BTN_W/2
121:SHOP_BUY_BTN_Y = 165
123:SHOP_NEXT_BTN_W = 96
124:SHOP_NEXT_BTN_H = 22
125:SHOP_NEXT_BTN_X = gw - 4 - SHOP_NEXT_BTN_W
126:SHOP_NEXT_BTN_Y = gh - 4 - SHOP_NEXT_BTN_H
141:-- Damage economy. Click damage = BASE_DAMAGE + items_owned * ITEM_BONUS.
143:-- kill-speed progression comes entirely from the shop. ITEM_COST is the
146:ITEM_COST = 10
147:ITEM_BONUS = 1
369:-- spent in the shop between rounds. items_owned bumps the click-damage
370:-- base by ITEM_BONUS each. Both reset only via run_reset, not start_round.
372:items_owned = 0
795: -- Damage = BASE_DAMAGE + items_owned bonus. Combo doesn't affect damage
797: local damage = BASE_DAMAGE + items_owned*ITEM_BONUS
1577: -- gold and items_owned persist across rounds — only run_reset wipes them.
1623: items_owned = 0
1638:function shop_buy_button_contains(mx, my)
1639: return mx >= SHOP_BUY_BTN_X and mx <= SHOP_BUY_BTN_X + SHOP_BUY_BTN_W
1640: and my >= SHOP_BUY_BTN_Y and my <= SHOP_BUY_BTN_Y + SHOP_BUY_BTN_H
1643:function shop_next_round_button_contains(mx, my)
1644: return mx >= SHOP_NEXT_BTN_X and mx <= SHOP_NEXT_BTN_X + SHOP_NEXT_BTN_W
1645: and my >= SHOP_NEXT_BTN_Y and my <= SHOP_NEXT_BTN_Y + SHOP_NEXT_BTN_H
1760: if shop_buy_button_contains(mx, my) and gold >= ITEM_COST then
1761: gold = gold - ITEM_COST
1762: items_owned = items_owned + 1
1763: elseif shop_next_round_button_contains(mx, my) then
1889: local item_dmg = items_owned*ITEM_BONUS
... [12 more lines]
The wiring is clear:
SHOP_BUY_BTN_*/SHOP_NEXT_BTN_*constants and the two*_containshelpers only support the old shop UI — safe to delete.items_owned/ITEM_BONUS/ITEM_COSTare also used bytarget:hitfor damage calc — keep those, they're gameplay, not UI.
Making four edits:
- Delete dead shop-button constants.
- Wrap walls in
game_state ~= 'shop'. - Delete the shop click handler.
- Delete the
*_containsfunctions and the shop draw block.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the click handler in update — find it and confirm exact text.
Read (E:\a327ex\emoji-aimer\main.lua)
1740 if not hit then on_miss(mx, my) end
1741 end
1742 end
1743
1744 -- Shop interactions: BUY (one item per click, repeat to stack) and
1745 -- NEXT ROUND (advance to the next round with the items just bought).
1746 if game_state == 'shop' and not transition.phase and input_pressed('click') then
1747 local mx, my = mouse_position()
1748 if shop_buy_button_contains(mx, my) and gold >= ITEM_COST then
1749 gold = gold - ITEM_COST
1750 items_owned = items_owned + 1
1751 elseif shop_next_round_button_contains(mx, my) then
1752 exit_shop()
1753 end
1754 end
1755
1756 -- Resource ↔ target collisions — small spring pulse on both bodies so
1757 -- the contact reads visually. Resources keep their physics bounce; the
1758 -- target wobbles in place (it's static).
1759 for _, ev in ipairs(collision_entities_begin('resource', 'target')) do
1760 spring_pull(ev.a.spring, 'main', 0.15)
1761 spring_pull(ev.b.spring, 'hit', 0.15)
1762 end
1763
1764 -- Effects (particles, hit_effects, damage_numbers) keep updating across
1765 -- state boundaries so in-flight animations finish cleanly when the round
1766 -- transitions or the run ends.
1767 collection_update(targets, dt)
1768 collection_update(effects, dt)
1769
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now delete the *_contains helpers and the entire shop draw block. Re-read their current locations first.
Grep (function shop_buy_button_contains|function shop_next_round_button_contains|game_state == 'shop' then)
1626:function shop_buy_button_contains(mx, my)
1631:function shop_next_round_button_contains(mx, my)
1844: if game_state == 'shop' then
Read (E:\a327ex\emoji-aimer\main.lua)
1620 -- AABB hit-test for the END ROUND button (only meaningful while 'cleared').
1621 function end_round_button_contains(mx, my)
1622 return mx >= END_ROUND_BTN_X and mx <= END_ROUND_BTN_X + END_ROUND_BTN_W
1623 and my >= END_ROUND_BTN_Y and my <= END_ROUND_BTN_Y + END_ROUND_BTN_H
1624 end
1625
1626 function shop_buy_button_contains(mx, my)
1627 return mx >= SHOP_BUY_BTN_X and mx <= SHOP_BUY_BTN_X + SHOP_BUY_BTN_W
1628 and my >= SHOP_BUY_BTN_Y and my <= SHOP_BUY_BTN_Y + SHOP_BUY_BTN_H
1629 end
1630
1631 function shop_next_round_button_contains(mx, my)
1632 return mx >= SHOP_NEXT_BTN_X and mx <= SHOP_NEXT_BTN_X + SHOP_NEXT_BTN_W
1633 and my >= SHOP_NEXT_BTN_Y and my <= SHOP_NEXT_BTN_Y + SHOP_NEXT_BTN_H
1634 end
1635
1636 -- -----------------------------------------------------------------------------
1637 -- init
1638 -- -----------------------------------------------------------------------------
1639 mouse_set_visible(false)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now delete the shop draw block.
Read (E:\a327ex\emoji-aimer\main.lua)
1830
1831 -- Shop overlay. Single placeholder item for now ("+1 score per kill"),
1832 -- buyable as many times as the player can afford. NEXT ROUND advances
1833 -- to the next round; END ROUND button is suppressed during shop.
1834 if game_state == 'shop' then
1835 -- Header: "SHOP" + a line about the next round's target.
1836 local header = 'SHOP'
1837 local header_w = font_get_text_width('mid', header)
1838 layer_text(ui_content_layer, header, fonts.mid, gw/2 - header_w/2, 16, white())
1839
1840 local next_round = round_index + 1
1841 local sub = 'ROUND ' .. next_round .. ' / ' .. #ROUNDS .. ' — KILL ' .. ROUNDS[next_round].target_kills
1842 local sub_w = font_get_text_width('main', sub)
1843 layer_text(ui_content_layer, sub, fonts.main, gw/2 - sub_w/2, 38, white())
1844
1845 -- Gold line — coin icon + number, centered.
1846 local coin_size = 9
1847 local coin_s = coin_size/coin_img.width
1848 local gold_str = tostring(gold)
1849 local gold_w = font_get_text_width('main', gold_str)
1850 local pair_w = coin_size + 4 + gold_w
1851 local gold_x = gw/2 - pair_w/2
1852 layer_push(ui_content_layer, gold_x + coin_size/2, 60 + 5, 0, coin_s, coin_s)
1853 layer_image(ui_content_layer, coin_img, 0, 0)
1854 layer_pop(ui_content_layer)
1855 layer_text(ui_content_layer, gold_str, fonts.main, gold_x + coin_size + 4, 60, white())
1856
1857 -- Damage readout — "<items> + COMBO DAMAGE PER CLICK".
1858 local item_dmg = items_owned*ITEM_BONUS
1859 local dmg_str = item_dmg .. ' + COMBO DAMAGE / CLICK'
... [45 more lines]
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Final sweep to make sure nothing dead remains.
Grep (SHOP_BUY|SHOP_NEXT|shop_buy_button|shop_next_round_button)
No matches found
All dead references gone. Done.
Summary
- Walls gated on
game_state ~= 'shop'in main.lua:1796. - Shop draw block deleted entirely — the
if game_state == 'shop'body and all of its content (header, gold readout, damage readout, item card, BUY button, NEXT ROUND button) are gone. Nothing renders inside the shop yet. - Shop click handler deleted from
update(). - Dead scaffolding removed:
SHOP_BUY_BTN_*/SHOP_NEXT_BTN_*constants and the two*_containshelpers.
Kept: items_owned, ITEM_BONUS, ITEM_COST (still used by target:hit for damage calc), and the exit_shop() function (still useful when we add a way out of the shop).
The shop now renders as just the sky-gradient background and the cursor. Clean slate. Note: with no exit button drawn, the only way out of the shop is R (full reset) — let me know when you want me to add the new "next round" affordance, or whether that's coming as part of the new shop UI.
Perfect. Now let's do most/all UI elements that will be needed for the shop, but without laying them out at all. Download various emojis to be used, previous instances downloaded them from Emojipedia, Twitter set. Each emoji needs to be the 512x512 image. Essentially I want the "UI kit" for the shop to be visible so I can fix each individual element before we build the layout of the shop itself.
Before downloading and writing, let me check the existing emoji dimensions so I match the convention, and sanity-check the plan with you.
PowerShell
Unable to find type [System.Drawing.Image].
At line:1 char:76
+ ... assets\*.png | ForEach-Object { $img = [System.Drawing.Image]::FromFi ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Drawing.Image:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
0.png: x
You cannot call a method on a null-valued expression.
At line:1 char:167
+ ... llName); "$($_.Name): $($img.Width)x$($img.Height)"; $img.Dispose() }
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Unable to find type [System.Drawing.Image].
At line:1 char:76
+ ... assets\*.png | ForEach-Object { $img = [System.Drawing.Image]::FromFi ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Drawing.Image:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
1.png: x
You cannot call a method on a null-valued expression.
At line:1 char:167
+ ... llName); "$($_.Name): $($img.Width)x$($img.Height)"; $img.Dispose() }
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
... [344 more lines]
Let me check PNG dimensions a different way.
PowerShell
backhand_index_pointing_up.png: 512x512
coin.png: 256x256
collision.png: 512x512
crown.png: 256x256
direct_hit.png: 512x512
fire.png: 512x512
gem.png: 256x256
high_voltage.png: 512x512
hourglass_done.png: 512x512
sparkles.png: 512x512
star.png: 512x512
Existing emojis are 512×512 (except coin/gem/crown at 256 — those probably predate the convention; I'll re-download them to 512 for consistency while I'm at it, if that's OK).
Before I touch any code or hit any URLs, let me lock in scope with you.
UI elements I'll build (each as a standalone draw fn, scattered)
- Item icon tile — emoji on a card frame. States: default, hovered, owned (small checkmark), unaffordable (dimmed).
- Hover tooltip — popup card: name, price (coin + number), one-line description, optional 1–3 stat lines.
- Tier header — "TIER 1" label + price-tag chip (the chunky tag-shape from the Pixel Mart mockup).
- Owned-items strip — compact row of slots (filled emoji + empty outline).
- Top-bar bits — Gold counter (coin + number), Item Value counter.
- Page title + subtitle — "SHOP" treatment + a small line like "ROUND 1 / 5 — KILL 5".
- Buttons — primary (e.g. "NEXT ROUND") and secondary (e.g. "BACK"). Default / hovered / disabled.
- Locked-tier overlay — dimmed band + 🔒 across a tier section.
Emojis to download (16, diverse for shop-item variety)
shield 🛡️, crossed swords ⚔️, bow & arrow 🏹, magic wand 🪄, red heart ❤️, four-leaf clover 🍀, magnet 🧲, skull 💀, bomb 💣, feather 🪶, eye 👁️, test tube 🧪, coffee ☕, hot pepper 🌶️, bone 🦴, locked 🔒
All 512×512, Twemoji (= Twitter set on Emojipedia), saved to assets/<name>.png matching the existing naming (e.g. magic_wand.png, four_leaf_clover.png).
A couple of micro-decisions worth your call
- Re-download coin/gem/crown at 512? They're 256 today and would benefit from matching the rest.
- Tier price-tag shape — Pixel Mart had the angled "luggage tag" with a notch + circle for the string-hole. Mock that up or just a plain rounded chip? My instinct: plain chip first (cheaper to draw, and the notch shape is a strong style commitment that should come later).
- Tooltip layout — Deadlock-style (header strip with name + price, then body with stat lines + description), or simpler (just name + price + description, no separate stat lines)? Probably need stat lines once items have real mechanics, but for the kit a minimal version is fine.
Anything to swap in/out of the emoji list, or any UI element you want removed/added before I start?
Seems fine to me.
Let me check the Emojipedia URL pattern for one emoji to figure out the download mechanics.
ToolSearch
[
{
"type": "tool_reference",
"tool_name": "WebFetch"
},
{
"type": "tool_reference",
"tool_name": "WebSearch"
}
]
WebFetch (https://emojipedia.org/twitter/shield)
Request failed with status code 403
WebFetch (https://emojipedia.org/shield)
Request failed with status code 403
WebSearch (em-content.zobj.net source twitter shield_1f6e1 512 png url)
Web search results for query: "em-content.zobj.net source twitter shield_1f6e1 512 png url"
Links: [{"title":"shield","url":"https://openmoji.org/library/emoji-1F6E1/"},{"title":"bug: Some emojis exist in the picker but don't render/exist in the application · Issue #20836 · coder/coder","url":"https://github.com/coder/coder/issues/20836"},{"title":"APNG specifier cant be used on images from the web · Issue #6980 · ImageMagick/ImageMagick","url":"https://github.com/ImageMagick/ImageMagick/issues/6980"},{"title":"🛡 shield : U+1F6E1 Unicode Information | Emojiall","url":"https://www.emojiall.com/en/code/1F6E1"},{"title":"zobj.net - urlscan.io","url":"https://urlscan.io/domain/zobj.net"},{"title":"U+1F6E1 SHIELD: 🛡 – Unicode","url":"https://codepoints.net/U+1F6E1?lang=en"},{"title":"X (formerly Twitter) URL | Shields.io","url":"https://shields.io/badges/x-formerly-twitter-url"},{"title":"️ Shield Emoji – Meaning and Pictures","url":"https://emojiguide.org/shield"},{"title":"“🛡” U+1F6E1 Shield Unicode Character","url":"https://www.compart.com/en/unicode/U+1F6E1"},{"title":"twemoji/assets/svg/1f6e1.svg at master · twitter/twemoji","url":"https://github.com/twitter/twemoji/blob/master/assets/svg/1f6e1.svg"}]
Based on the search results, the URL you're asking about appears to be related to emoji content delivery. The em-content.zobj.net domain hosts emoji images from various sources, including Twitter/X emoji sets.
The specific URL structure `em-content.zobj.net/source/twitter/shield_1f6e1_512.png` would point to:
- **em-content.zobj.net** - The emoji content CDN/hosting service
- **source/twitter** - Twitter emoji set
- **shield_1f6e1** - The shield emoji (Unicode U+1F6E1)
- **512** - 512 pixel resolution
- **.png** - PNG image format
The shield emoji (🛡) has the Unicode point U+1F6E1 and appears to be a standard emoji available across multiple platforms. The em-content.zobj.net service provides PNG versions of emojis from different sources in various resolutions.
REMINDER: You MUST include the sources above in your response to the user using markdown hyperlinks.
Let me check what conversion tools are available, and probe the Emojipedia CDN directly.
PowerShell
magick : NOT FOUND
convert : C:\WINDOWS\system32\convert.exe
inkscape : NOT FOUND
rsvg-convert : NOT FOUND
PowerShell
403 https://em-content.zobj.net/source/twitter/408/shield_1f6e1.png
403 https://em-content.zobj.net/source/twitter/376/shield_1f6e1.png
403 https://em-content.zobj.net/thumbs/240/twitter/408/shield_1f6e1.png
403 https://em-content.zobj.net/source/twitter/shield_1f6e1.png
403 https://emojipedia-us.s3.amazonaws.com/source/skype/289/shield_1f6e1.png
PowerShell
python : C:\Users\adn\AppData\Local\Programs\Python\Python314\python.exe
python3 : NOT FOUND
py : C:\WINDOWS\py.exe
node : C:\Program Files\nodejs\node.exe
npm : C:\Program Files\nodejs\npm.ps1
npx : C:\Program Files\nodejs\npx.ps1
curl :
PowerShell
Exit code 1
Traceback (most recent call last):
File "<string>", line 1, in <module>
import sys; print(sys.version); mods = ['PIL', 'cairosvg', 'requests']; [print(m, ':', __import__(m).__version__ if hasattr(__import__(m), '__version__') else 'OK') for m in mods if __import__('importlib').util.find_spec(m)]; [print(m, ': NOT FOUND') for m in mods if not __import__('importlib').util.find_spec(m)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'importlib' has no attribute 'util'
3.14.2 (tags/v3.14.2:df79316, Dec 5 2025, 17:18:21) [MSC v.1944 64 bit (AMD64)]
PowerShell
PIL : YES
cairosvg : NO
requests : NO
urllib3 : NO
PowerShell
err: The remote server returned an error: (403) Forbidden.
PowerShell
sharp: NO - MODULE_NOT_FOUND
Let me check whether there's already a download script in the project (previous instances may have left one).
Bash (find E:/a327ex/emoji-aimer -maxdepth 4 -type f ( -name ".py" -o -name ".sh" -...)
E:/a327ex/emoji-aimer/run.bat
Bash (find E:/a327ex -maxdepth 5 -type f ( -name "emoji" -o -name "download" -o -...)
E:/a327ex/a327ex-site/notes/emoji-ball-battles.md
E:/a327ex/anchor.blot.im/files/emoji-ball-battles-1.mp4
E:/a327ex/emoji-ball-battles/reference/basic-emoji-anchor-game.md
E:/a327ex/emoji-ball-battles/reference/emoji-merge-main/assets/multiply_emoji.frag
E:/a327ex/emoji-ball-battles/reference/emoji_effects_documentation.md
Grep (zobj.net|em-content|emojipedia|twemoji|cairosvg|jsdelivr)
Found 15 files limit: 15
a327ex-site\server\templates.lua
a327ex-site\README.md
anchor.blot.im\files\UI Design Workflow\Claude AnchorApp 5.html
Anchor2\app\docs\mockup_v2_code.html
anchor.blot.im\files\UI Design Workflow\Claude AnchorApp 6.html
Anchor2\app\docs\mockup_v2_write.html
Anchor2\app\docs\mockup_v2_command_palette.html
anchor.blot.im\files\UI Design Workflow\Claude AnchorApp 4.html
Anchor2\app\docs\mockup_v2_browse.html
Anchor2\app\docs\mockup_v2_canvas.html
anchor.blot.im\files\UI Design Workflow\Claude AnchorApp 3.html
Anchor2\app\docs\mockup_v2_ui_kit.html
Anchor2\app\docs\mockup_music_piano_roll.html
Anchor2\app\docs\mockup_code_editor.html
Anchor2\app\docs\mockup_write_mode.html
Bash (grep -lE "em-content.zobj.net|emojipedia..png" --include=".py" --include="*...)
(Bash completed with no output)
PowerShell
err: Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
svg err: Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
PowerShell
OK 200 850 image/png
PowerShell
SVG OK 200 image/svg+xml
PowerShell
OK 200 19499 image/png
Got a working pipeline: jsdelivr SVG → wsrv.nl rasterizer → 512×512 PNG. Let me verify the output quality with one sample.
PowerShell
saved: 19499 bytes, 512x512
Read (E:\a327ex\emoji-aimer\assets_test_shield.png)
[
{
"type": "image",
"source": {
"type": "base64",
"data": "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",
"media_type": "image/png"
}
}
]
Read (E:\a327ex\emoji-aimer\assets\fire.png)
[
{
"type": "image",
"source": {
"type": "base64",
"data": "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",
"media_type": "image/png"
}
}
]
Quality matches the existing Twemoji style. Pipeline confirmed. Downloading the full set now.
PowerShell
shield : 512x512 (19499 bytes)
crossed_swords : 512x512 (18146 bytes)
bow_and_arrow : 512x512 (20210 bytes)
magic_wand : 512x512 (10581 bytes)
red_heart : 512x512 (10962 bytes)
four_leaf_clover : 512x512 (17450 bytes)
magnet : 512x512 (19158 bytes)
skull : 512x512 (18081 bytes)
bomb : 512x512 (12742 bytes)
feather : 512x512 (22664 bytes)
eye : 512x512 (20991 bytes)
test_tube : 512x512 (15993 bytes)
coffee : 512x512 (29768 bytes)
hot_pepper : 512x512 (12382 bytes)
bone : 512x512 (19240 bytes)
locked : 512x512 (9369 bytes)
coin : 512x512 (28437 bytes)
gem : 512x512 (10916 bytes)
crown : 512x512 (23462 bytes)
Read (E:\a327ex\emoji-aimer\assets\magic_wand.png)
[
{
"type": "image",
"source": {
"type": "base64",
"data": "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",
"media_type": "image/png"
}
}
]
Read (E:\a327ex\emoji-aimer\assets\eye.png)
[
{
"type": "image",
"source": {
"type": "base64",
"data": "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",
"media_type": "image/png"
}
}
]
Now I'll build the UI elements. Let me check the existing draw_hud_chip helper so my new draw functions match its style.
Read (E:\a327ex\emoji-aimer\main.lua)
1419 local pad_x = 3
1420 local pad_y = 5
1421 local icon_w = 14
1422 -- Default gap matches the hourglass chip (which has ~2px built-in
1423 -- transparent padding on its right). Tighter icons (bullseye, coin) bbox
1424 -- to the edge — pass a larger gap so the visual icon→text distance lines
1425 -- up with the timer.
1426 gap = gap or 4
1427 local font_h = (font_name == 'big') and 8 or (font_name == 'main') and 11 or 16
1428 -- Width is normally driven by the text's measured width. Pass min_text_w
1429 -- to force a fixed text region (worst-case width) so the chip doesn't
1430 -- twitch as digits change — needed for the ticking timer.
1431 local txt_w = font_get_text_width(font_name, text_str)
1432 if min_text_w and min_text_w > txt_w then txt_w = min_text_w end
1433 local chip_w = pad_x + icon_w + gap + txt_w + pad_x
1434 local chip_h = pad_y + math.max(icon_w, font_h) + pad_y
1435
1436 layer_rounded_rectangle(ui_panel_layer, x, y, chip_w, chip_h, 2, fg())
1437
1438 local icon_s = icon_w / icon_image.width
1439 local cy = y + chip_h/2
1440 layer_push(ui_content_layer, x + pad_x + icon_w/2, cy, 0, icon_s, icon_s)
1441 layer_image(ui_content_layer, icon_image, 0, 0)
1442 layer_pop(ui_content_layer)
1443
1444 -- LanaPixel sits high in its 11-px box, so visual centering wants a small
1445 -- downward nudge from the technical center.
1446 local text_y = math.floor(y + chip_h/2 - font_h/2 + 1)
1447 layer_text(ui_content_layer, text_str, fonts[font_name],
1448 x + pad_x + icon_w + gap, text_y, white())
... [12 more lines]
Now I'll wire the new emojis into image_load and build the UI kit. Let me check the current registration block.
Read (E:\a327ex\emoji-aimer\main.lua)
247 -- images
248 -- -----------------------------------------------------------------------------
249 direct_hit_img = image_load('direct_hit', 'assets/direct_hit.png')
250 star_img = image_load('star', 'assets/star.png')
251 backhand_index_pointing_up = image_load('backhand_index_pointing_up','assets/backhand_index_pointing_up.png')
252 hourglass_img = image_load('hourglass', 'assets/hourglass_done.png')
253 high_voltage_img = image_load('high_voltage', 'assets/high_voltage.png')
254 fire_img = image_load('fire', 'assets/fire.png')
255 x_mark_img = image_load('x_mark', 'assets/x_mark.png')
256 coin_img = image_load('coin', 'assets/coin.png')
257 gem_img = image_load('gem', 'assets/gem.png')
258 crown_img = image_load('crown', 'assets/crown.png')
259
260 -- Digit emoji sprites (keycap-style 0..9). Used by damage_number for per-digit
261 -- score popups. Indexed by string ("0".."9") so tostring(amount):sub() lookups
262 -- work directly. Direct port of the reference's an.images['0'..'9'] pattern.
263 digit_imgs = {}
264 for i = 0, 9 do
265 digit_imgs[tostring(i)] = image_load('digit_' .. i, 'assets/' .. i .. '.png')
266 end
267 -- "+" prefix sprite for resource-pickup damage numbers ("+1", "+5", "+25").
268 -- Gray-keycap-style so it rides the same recolor shader as the digits.
269 digit_imgs['+'] = image_load('digit_plus', 'assets/plus.png')
270
271 spritesheet_register('hit1', 'assets/hit1.png', 96, 48)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now I'll add the kit helpers and the scatter renderer. I'll put the helpers right after draw_hud_chip and call the scatter from the shop block.
Read (E:\a327ex\emoji-aimer\main.lua)
1448 -- to force a fixed text region (worst-case width) so the chip doesn't
1449 -- twitch as digits change — needed for the ticking timer.
1450 local txt_w = font_get_text_width(font_name, text_str)
1451 if min_text_w and min_text_w > txt_w then txt_w = min_text_w end
1452 local chip_w = pad_x + icon_w + gap + txt_w + pad_x
1453 local chip_h = pad_y + math.max(icon_w, font_h) + pad_y
1454
1455 layer_rounded_rectangle(ui_panel_layer, x, y, chip_w, chip_h, 2, fg())
1456
1457 local icon_s = icon_w / icon_image.width
1458 local cy = y + chip_h/2
1459 layer_push(ui_content_layer, x + pad_x + icon_w/2, cy, 0, icon_s, icon_s)
1460 layer_image(ui_content_layer, icon_image, 0, 0)
1461 layer_pop(ui_content_layer)
1462
Read (E:\a327ex\emoji-aimer\main.lua)
1463 -- LanaPixel sits high in its 11-px box, so visual centering wants a small
1464 -- downward nudge from the technical center.
1465 local text_y = math.floor(y + chip_h/2 - font_h/2 + 1)
1466 layer_text(ui_content_layer, text_str, fonts[font_name],
1467 x + pad_x + icon_w + gap, text_y, white())
1468
1469 return chip_w, chip_h
1470 end
1471
1472 function spawn_target(x, y)
1473 local t = target(x, y)
1474 targets[#targets + 1] = t
1475 return t
1476 end
1477
1478 -- Try to spawn one target at a random arena position. Bails (returns false)
1479 -- if every attempt overlapped an existing target's TARGET_MIN_SPAWN_DIST
1480 -- exclusion zone. Caller is responsible for deciding *whether* to spawn —
1481 -- this just handles the "find a safe spot" placement.
1482 function try_spawn_target()
Now adding the kit helpers + sample-items table after draw_hud_chip ends at line 1470.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now plug the kit call into the shop draw block.
Read (E:\a327ex\emoji-aimer\main.lua)
2015 local stack_y = 8 -- distance from top screen edge
2016 local chip_gap = 6 -- vertical gap between chips
2017 local cur_y = stack_y
2018 local _, ch
2019
2020 -- Worst-case text width for the timer so the chip stays a fixed size
2021 -- as the digits tick. LanaPixel isn't perfectly monospaced.
2022 local timer_text_w = font_get_text_width('main', '88:88')
2023 _, ch = draw_hud_chip(stack_x, cur_y, hourglass_img,
2024 string.format('%02d:%02d', m, s), nil, nil, timer_text_w)
2025 cur_y = cur_y + ch + chip_gap
2026
2027 _, ch = draw_hud_chip(stack_x, cur_y, direct_hit_img,
2028 kills_this_round .. ' / ' .. round.target_kills, nil, 6)
2029 cur_y = cur_y + ch + chip_gap
2030
2031 draw_hud_chip(stack_x, cur_y, coin_img, tostring(gold), nil, 6)
2032 end
2033
2034 -- (No END ROUND button — round-end transition is automatic: 'cleared'
2035 -- enters vacuum mode in resource:update, and once every resource has
2036 -- been collected the update loop calls advance_round → shop.)
2037
2038 -- Game-over / win overlay. Centered title + restart hint. Title uses
2039 -- fonts.mid (Awesome 9 @ 16) for impact; hint uses fonts.main.
Read (E:\a327ex\emoji-aimer\main.lua)
2038 -- Game-over / win overlay. Centered title + restart hint. Title uses
2039 -- fonts.mid (Awesome 9 @ 16) for impact; hint uses fonts.main.
2040 if game_state == 'won' or game_state == 'lost' then
2041 local title = (game_state == 'won') and 'YOU WON!' or 'GAME OVER'
2042 local hint = 'PRESS R FOR NEW RUN'
2043 local title_w = font_get_text_width('mid', title)
2044 local hint_w = font_get_text_width('main', hint)
2045 layer_text(ui_content_layer, title, fonts.mid, gw/2 - title_w/2, gh/2 - 16, white())
2046 layer_text(ui_content_layer, hint, fonts.main, gw/2 - hint_w/2, gh/2 + 8, white())
2047 end
2048
2049 camera_detach(main_camera, ui_content_layer)
2050 camera_detach(main_camera, ui_panel_layer)
2051
2052 -- Round-end wipe — yellow circle on transition_layer (rendered last in
2053 -- the composite, above the cursor). Radius is tweened directly on the
2054 -- transition table by start_round_end_transition's chained timer_tween.
2055 if transition.radius > 0 then
2056 layer_circle(transition_layer, transition.origin_x, transition.origin_y,
2057 transition.radius, yellow())
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Quick verification that the framework primitives I used match Emoji Aimer's framework copy (Anchor 1, not Anchor 2).
Grep (^function layer_rounded_rectangle|^function layer_rectangle\b|^function layer_image|^function layer_push|^function layer_text|^function font_get_text_width)
108:function layer_rectangle(lyr, x, y, w, h, color)
152:function layer_rounded_rectangle(lyr, x, y, w, h, radius, color)
156:function layer_rounded_rectangle_line(lyr, x, y, w, h, radius, color, line_width)
169:function layer_image(lyr, img, x, y, color, flash)
174:function layer_texture(lyr, tex, x, y, color)
193:function layer_text(lyr, text, f, x, y, color)
198:function layer_push(lyr, x, y, r, sx, sy)
Grep (^function font_get_text_width)
No matches found
Grep (font_get_text_width)
E:\a327ex\emoji-aimer\anchor\font.lua:27: return font_get_text_width(self.name, text)
Grep (function font_get_text_width|font_get_text_width =)
No matches found
Grep (^function color\b|^color =)
105:color = color_new
Read (E:\a327ex\emoji-aimer\anchor\color.lua)
1 --[[
2 color — mutable RGBA color with HSL conversion helpers.
3
4 Simpler than v1's color class. A color is a plain table {r, g, b, a} with
5 a __call metamethod that returns the packed rgba integer used by drawing
6 functions. No auto-sync between RGB and HSL — HSL is a *conversion*, not a
7 storage format. If you want to modify hue, convert to HSL, modify, convert
8 back.
9
10 Usage:
11 red = color_new(255, 0, 0)
12 red.a = 128 -- set alpha
13 layer_circle(game_layer, x, y, r, red()) -- __call returns packed rgba integer
14
15 -- HSL manipulation:
16 h, s, l = color_to_hsl(red)
17 h = (h + 120) % 360 -- shift hue
18 shifted = color_from_hsl(h, s, l, red.a)
19
20 -- Common operations:
21 copy = color_clone(red)
22 mixed = color_mix(red, blue, 0.5)
23 dark = color_darken(red, 0.5) -- multiply RGB by 0.5
24 light = color_lighten(red, 1.5) -- multiply RGB by 1.5 (clamped)
25 inverted = color_invert(red)
26
27 Design notes:
28 - Colors are plain tables. Modify fields directly: c.r = 100.
29 - Procedural functions (color_mix, color_clone, etc.) return NEW colors,
30 not mutating the input. If you want to mutate, do `c.r = ...` directly.
... [10 more lines]
Bash (grep -n "^function color_new|color_new =" E:/a327ex/emoji-aimer/anchor/color.lu...)
94:function color_new(r, g, b, a)
Done. Summary of what I added:
Assets
- 19 emojis downloaded to
emoji-aimer/assets/at 512×512 Twemoji style via jsdelivr SVG → wsrv.nl rasterizer.- New (16): shield, crossed_swords, bow_and_arrow, magic_wand, red_heart, four_leaf_clover, magnet, skull, bomb, feather, eye, test_tube, coffee, hot_pepper, bone, locked.
- Re-downloaded at 512 (were 256): coin, gem, crown.
Code in main.lua
- Image registrations for all 16 new emojis (main.lua:261).
SHOP_KIT_ITEMS(main.lua:1482) — 6 sample items (name + emoji + price + desc + stats) powering the tile/tooltip demos.- Draw helpers (after
draw_hud_chip):draw_shop_item_tile(x, y, item, state)— 48×56 card; states: default / hovered / owned (green banner) / unaffordable.draw_shop_tooltip(x, y, item)— popup card; yellow header band with name + right-aligned price chip, then stat lines, then description.draw_shop_tier_header(x, y, label, price)— "TIER N" + price chip.draw_shop_owned_strip(x, y, items, max_slots)— row of 18×18 slots.draw_shop_button(x, y, w, h, label, state, variant)— rounded button; variants primary (yellow) / secondary (fg), states default / hovered / disabled.draw_shop_locked_overlay(x, y, w, h)— translucent dim band + padlock.
draw_shop_ui_kit()— scatters all of the above across the screen. Wired into the shop draw block.
Compile and run — let me know how each element looks. Easiest review pass is probably to go element by element: tile states first (are the four states distinct enough? tile dimensions OK? emoji-to-name ratio right?), then tooltip, then the rest. I expect a few things to need tuning — text vertical centering in narrow chips and the owned-banner contrast against the cream tile are the two I'd watch for.
Let's focus on each element at a time. Hide all the other ones and lets focus on the emoji cards for now.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Hidden. Only the four item-tile states render now — default, hovered, owned, unaffordable, spread across the middle of the screen with breathing room. The other helpers (tooltip, tier header, owned strip, buttons, locked overlay) stay defined and we'll bring them back into the kit one at a time as we finish tuning each.
Run it and tell me what you want to change about the tile. Things I'd watch for: tile size (48×56 — too small? too big?), emoji-to-name ratio, frame contrast on each state, whether the "OWNED" green banner reads well, whether unaffordable's fg_dark frame alone is enough differentiation or if the contents need dimming too.
OK, remove the camera wobble from the shop view only, then let's have elements actually work while taking input into account. Hovering should highlight the element and also spring pull it subtly, OWNED needs to be another font, FatFont at size 8 is actually very big, so you need to use Awesome Font as you used elsewhere instead, or just use Lana directly instead there. The right-most card is for when its not selected or not available to be bought or something else?
Let me check how fonts.big actually looks in the existing code and how springs are wired up before I touch anything.
Grep (fonts.big|fonts.main|fonts.mid)
1149: layer_text(cursor_layer, text, fonts.mid, cur_x, -8, tier.color())
1510: layer_text(ui_content_layer, lbl, fonts.big, x + w/2 - lbl_w/2, y + h - 11, white())
1513: layer_text(ui_content_layer, item.name, fonts.main, x + w/2 - name_w/2, y + 38, white())
1539: layer_text(ui_content_layer, item.name, fonts.main, x + pad, y + 3, white())
1546: layer_text(ui_content_layer, price_str, fonts.main, px + coin_size + 3, y + 3, white())
1551: layer_text(ui_content_layer, lbl, fonts.main, x + pad, cy, white())
1553: layer_text(ui_content_layer, val, fonts.main, x + w - pad - val_w, cy, white())
1557: layer_text(ui_content_layer, item.desc, fonts.main, x + pad, cy, white())
1562: layer_text(ui_content_layer, tier_label, fonts.big, x, y, white())
1574: layer_text(ui_content_layer, price_str, fonts.main, chip_x + pad_x,
1608: layer_text(ui_content_layer, label, fonts.main, x + w/2 - lbl_w/2, text_y, white())
2002: -- fonts.mid (Awesome 9 @ 16) for impact; hint uses fonts.main.
2008: layer_text(ui_content_layer, title, fonts.mid, gw/2 - title_w/2, gh/2 - 16, white())
2009: layer_text(ui_content_layer, hint, fonts.main, gw/2 - hint_w/2, gh/2 + 8, white())
Grep (^function spring_new|^function spring_update|^function spring_pull|^function spring_animate)
27:function spring_new()
63:function spring_pull(s, name, force, frequency, bounce)
101:function spring_update(s, dt)
Read (E:\a327ex\emoji-aimer\anchor\spring.lua)
1 --[[
2 spring — procedural damped spring animation.
3
4 Usage:
5 self.spring = spring_new() -- in constructor
6 spring_add(self.spring, 'scale', 1, 5, 0.5) -- name, initial value, frequency, bounce
7 spring_pull(self.spring, 'scale', 0.3) -- apply impulse
8 spring_update(self.spring, dt) -- in update
9
10 -- Read current value:
11 local s = self.spring.scale.x
12
13 A default 'main' spring at value 1 is created on spring_new() for convenience.
14 You typically use spring.main.x as a single pulsing value for hit flashes,
15 click feedback, etc.
16
17 Spring parameters:
18 frequency - oscillations per second (higher = faster)
19 bounce - bounciness 0-1 (0=no overshoot, 1=infinite oscillation)
20 bounce=0.5 is moderate overshoot, common for hit reactions.
21 ]]
22
23 --[[
24 spring_new()
25 Creates a new spring container with a default 'main' spring at value 1.
26 ]]
27 function spring_new()
28 local s = {
29 _names = {},
30 }
... [80 more lines]
Got it. Let me also clarify the rightmost card — I had it as the unaffordable state (you can see the item but can't buy it because gold < price). Per the earlier design discussion (no rarity, no locking — just price-gated), unaffordable is the only natural "negative" state per-tile. Tier-level locks live on the tier overlay, not on individual tiles. If you want the rightmost card to mean something else (out of stock, prerequisite locked, etc.), tell me.
Making all the changes:
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now wire up the kit tile state + update loop, replace the kit draw function.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now wire shop_kit_init into bootstrap, shop_kit_update into the update loop, and gate camera attach on shop.
Read (E:\a327ex\emoji-aimer\main.lua)
1672 end
1673 end
1674
1675 function spawn_target(x, y)
1676 local t = target(x, y)
1677 targets[#targets + 1] = t
1678 return t
1679 end
1680
1681 -- Try to spawn one target at a random arena position. Bails (returns false)
1682 -- if every attempt overlapped an existing target's TARGET_MIN_SPAWN_DIST
1683 -- exclusion zone. Caller is responsible for deciding *whether* to spawn —
1684 -- this just handles the "find a safe spot" placement.
1685 function try_spawn_target()
1686 for attempt = 1, 20 do
1687 local x = random_float(ARENA_X_MIN + TARGET_RADIUS, ARENA_X_MAX - TARGET_RADIUS)
1688 local y = random_float(ARENA_Y_MIN + TARGET_RADIUS, ARENA_Y_MAX - TARGET_RADIUS)
1689 local ok = true
1690 for _, t in ipairs(targets) do
1691 if not t._dead and math.length(x - t.x, y - t.y) < TARGET_MIN_SPAWN_DIST then
1692 ok = false
1693 break
1694 end
1695 end
1696 if ok then
Grep (^the_combo_display = combo_display()|^the_cursor)
1852:the_cursor = cursor()
1853:the_combo_display = combo_display()
Read (E:\a327ex\emoji-aimer\main.lua)
1849 -- init
1850 -- -----------------------------------------------------------------------------
1851 mouse_set_visible(false)
1852 the_cursor = cursor()
1853 the_combo_display = combo_display()
1854
1855 -- Boot entry. Pick exactly one:
1856 -- start_round(1) — start the run normally at round 1
1857 -- round_index=0; start_shop() — start in the shop before round 1
1858 -- (round_index=0 makes the shop's "upcoming round" read as 1, and exit_shop
1859 -- will bump it to 1 and start round 1 cleanly.)
1860 round_index = 0
1861 start_shop()
1862
1863 -- -----------------------------------------------------------------------------
1864 -- main loop
1865 -- -----------------------------------------------------------------------------
1866 function update(dt)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now shop_kit_update in the update loop. Let me find a good spot.
Read (E:\a327ex\emoji-aimer\main.lua)
1888 end
1889
1890 the_cursor:update(dt)
1891 the_combo_display:update(dt)
1892
1893 -- Combo timer ticks while a streak is alive; tick gated to active states
1894 -- so combo doesn't decay during 'won' / 'lost' (lets the player see their
1895 -- final streak). Round transitions reset combo via start_round.
1896 if (game_state == 'playing' or game_state == 'cleared') and combo_count > 0 then
1897 combo_timer = combo_timer - dt
1898 if combo_timer <= 0 then on_combo_break() end
1899 end
1900
1901 -- 'playing' → 'cleared' when kill count hits the target. Targets and
1902 -- resources both stay alive — clicks are already gated to 'playing' so
1903 -- the targets just sit there inert, and the cleared check in
1904 -- resource:update flips resources into vacuum mode (full-strength pull
1905 -- regardless of distance) so they fly to the cursor for collection.
1906 -- Everything gets killed by advance_round() at the in→mid boundary,
1907 -- once the yellow circle has fully covered the screen.
1908 if game_state == 'playing' and kills_this_round >= ROUNDS[round_index].target_kills then
1909 game_state = 'cleared'
1910 end
1911
1912 -- Resources all in → start the round-end wipe. transition.phase guard
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now gate the camera attach for UI layers on shop. Find the attach/detach block.
Grep (camera(attach|detach)(main_camera, ui)
2011: camera_attach(main_camera, ui_panel_layer)
2012: camera_attach(main_camera, ui_content_layer)
2061: camera_detach(main_camera, ui_content_layer)
2062: camera_detach(main_camera, ui_panel_layer)
Read (E:\a327ex\emoji-aimer\main.lua)
2007
2008 -- UI is camera-attached so the chips wobble with the side walls under
2009 -- the handcam. overlay_layer / cursor_layer / transition_layer stay in
2010 -- screen space so the dim, the cursor, and the wipe circle don't shake.
2011 camera_attach(main_camera, ui_panel_layer)
2012 camera_attach(main_camera, ui_content_layer)
2013
2014 -- HUD chips stacked vertically along the top of the LEFT side wall.
2015 -- Drawn on ui_content_layer in white; the outline_shader pass below
2016 -- adds the chunky black halo so the white text reads against the cream
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Read (E:\a327ex\emoji-aimer\main.lua)
2061 -- Replaces the real shop layout for now.
2062 if game_state == 'shop' then draw_shop_ui_kit() end
2063
2064 camera_detach(main_camera, ui_content_layer)
2065 camera_detach(main_camera, ui_panel_layer)
2066
2067 -- Round-end wipe — yellow circle on transition_layer (rendered last in
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary:
- Camera wobble removed for shop. The
camera_attach/camera_detachpair aroundui_panel_layerandui_content_layeris now gated ongame_state ~= 'shop'. Shop tiles render in pure screen space. - Hover wired up via
shop_kit_update(dt)(main.lua:1666) — runs only whengame_state == 'shop'. Each tile carries its own persistent spring and ahoveredflag. Hit-test against tile bbox each frame; on hover-enter (hovered now, not last frame) wespring_pull(spring, 'main', 0.08)for a subtle scale pulse. Spring scale is read in draw and applied via alayer_pushwrapping the whole tile so frame + emoji + label all pulse together. draw_shop_item_tilesignature changed —base_state ∈ {'available', 'owned', 'unaffordable'}is decoupled from the transienthoveredflag. A tile can be hovered AND owned simultaneously now.- OWNED label uses
fonts.main(LanaPixel @ 11) instead offonts.big. FatPixelFont @ 8 was chunkier than the banner needed. Banner geometry unchanged (14px), text vertically centered via the same+1nudgedraw_hud_chipuses. - Rightmost tile = unaffordable, confirming the original intent. If you want different semantics there (out of stock, prerequisite locked, etc.), let me know.
Things to watch when you run it: the spring pulse is currently a 0.08 impulse (~8% pop). If that feels too small or too big, easy to tune in shop_kit_update. And the OWNED label might want a small vertical nudge — LanaPixel at 11 in a 14-tall banner can look a hair high without the +1 adjustment.
Let's have the text be kind of like the owned one, except behind a yellow bar. The owned bar is green, the unaffordable is gray. Text for sword and owned specifically is lower than normal, not sure if those elements are default to a scale slightly below 1 but they look choppy. When we're hovering over the element, have the emoji wobble a little, I believe the wobble camera effect we have can also be applied to individual objects, although you may have to read documentation there. Either we can have the emoji itself move like that, or the entire card, we'll try both variations to see which looks better. Emoji on unaffordable card should be grayed out.
Let me check how the handcam shake works so I can apply it to a tile or emoji.
Read (E:\a327ex\emoji-aimer\anchor\shake.lua)
1 --[[
2 shake — procedural camera shake system.
3
4 Lives as a sub-structure of a camera. Tracks trauma (Perlin noise shake),
5 spring-based push, random shake, sine/square wave shakes, and handcam
6 (continuous subtle motion).
7
8 Usage:
9 -- Part of camera_new; normally you don't create shake directly.
10 -- In game code you access camera.shake.
11 shake_push(camera.shake, angle, amount)
12 shake_shake(camera.shake, amplitude, duration)
13 shake_trauma(camera.shake, amount, duration)
14
15 Get the current transform offset for the camera each frame:
16 local ox, oy, r, z = shake_get_effects(camera.shake)
17 ]]
18
19 --[[
20 shake_new()
21 Create a new shake state table. Normally called by camera_new.
22 ]]
23 function shake_new()
24 return {
25 -- Trauma (Perlin noise shake)
26 trauma_instances = {},
27 trauma_amplitude = {x = 24, y = 24, rotation = 0.2, zoom = 0.2},
28 trauma_time = 0,
29
30 -- Spring-based push (directional impulses)
... [257 more lines]
Let me check how layer_image handles the color parameter — that's the easiest way to gray out the emoji.
Read (E:\a327ex\emoji-aimer\anchor\layer.lua)
160 function layer_rectangle_gradient_h(lyr, x, y, w, h, color1, color2)
161 eng.rectangle_gradient_h(lyr_handle(lyr), x, y, w, h, color1, color2)
162 end
163
164 function layer_rectangle_gradient_v(lyr, x, y, w, h, color1, color2)
165 eng.rectangle_gradient_v(lyr_handle(lyr), x, y, w, h, color1, color2)
166 end
167
168 --- Image object (has .handle) or pass-through same as engine.
169 function layer_image(lyr, img, x, y, color, flash)
170 eng.draw_texture(lyr_handle(lyr), img.handle, x, y, color or 0xFFFFFFFF, flash or 0)
171 end
172
173 --- Raw texture userdata / handle at x, y.
174 function layer_texture(lyr, tex, x, y, color)
175 eng.draw_texture(lyr_handle(lyr), tex, x, y, color or 0xFFFFFFFF, 0)
176 end
177
178 function layer_spritesheet(lyr, sheet, frame, x, y, color, flash)
179 eng.draw_spritesheet_frame(lyr_handle(lyr), sheet.handle, frame, x, y, color or 0xFFFFFFFF, flash or 0)
180 end
181
182 function layer_animation(lyr, animation_object, x, y, color, flash)
183 eng.draw_spritesheet_frame(
184 lyr_handle(lyr),
185 animation_object.spritesheet.handle,
186 animation_object.frame,
187 x, y,
188 color or 0xFFFFFFFF,
189 flash or 0
... [10 more lines]
Got the shake module. It can run standalone — each tile gets its own shake state with handcam enabled. I'll wire shake offsets through the draw instead of spring scale (which was causing the choppiness — sub-pixel scale fluctuation on pixel art).
Plan:
- Replace per-tile
springwith per-tileshakestate, always-on handcam, staggered phase. - Add a
hover_amountthat lerps 0↔1; multiply shake offsets by it so wobble fades in/out smoothly. - Banner on all three states: yellow (available), green (owned), gray (unaffordable). Same Y position everywhere — fixes the "lower than normal" alignment.
- Tile shrinks 56 → 48 tall so the banner sits closer under the emoji.
- Unaffordable emoji is tinted via the existing
layer_imagecolor param (multiplicative dim). SHOP_KIT_WOBBLE_MODE = 'emoji' | 'card'constant to toggle which part wobbles.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now rewrite draw_shop_item_tile with banners on all states, gray-tinted emoji on unaffordable, and shake-based wobble.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now rewrite the kit init / update / draw to use shake state and hover_amount.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary of what changed:
Tile design refresh (main.lua:1493)
- Shrunk tile 48×56 → 48×48 so the banner sits closer under the emoji. Fixes the "lower than normal" feeling — all banner text now sits at the same Y across every state.
- Banners on all three states, same geometry: yellow (available), green (owned), gray (unaffordable). White text + outline_shader halo for legibility on any color.
- Unaffordable emoji is multiplicatively dimmed via
layer_image(..., color(140,140,140,255)()). Frame also drops tofg_dark. Both together read clearly as "off-limits." - OWNED label uses
fonts.main(LanaPixel @ 11). Same font/position as the item name in other states — no more mismatch.
Hover wobble via shake_handcam (main.lua:1657)
- Each tile owns a standalone
shakestate with handcam enabled (ampx=2, y=2, rotation=0.05, frequency1.0). Initialhandcam_timeis staggered withrandom_float(0, 100)so the four tiles don't wobble in sync. hover_amountlerps 0↔1 (dt*10smoothing factor). Shake offsets are multiplied by it in draw, so the wobble fades in/out rather than snapping on hover-enter / hover-leave.- No more spring scale — that was the source of the choppy text. Pure translation + rotation translates much cleaner onto pixel art than fractional scale.
Mode toggle (main.lua:1490)
SHOP_KIT_WOBBLE_MODE = 'emoji'(default) — only the icon shakes inside a stationary frame.- Change to
'card'— the whole tile (frame + banner + emoji + label) wobbles as a unit.
Tunables if anything feels off when you run it:
- Wobble amplitude →
shake_handcamcall (x=2, y=2, rotation=0.05). - Wobble frequency → fourth arg of
shake_handcam(1.0now; lower = slower). - Fade speed →
dt*10inshop_kit_update. - Emoji dim level →
color(140, 140, 140, 255)indraw_shop_item_tile. - Banner height →
banner_h = 14.
Hit me with whichever you want to tweak first when you've seen both modes.
What size are the emojis now?
28×28 pixels in the 480×270 internal resolution.
Source PNGs are 512×512; they get scaled down to 28×28 by s = icon_size/item.img.width in draw_shop_item_tile. With the game's 3× display scale that's 84×84 actual screen pixels.
In context of the 48×48 tile: emoji occupies a 28×28 box centered horizontally with 2px top padding (Y range 2..30), leaving Y 34..48 for the 14-tall banner and a 4px gap between them.
To change it, edit icon_size = 28 in main.lua inside draw_shop_item_tile. The scale recomputes automatically from the source width.
[Pasted image/png]
Decrease them to 22x22, wobble the entire card, make the corners more rounded. Enforce correct size and scale on text, it's still showing up as incorrect on "sword" and "owned", like the image I posted. Use a shader to turn the heart into actual grayscale. Bring back spring pull on hover enter.
Good catch on the SWORD/OWNED text — that's a sub-pixel alignment bug. Odd text widths divided by 2 produce fractional offsets which snap differently per glyph. Need math.floor on the centered positions.
Let me check the existing shader format before writing the grayscale one.
Read (E:\a327ex\emoji-aimer\assets\recolor.frag)
1 // Recolor shader - maps grayscale emoji to target color
2 // Gray background becomes target color, white text stays white
3 in vec2 TexCoord;
4 out vec4 FragColor;
5 uniform sampler2D u_texture;
6 uniform vec4 u_target_color; // target color (0-1 range, alpha ignored)
7
8 void main() {
9 vec4 tex = texture(u_texture, TexCoord);
10
11 // Grayscale value
12 float gray = tex.r;
13
14 // Background is 120/255 (~0.471), text is 1.0
15 // Normalize: 0.471 -> 0, 1.0 -> 1
16 float t = (gray - 0.471) / (1.0 - 0.471);
17 t = clamp(t, 0.0, 1.0);
18
19 // Mix target color -> white
20 vec3 color = mix(u_target_color.rgb, vec3(1.0), t);
21
22 FragColor = vec4(color, tex.a);
23 }
24
Read (E:\a327ex\emoji-aimer\assets\outline.frag)
1 // Outline shader - samples neighbors to detect alpha edges
2 // Outputs black where any neighbor has alpha, creating silhouette outline
3 in vec2 TexCoord;
4 out vec4 FragColor;
5 uniform sampler2D u_texture;
6 uniform vec2 u_pixel_size;
7
8 void main() {
9 // Sample center pixel
10 vec4 center = texture(u_texture, TexCoord);
11
12 // Sample 24 neighbors in 5x5 grid (excluding center)
13 float x = u_pixel_size.x;
14 float y = u_pixel_size.y;
15
16 float a = 0.0;
17 // Row -2
18 a += texture(u_texture, TexCoord + vec2(-2.0*x, -2.0*y)).a;
19 a += texture(u_texture, TexCoord + vec2(-1.0*x, -2.0*y)).a;
20 a += texture(u_texture, TexCoord + vec2( 0.0, -2.0*y)).a;
21 a += texture(u_texture, TexCoord + vec2( 1.0*x, -2.0*y)).a;
22 a += texture(u_texture, TexCoord + vec2( 2.0*x, -2.0*y)).a;
23 // Row -1
24 a += texture(u_texture, TexCoord + vec2(-2.0*x, -1.0*y)).a;
25 a += texture(u_texture, TexCoord + vec2(-1.0*x, -1.0*y)).a;
26 a += texture(u_texture, TexCoord + vec2( 0.0, -1.0*y)).a;
27 a += texture(u_texture, TexCoord + vec2( 1.0*x, -1.0*y)).a;
28 a += texture(u_texture, TexCoord + vec2( 2.0*x, -1.0*y)).a;
29 // Row 0 (skip center)
30 a += texture(u_texture, TexCoord + vec2(-2.0*x, 0.0)).a;
... [25 more lines]
Now I'll create the grayscale shader and make all the changes.
Write (E:\a327ex\emoji-aimer\assets\grayscale.frag)
File created successfully at: E:\a327ex\emoji-aimer\assets\grayscale.frag (file state is current in your context — no need to Read it back)
Now wire the shader and the grayscale_layer into main.lua.
Read (E:\a327ex\emoji-aimer\main.lua)
238 -- -----------------------------------------------------------------------------
239 -- shaders
240 -- -----------------------------------------------------------------------------
241 shadow_shader = shader_load_file('assets/shadow.frag')
242 outline_shader = shader_load_file('assets/outline.frag')
243 recolor_shader = shader_load_file('assets/recolor.frag') -- gray-keycap → target color, white digit stays white
244 shader_set_vec2_immediate(outline_shader, 'u_pixel_size', 1/gw, 1/gh)
245
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now add the grayscale layer near the other layer declarations.
Grep (^digit_layer\s*=)
223:digit_layer = layer_new('digit')
Read (E:\a327ex\emoji-aimer\main.lua)
220 -- recolor_shader's u_target_color uniform, and draw_from into effects_layer
221 -- so the gray keycap sprites get recolored to the bucket's tier color (digit
222 -- stays white via the shader's gray-vs-white mix).
223 digit_layer = layer_new('digit')
224
225 -- Cursor on its own outlined layer so it renders on top of everything else
226 -- without the shader merging it into the UI silhouettes.
227 cursor_layer = layer_new('cursor')
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now flip the wobble mode to 'card' and rewrite the tile draw function with the new sizing, rounded corners, grayscale routing, spring scale, and pixel-snapped text.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Update shop_kit_init, shop_kit_update, and draw_shop_ui_kit to add the spring and use the tile-struct call signature.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the grayscale pass — add it after the recolor pass and before the outline derivation.
Grep (layer_draw_from(effects_layer, digit_layer, recolor_shader))
2179: layer_draw_from(effects_layer, digit_layer, recolor_shader)
Read (E:\a327ex\emoji-aimer\main.lua)
2178 'u_target_color', col.r/255, col.g/255, col.b/255, 1)
2179 layer_draw_from(effects_layer, digit_layer, recolor_shader)
2180 end
2181 camera_detach(main_camera, digit_layer)
2182 end
2183
2184 -- Derive shadow + outline passes via the outline / shadow shaders.
2185 layer_clear(shadow_layer)
2186 layer_draw_from(shadow_layer, game_layer, shadow_shader)
2187 layer_draw_from(shadow_layer, effects_layer, shadow_shader)
2188
2189 layer_clear(game_outline)
2190 layer_draw_from(game_outline, game_layer, outline_shader)
2191 layer_clear(effects_outline)
2192 layer_draw_from(effects_outline, effects_layer, outline_shader)
2193 layer_clear(ui_panel_outline)
2194 layer_draw_from(ui_panel_outline, ui_panel_layer, outline_shader)
2195 layer_clear(ui_content_outline)
2196 layer_draw_from(ui_content_outline, ui_content_layer, outline_shader)
2197 layer_clear(cursor_outline)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary:
Sizing
- Emoji
icon_size = 28 → 22. With the tile still 48×48, that's a 6px top padding and 6px gap to the banner, slightly more breathing room around the icon. - Corner radius
3 → 6, more pronounced rounding.
Text alignment fix (the SWORD/OWNED bug)
text_x = math.floor(-lbl_w/2)in draw_shop_item_tile. Odd-width glyph runs (SWORD, OWNED) were landing at-13.5etc., and with nearest-neighbor sampling each glyph snapped to a different integer column, producing the squished look. Floor-snapping the centered origin makes glyph spacing deterministic.
Wobble
SHOP_KIT_WOBBLE_MODE = 'card'— the whole tile (frame + banner + emoji + label) wobbles as a unit now.
Spring pull back
- Each tile carries a
springagain. On hover-enter (was-not-hovered, is-now),spring_pull(spring, 'main', 0.08)gives a one-shot scale pop. While idle,spring.main.x = 1.0so it doesn't drift. - Continuous shake (handcam) is still gated by
hover_amountso it fades in/out cleanly; the spring is the discrete "tap" on hover-enter.
True grayscale via shader
- New
emoji-aimer/assets/grayscale.fragdoes luminance-based desat:lum = 0.299*r + 0.587*g + 0.114*b, alpha preserved. - New
grayscale_layer. Unaffordable tiles route their emoji draw tograyscale_layerinstead ofui_content_layer. The outer card transform is pushed ongrayscale_layerfor those tiles only so the geometry matches. - After the existing recolor pass and before outline derivation, a shop-only grayscale pass:
layer_render(grayscale_layer)→layer_draw_from(ui_content_layer, grayscale_layer, grayscale_shader). Outline shader then catches the gray silhouette and gives it the same black halo as everything else.
Things still to watch when you run it: during the spring pop (~0.5s) the scaled text will go through fractional pixel positions, so it may briefly look soft before settling. If that's noticeable I can quantize the scale or move the pop effect off the text-bearing transform (only scale the emoji, leave the banner static). Just say the word.
Perfect. It seems you have rounded corners only on the top corners, make all of them rounded. Text should be 1 pixel down too. And then, how many of these can you fit on the screen on a grid, leaving space for other things on the side and some space bottom/top for the rest of the UI?
Three things to address. Let me fix the rounded corners and text shift in code first, then answer the grid question.
Rounded corners fix: the banner is a non-rounded rect drawn over the rounded frame, which is why only the top corners show curvature. Switching the banner to a rounded rect of the same radius makes its bottom corners exactly match the frame's bottom corners; the banner's top rounded corners would normally create small notches against the frame, so I'll fill those notches with two radius × radius rects so the banner top still reads as flat.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Text 1px down:
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Grid capacity answer
Working with a 480×270 screen, 48×48 tiles, and 4-px gaps between tiles. The math depends on what you reserve for the surrounding UI. Here's the budget:
| Reserved | Width | Height |
|---|---|---|
| Side margins (8 each) | 16 total | — |
| Top (title + gold counter row) | — | ~28 |
| Bottom (owned strip + back/next) | — | ~36 |
| Grid area | 464 | 206 |
With 48×48 + 4 gap (cell pitch = 52):
- Columns:
(464 + 4) / 52 = 9.0→ 9 columns (fills exactly: 9·48 + 8·4 = 464). - Rows in pure grid (no tier headers between rows):
(206 + 4) / 52 = 4.04→ 4 rows (uses 204).
Flat grid: 9 × 4 = 36 tiles.
If you want tier headers inside the grid (one header strip above each row, ~12 tall + 4 gap), each tier section eats 16 extra px:
- 1 tier × 4 rows → header + 4·48 + 3·4 = 220, doesn't fit in 206.
- 4 tiers × 1 row each → 4·(16 + 48) − 4 (no gap after last) = 252, doesn't fit.
- 3 tiers × 1 row each → 3·(16 + 48) − 4 = 188, fits → 3 tier sections × 9 cols = 27 tiles total.
So:
- Flat grid (Deadlock catalog style, no inline tier headers): 36 tiles.
- With per-row tier headers (3 tiers visible): 27 tiles.
- With all 4 tier headers inline: doesn't fit at 48×48 — would need to shrink tiles to ~40×40 (then 10 cols × 4 tier rows = 40 tiles, with tighter headers).
A practical mid-point: a flat 9 × 4 grid (36 tiles), with tier labels living outside the grid — e.g., a row of "Tier 1 · Tier 2 · Tier 3 · Tier 4" pills along the top, or color-coded tile borders by tier instead of section dividers. That keeps the layout dense without sacrificing the per-tile size you've already tuned.
Want me to lay out a placeholder 9×4 grid in the kit so you can see it at scale before committing to a tier-divided variant?
Yes, also use all the emojis you downloaded and their names so we can fix any issues regarding text size.
Let me check what existing emoji images are loaded so I can use all of them in the kit.
Grep (sparkles|collision)
7: ring, more particles (collision + sparkle emojis), bigger shake. New target
322:physics_enable_collision('resource', 'wall')
323:physics_enable_collision('resource', 'resource')
324:physics_enable_collision('resource', 'target')
2035: -- Resource ↔ target collisions — small spring pulse on both bodies so
2038: for _, ev in ipairs(collision_entities_begin('resource', 'target')) do
Grep (image_load|spritesheet_register)
257:direct_hit_img = image_load('direct_hit', 'assets/direct_hit.png')
258:star_img = image_load('star', 'assets/star.png')
259:backhand_index_pointing_up = image_load('backhand_index_pointing_up','assets/backhand_index_pointing_up.png')
260:hourglass_img = image_load('hourglass', 'assets/hourglass_done.png')
261:high_voltage_img = image_load('high_voltage', 'assets/high_voltage.png')
262:fire_img = image_load('fire', 'assets/fire.png')
263:x_mark_img = image_load('x_mark', 'assets/x_mark.png')
264:coin_img = image_load('coin', 'assets/coin.png')
265:gem_img = image_load('gem', 'assets/gem.png')
266:crown_img = image_load('crown', 'assets/crown.png')
270:shield_img = image_load('shield', 'assets/shield.png')
271:crossed_swords_img = image_load('crossed_swords', 'assets/crossed_swords.png')
272:bow_and_arrow_img = image_load('bow_and_arrow', 'assets/bow_and_arrow.png')
273:magic_wand_img = image_load('magic_wand', 'assets/magic_wand.png')
274:red_heart_img = image_load('red_heart', 'assets/red_heart.png')
275:four_leaf_clover_img = image_load('four_leaf_clover', 'assets/four_leaf_clover.png')
276:magnet_img = image_load('magnet', 'assets/magnet.png')
277:skull_img = image_load('skull', 'assets/skull.png')
278:bomb_img = image_load('bomb', 'assets/bomb.png')
279:feather_img = image_load('feather', 'assets/feather.png')
280:eye_img = image_load('eye', 'assets/eye.png')
281:test_tube_img = image_load('test_tube', 'assets/test_tube.png')
282:coffee_img = image_load('coffee', 'assets/coffee.png')
283:hot_pepper_img = image_load('hot_pepper', 'assets/hot_pepper.png')
284:bone_img = image_load('bone', 'assets/bone.png')
285:locked_img = image_load('locked', 'assets/locked.png')
292: digit_imgs[tostring(i)] = image_load('digit_' .. i, 'assets/' .. i .. '.png')
296:digit_imgs['+'] = image_load('digit_plus', 'assets/plus.png')
298:spritesheet_register('hit1', 'assets/hit1.png', 96, 48)
Grep (sparkles|collision.png)
No matches found
Glob (emoji-aimer/assets/*.png)
emoji-aimer\assets\star.png
emoji-aimer\assets\collision.png
emoji-aimer\assets\sparkles.png
emoji-aimer\assets\direct_hit.png
emoji-aimer\assets\backhand_index_pointing_up.png
emoji-aimer\assets\hit1.png
emoji-aimer\assets\hourglass_done.png
emoji-aimer\assets\high_voltage.png
emoji-aimer\assets\fire.png
emoji-aimer\assets\0.png
emoji-aimer\assets\1.png
emoji-aimer\assets\2.png
emoji-aimer\assets\3.png
emoji-aimer\assets\4.png
emoji-aimer\assets\5.png
emoji-aimer\assets\6.png
emoji-aimer\assets\7.png
emoji-aimer\assets\8.png
emoji-aimer\assets\9.png
emoji-aimer\assets\x.png
emoji-aimer\assets\x_mark.png
emoji-aimer\assets\plus.png
emoji-aimer\assets\shield.png
emoji-aimer\assets\crossed_swords.png
emoji-aimer\assets\bow_and_arrow.png
emoji-aimer\assets\magic_wand.png
emoji-aimer\assets\red_heart.png
emoji-aimer\assets\four_leaf_clover.png
emoji-aimer\assets\magnet.png
emoji-aimer\assets\skull.png
... [11 more lines]
Grep (collision.png|sparkles.png|'sparkles'|'collision')
No matches found
Loading sparkles and collision (the two unused Twemoji PNGs already in assets) so I have 28 items to fill more of the 36-cell grid.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now replace the 4-item sample list with 28 items using their actual emoji names (including the deliberately long ones like FOUR LEAF CLOVER and CROSSED SWORDS to surface overflow), then rewrite shop_kit_init for the 9×4 grid and update draw_shop_ui_kit to render empty-slot placeholders.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now rewrite shop_kit_init for the 9×4 grid layout, plus split-out empty-slot rendering.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. The 9×4 grid is now wired up. Quick map of what you'll see:
Row 1 (items 1–9): SHIELD¹, CROSSED SWORDS, BOW AND ARROW, MAGIC WAND, RED HEART, FOUR LEAF CLOVER², MAGNET¹, SKULL, BOMB Row 2 (items 10–18): FEATHER, EYE, TEST TUBE, COFFEE, HOT PEPPER², BONE, LOCKED, COIN, GEM Row 3 (items 19–27): CROWN, DIRECT HIT, STAR¹, HIGH VOLTAGE², HOURGLASS, FIRE, X MARK, POINTER, SPARKLES Row 4 (item 28 + 8 empties): COLLISION², then 8 desaturated empty slots
¹ = owned (green banner with "OWNED") ² = unaffordable (gray banner with item name, grayscale emoji)
The names span 3 to 16 characters on purpose so you can see where things break:
- Short (3–4 chars): EYE, GEM, BOMB, BONE, COIN, STAR, FIRE
- Medium (5–7): SHIELD, SKULL, CROWN, MAGNET, X MARK, COFFEE, FEATHER, POINTER, LOCKED, HOURGLASS
- Long (8–10): SPARKLES, RED HEART, TEST TUBE, DIRECT HIT, HOT PEPPER, COLLISION, MAGIC WAND
- Definitely overflow (12+): HIGH VOLTAGE, BOW AND ARROW, CROSSED SWORDS, FOUR LEAF CLOVER
Things to look for when you run it:
- Where overflow starts — anything over ~7 chars probably runs past the tile edge.
- Whether truncation, smaller font, or shorter display names is the right answer.
- Empty-cell visual (currently desaturated
fg_darkrounded rect) — works as a stand-in, or want something more obviously empty (dashed outline, ghost icon)?
Grid is at x=8..472 (8px side margins), y=28..232 (28 top, 38 bottom reserved for the other UI). Wobble + spring + hover work for all 28 interactive tiles.
This is good enough for this element, we can fix text on a per-item basis as we add actual items to the game progressively. What's the next UI element you initially implemented?
Next in the order I originally laid out is the hover tooltip — the popup card that surfaces full item details (name, price, description, optional stat lines) when you mouse over a tile. It's already defined as draw_shop_tooltip in main.lua, just not called from draw_shop_ui_kit right now.
Two ways we could approach this:
A. Show the tooltip in context — keep the 9×4 grid visible, and render the tooltip for whichever tile is currently hovered. Practical advantage: you see the tooltip at the actual size and position it'll appear in the real shop, and you can compare its scale against the tiles next to it. Iterating on layout/typography happens against realistic context.
B. Strict isolation — hide the grid like we did for the tile, and render 2–3 tooltip variants at fixed positions (e.g., one short, one long, one without stat lines) so you can compare them side by side.
I'd lean toward A for this one — the tile work is finalized so the grid can serve as backdrop, and a tooltip is by nature a hover element so seeing it driven by real hover state catches "what happens at the edge of the screen / under the cursor" issues you'd miss in isolation.
One thing to flag before I implement: the items currently only have name + img. To populate a tooltip I need price + description + stats — I'll just hardcode placeholder values per item (price scaled by name length or random, descriptions like "Block 5 damage every 4s", stats like {DAMAGE, +4}). That keeps focus on visual tuning rather than designing real mechanics.
Want me to go with A, or do you prefer B? And any preference on tooltip anchor — beside the tile (right or below, flipped near screen edges), or fixed somewhere on screen?
Yea, A. Yes, placeholder values for everything is fine.
Implementing it now. I'll need to:
- Update
draw_shop_tooltipwith the same notch-fill rounded corner treatment as the tile (currently has the same bug — sharp-cornered yellow header on a rounded panel). - Add
shop_tooltip_sizeandshop_tooltip_positionhelpers (the second handles screen-edge flipping). - Track
SHOP_KIT_HOVERED_TILEin update. - Augment items with placeholder price/desc/stats.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now wire up the hover tracking, placeholder data, and tooltip rendering.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now track hover in shop_kit_update and draw the tooltip in draw_shop_ui_kit.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Let me double-check one subpixel detail in the tooltip — the coin icon center.
Read (E:\a327ex\emoji-aimer\main.lua)
1559
1560 -- State palette: banner color + label.
1561 local banner_col, banner_text
1562 if t.base_state == 'owned' then banner_col, banner_text = green(), 'OWNED'
1563 elseif t.base_state == 'unaffordable' then banner_col, banner_text = gray(), t.item.name
1564 else banner_col, banner_text = yellow(), t.item.name end
1565
1566 -- Frame color: hover → white, unaffordable → fg_dark, else fg.
1567 local frame_col
1568 if t.hovered then frame_col = white()
Grep (px + cs/2)
1676: layer_push(ui_content_layer, px + cs/2, y + header_h/2, 0, coin_s, coin_s)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Here's how the tooltip behaves:
Trigger: appears for whichever grid tile is currently under the cursor; vanishes when the cursor moves off all tiles. The hovered tile still wobbles + scale-pops as before — the tooltip is layered on top.
Anchoring (shop_tooltip_position): defaults to the right side of the tile with a 4px gap. If that would overflow the right edge (rightmost grid column with a wide tooltip), it flips to the left. If the bottom edge would clip (bottom row with a tall tooltip), it shifts up so the bottom sits at gh - 4. Top and left clamps as final guards.
Visual (draw_shop_tooltip): white rounded panel (radius 6) with a yellow header band on top. Same notch-fill trick as the tile banner so the header band reads as flat-bottomed against the panel's rounded top corners. Header: item name (left), coin + price (right). Body: stat lines (label left, value right), then description.
Placeholder data (shop_kit_init): each item gets price = 100 + i*50, a description cycled from a 5-line pool, and a stat set cycled from a 5-set pool (so you'll see tooltips with 1, 2, and 3 stat lines as you move across the grid).
Things to watch when you run it:
- Tooltip pops between tiles as you move the cursor across the grid — feels jittery without a small hover delay? If so we can add a debounce.
- Long descriptions push the tooltip wider; long item names + 4-digit prices might collide in the header (no clipping handling yet).
- Flipping at the right edge — hover the rightmost column and verify the tooltip appears on the LEFT of the tile cleanly.
- Bottom-row hover — tooltip should shift up to stay on screen.
- Tooltip overlapping its own tile's wobble — the 4px gap should be enough but if the wobble amplitude swings far enough you might see touching.
Needs to be on a layer above normal UI elements for the grid.
[Request interrupted by user]
If button + button text are on layers ui_1, ui_2, for instance, we need tooltip + tooltip text to be on layers ui_3, ui_4 since they'll be on top of everything. All those layers outlined, of course.
Good call. Right now tile + tooltip share ui_panel_layer / ui_content_layer, so the outline shader treats overlapping pixels as one silhouette — the tooltip can't have a clean outline against the tile beneath it. Need two dedicated top-UI layers, each with their own outline pass.
Let me find the layer setup and rendering pipeline.
Read (E:\a327ex\emoji-aimer\main.lua)
205 -- ui_content_layer — text + icons. Drawn in WHITE so the shader's black
206 -- halo reads as a black outline around white interior
207 -- (matches the reference look). Icons get outlined too.
208 -- Both have a derived <layer>_outline pass that runs outline_shader on them.
209 ui_panel_layer = layer_new('ui_panel')
210 ui_panel_outline = layer_new('ui_panel_outline')
211 ui_content_layer = layer_new('ui_content')
212 ui_content_outline = layer_new('ui_content_outline')
213
214 -- Fullscreen dim for ROUND END. Not outlined — outlining a fullscreen rect
215 -- produces a fully-black screen.
216 overlay_layer = layer_new('overlay')
217
218 -- Intermediate layer for damage_number rendering. Each frame we bucket damage
219 -- numbers by rarity color; for each bucket we re-render to digit_layer, set
220 -- recolor_shader's u_target_color uniform, and draw_from into effects_layer
221 -- so the gray keycap sprites get recolored to the bucket's tier color (digit
222 -- stays white via the shader's gray-vs-white mix).
223 digit_layer = layer_new('digit')
224
225 -- Intermediate layer for the grayscale-emoji pass. Unaffordable shop-tile
226 -- emojis are drawn here (instead of ui_content_layer); each frame we
227 -- layer_render this, then draw_from it through grayscale_shader onto
228 -- ui_content_layer so the outline derivation picks up a true-grayscale
229 -- silhouette. Saves recoloring source PNGs.
230 grayscale_layer = layer_new('grayscale')
231
232 -- Cursor on its own outlined layer so it renders on top of everything else
233 -- without the shader merging it into the UI silhouettes.
234 cursor_layer = layer_new('cursor')
... [15 more lines]
Add the two new top UI layers right after the existing UI layers.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now update draw_shop_tooltip to draw to the new layers.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now wire the new layers into the rendering pipeline. Find the render block.
Grep (layer_render(ui_panel_layer)|layer_render(ui_content_layer))
2321: layer_render(ui_panel_layer)
2322: layer_render(ui_content_layer)
Read (E:\a327ex\emoji-aimer\main.lua)
2315 the_combo_display:draw()
2316
2317 -- Render queues to FBOs
2318 layer_render(bg_layer)
2319 layer_render(game_layer)
2320 layer_render(effects_layer)
2321 layer_render(ui_panel_layer)
2322 layer_render(ui_content_layer)
2323 layer_render(overlay_layer)
2324 layer_render(cursor_layer)
2325 layer_render(transition_layer)
2326
2327 -- Damage-number recolor pass. Bucket damage_numbers by their rarity_color
2328 -- (color object as table key — color objects are stable globals so identity
2329 -- works as a key). For each bucket: queue all its digits to digit_layer,
2330 -- render, set u_target_color uniform, draw_from into effects_layer applying
2331 -- recolor_shader. Done before the outline pass so the outlined silhouette
2332 -- includes the colored numbers.
2333 local damage_buckets = {}
2334 for _, fx in ipairs(effects) do
2335 if not fx._dead and fx.rarity_color then
2336 local key = fx.rarity_color
2337 damage_buckets[key] = damage_buckets[key] or {}
2338 table.insert(damage_buckets[key], fx)
2339 end
2340 end
2341 if next(damage_buckets) then
2342 camera_attach(main_camera, digit_layer)
2343 for col, bucket in pairs(damage_buckets) do
2344 for _, dn in ipairs(bucket) do dn:draw() end
... [50 more lines]
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Also need to mirror the camera attach/detach for the new layers so they behave like the existing UI (camera-attached outside shop, free in shop).
Grep (camera(attach|detach)(main_camera, ui(panel|content)_layer))
2250: camera_attach(main_camera, ui_panel_layer)
2251: camera_attach(main_camera, ui_content_layer)
2302: camera_detach(main_camera, ui_content_layer)
2303: camera_detach(main_camera, ui_panel_layer)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. The tooltip now lives on its own layer pair above the regular UI:
ui_top_panel_layer— tooltip panel + yellow header band fill + notch-fill rects.ui_top_content_layer— tooltip text (name, price, stats, description) + coin icon.
Both get their own outline derivative (ui_top_panel_outline, ui_top_content_outline) and composite in the order [ui_panel → ui_content → ui_top_panel → ui_top_content], so the tooltip silhouette is computed independently from any tile beneath it. Camera attach/detach mirrors the existing UI layers — camera-attached outside the shop, free in shop.
When you hover a tile now, the tooltip should have a clean, unbroken outline of its own — no merging with the tile underneath.
Everything looks good, let's just have the tooltip centered vertically against the card.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Tooltip Y now starts at tile_center - tooltip_height/2, math.floor'd for pixel alignment. The existing edge clamps still apply, so top-row tiles will shift the tooltip down off the top edge and bottom-row tiles will shift it up — they just compose with the new centered default instead of the previous top-aligned one.
Great, what's the next UI element?
Next in the original list is the tier header — the "TIER N" label + price chip that would label each tier section of the catalog.
There's already a draw_shop_tier_header(x, y, label, price) function defined. It renders the label in fonts.big (FatPixelFont @ 8) followed by a small rounded chip showing $<price>. One thing I'd want to flag upfront: fonts.big is the same font we ditched on the OWNED banner because it was visually chunky. The tier header might want it (heading style, "section divider" feel) or might want fonts.main for consistency. Easy to swap once you see it.
Layout question for this one: the tile and tooltip both had natural context (grid + hover-driven). The tier header's natural context is above a tier section in the grid — but the current grid is flat with no tier subdivision. So the "in context" approach doesn't really apply yet.
Three ways to show it:
- A. Hide the grid, render 4 tier headers stacked vertically with escalating prices ($300, $600, $1200, $2400). Clean isolation review.
- B. Keep the grid, render 4 tier headers above the top of the catalog as a horizontal row (tab-strip style, like Pixel Mart). Tests whether they fit in the 28px top reserve.
- C. Reorganize the grid into tier-divided rows (Tier 1 row of 9, Tier 2 row of 9, Tier 3 row of 9 with headers between — drops 1 item, doesn't fit Tier 4). Shows them in their final context but requires grid restructure.
I'd lean toward A since the tier header isn't a hover-driven or context-sensitive element — it's a static label, and isolation is the fastest path to tuning its typography + chip shape. Once it looks right, when we get to the full shop layout we can drop it wherever it ends up.
Sound good? Or do you want B or C instead?
Let's skip to the next element.,
Skipping to owned-items strip — the compact row of slots showing what you've purchased.
There's already draw_shop_owned_strip(x, y, items, max_slots) defined: a row of 18×18 rounded slots (radius 2), each filled slot rendering a 14×14 emoji centered.
Natural context for this one — the bottom 38px reserve under the grid is where it belongs. I'll keep the grid as backdrop and drop the strip in the bottom reserve, centered horizontally. Defaults I'll use:
- 10 slots, 5 filled with items from the grid (SHIELD, COFFEE, BOMB, MAGNET, BONE) + 5 empty. Mix demonstrates the "partial purchase" state.
- Slot size 18, gap 2 as currently defined.
- Slot radius 2 as currently defined — much sharper than the tiles' radius 6, deliberately small for visual differentiation, but easy to bump if you'd rather they match.
Things to look at when you run it:
- Slot size against tile size (18 vs 48) — does the strip feel like a "summary" of the catalog or too tiny?
- Empty slot vs filled — currently both have the same
fgframe, only difference is presence of emoji. Possibly empty slots should look dimmer / dashed to read as "no item" at a glance. - Whether the strip needs a label nearby ("OWNED" / "INVENTORY" / item count like "5 / 10").
Implementing now.
Read (E:\a327ex\emoji-aimer\main.lua)
1733 local chip_h = pad_y + 11 + pad_y
1734 local chip_x = x + lbl_w + 6
1735 local chip_y = y - 3
1736 layer_rounded_rectangle(ui_panel_layer, chip_x, chip_y, chip_w, chip_h, 2, fg())
1737 layer_text(ui_content_layer, price_str, fonts.main, chip_x + pad_x,
1738 math.floor(chip_y + chip_h/2 - 11/2 + 1), white())
1739 end
1740
1741 -- Compact row of slots — filled with emoji where occupied, outlined empty
1742 -- squares elsewhere. items is a sparse table indexed 1..max_slots.
1743 function draw_shop_owned_strip(x, y, items, max_slots)
1744 local slot = 18
1745 local gap = 2
1746 local icon_s = 14
1747 for i = 1, max_slots do
1748 local sx = x + (i - 1)*(slot + gap)
1749 layer_rounded_rectangle(ui_panel_layer, sx, y, slot, slot, 2, fg())
1750 local it = items[i]
1751 if it then
1752 local s = icon_s/it.img.width
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. The owned strip is now rendered in the bottom reserve area below the grid:
- 10 slots, 18×18 each with a 2px gap, total strip width 198px.
- Centered horizontally at
x ≈ 141. - Y = 242 (10px below the grid's bottom edge at y=232).
- 5 slots filled with SHIELD, COFFEE, BOMB, MAGNET, BONE; 5 empty.
Things to look at when you run it:
- Slot vs tile contrast — at 18×18 (~37% of tile size), does the strip read as a clear "summary" or get lost?
- Empty vs filled distinction — both use
fgframe currently. Hard to tell empty slots from "tile with no emoji" at a glance. Probably wants dimming (e.g.,fg_darkframe for empty), or a dotted outline, or a faint placeholder dot. - Corner radius mismatch — slots are radius 2, tiles are radius 6. They look different on purpose right now, but could match for consistency.
- No label nearby — Pixel Mart had "16 / 24 SLOTS" header. Do we want a count badge or "OWNED" label, or is the visual enough?
Let me know what to adjust.
You can remove the bottom line of the grid, increase the slot size to 22x22.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the slot size. I'll scale the icon proportionally (kept the same 4px padding ratio).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Update the strip's centering math in draw_shop_ui_kit to use the new slot size.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Changes:
- Grid is now 9×3 = 27 cells. Items 1–27 fill, item 28 (COLLISION) is unused. No empty cells. Grid now ends at y=180 (was 232), freeing ~50px of additional bottom space.
- Owned-strip slots are 22×22. Icon scaled proportionally to 18×18 (same 2px-each-side padding as before). Strip width 238, still centered at x≈121, still at y=242.
Now there's a noticeable gap (~62px) between the grid bottom (y=180) and the strip (y=242) — extra room for the rest of the bottom UI (title, gold/value chips, continue button etc.) when we add them.
Let's start thinking about the layout for now. Let's reorganize the grid such that it takes over the middle of the screen, while space on the left exists for our owned item slots. The item slots should be bigger than they are now, but the emojis inside should be smaller. Hovering over each owned item also shows a tooltip with its description, and it also wobbles + light spring pull on hover. On all hover with UI elements that hover themselves, the cursor should also spring pull lightly.
Big change. Let me check the cursor structure first since we'll need to add spring-pull to it.
Grep (^function cursor:|^cursor = )
947:cursor = class()
949:function cursor:new()
974:function cursor:flash_gather()
980:function cursor:update(dt)
1033:function cursor:draw()
1049:function cursor:destroy() end
Read (E:\a327ex\emoji-aimer\main.lua)
947 cursor = class()
948
949 function cursor:new()
950 self.x, self.y = 0, 0
951 make_entity(self)
952 self.timer = timer_new()
953 self.spring = spring_new()
954 spring_add(self.spring, 'r', 0)
955
956 self.previous_mouse_deltas_x = {}
957 self.previous_mouse_deltas_y = {}
958 self.mouse_dt_sy = 1
959 self.last_sway_x_time = 0
960 self.last_sway_y_time = 0
961
962 self.click_r = 0
963 self.click_sx, self.click_sy = 1, 1
964
965 self.flashing = false
966
967 self.image = backhand_index_pointing_up
968 self.image_scale = CURSOR_SIZE / self.image.width
969 end
970
971 -- flash_gather — react to a resource pickup. Spring pulse on main (which
972 -- affects scale via cursor:draw) plus a brief white tint. Named timer so
973 -- back-to-back grabs replace the in-flight unflash cleanly.
974 function cursor:flash_gather()
975 spring_pull(self.spring, 'main', 0.3)
976 self.flashing = true
... [70 more lines]
Big refactor. Let me plan it:
Layout (480×270):
- Left margin: 8
- Owned column: x=8, 2×6 slots of 28×28 (icon 16) with 2px gap = 58 wide, ends at x=66
- Gap: 12
- Grid: x=78, 7×3 tiles of 48×48 = 360 wide, ends at x=438
- Right margin: 42 (room for future right-side UI)
- Grid now shows 21 of 27 items; the rest can populate owned slots
Behaviors:
- Owned slots get hover/wobble/spring/tooltip — same machinery as grid tiles, but lighter visuals (no banner, just frame + emoji)
- Cursor itself gets a light spring pull (
0.05) on hover-enter for any element that has its own hover effect
Refactors needed:
cursor:flash_hover()method- Hoverable elements carry
w, hfields soshop_tooltip_positionworks for both tile and slot sizes shop_kit_updateiterates tiles AND owned slots; setsSHOP_KIT_HOVERED_TILEto either kind- New
draw_shop_owned_slot(slot) draw_shop_ui_kitorchestrates everything
Starting with the cursor method.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the layout constants and owned-slot data structure.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now update shop_kit_init to build both grid tiles AND owned slots, and add w/h fields to each so the tooltip position helper works for both.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Update shop_kit_update to handle both element types and trigger the cursor flash.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now shop_tooltip_position needs to read width/height from the element struct, and add draw_shop_owned_slot.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now add draw_shop_owned_slot and replace the old draw_shop_owned_strip. Let me find both.
Read (E:\a327ex\emoji-aimer\main.lua)
1759 if it then
1760 local s = icon_s/it.img.width
1761 layer_push(ui_content_layer, sx + slot/2, y + slot/2, 0, s, s)
1762 layer_image(ui_content_layer, it.img, 0, 0)
1763 layer_pop(ui_content_layer)
1764 end
1765 end
1766 end
1767
1768 -- Rounded-rect button. state: 'default', 'hovered', 'disabled'.
1769 -- variant: 'primary' (yellow), 'secondary' (fg).
1770 function draw_shop_button(x, y, w, h, label, state, variant)
1771 variant = variant or 'secondary'
1772 local base = (variant == 'primary') and yellow() or fg()
1773 local col = base
1774 if state == 'hovered' then col = white() end
1775 if state == 'disabled' then col = fg_dark() end
1776 layer_rounded_rectangle(ui_panel_layer, x, y, w, h, 3, col)
1777 local lbl_w = font_get_text_width('main', label)
1778 local text_y = math.floor(y + h/2 - 11/2 + 1)
1779 layer_text(ui_content_layer, label, fonts.main, x + w/2 - lbl_w/2, text_y, white())
1780 end
Read (E:\a327ex\emoji-aimer\main.lua)
1747 end
1748
1749 -- Compact row of slots — filled with emoji where occupied, outlined empty
1750 -- squares elsewhere. items is a sparse table indexed 1..max_slots.
1751 function draw_shop_owned_strip(x, y, items, max_slots)
1752 local slot = 22
1753 local gap = 2
1754 local icon_s = 18
1755 for i = 1, max_slots do
1756 local sx = x + (i - 1)*(slot + gap)
1757 layer_rounded_rectangle(ui_panel_layer, sx, y, slot, slot, 2, fg())
1758 local it = items[i]
1759 if it then
1760 local s = icon_s/it.img.width
1761 layer_push(ui_content_layer, sx + slot/2, y + slot/2, 0, s, s)
1762 layer_image(ui_content_layer, it.img, 0, 0)
1763 layer_pop(ui_content_layer)
1764 end
1765 end
1766 end
1767
1768 -- Rounded-rect button. state: 'default', 'hovered', 'disabled'.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now rewrite draw_shop_ui_kit for the new layout — drop the old centered strip, add owned-slot drawing.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Major refactor complete. Summary:
Layout — grid moved to middle, owned slots column on left:
- Left margin 8 → owned column (2×6 = 12 slots, 28×28 each with 16×16 emojis, radius 4) → 12px gap → 7×3 = 21 tile grid → ~42px right margin reserved for future UI
- Owned column ends at y=206, grid ends at y=180, leaving ~64px bottom area for further UI
Owned slots:
- 7 filled in the demo (SHIELD, CROSSED SWORDS, RED HEART, HIGH VOLTAGE, BOMB, FIRE, POINTER) + 5 empty
- Filled slots have same machinery as grid tiles: shake handcam, hover-enter spring pull, hover_amount lerp, tooltip on hover
- Empty slots are static fg_dark rounded rects, no hover interaction
- No banner/label — just frame + centered emoji, deliberately stripped down vs catalog tiles
Cursor spring pull (cursor:flash_hover) — pulls the cursor's main spring by 0.05 on every hover-enter event from either a tile or a filled slot. Both spawn via the shared update_hover_element helper, so any future hover-able element gets the same behavior for free.
Tooltip — works for both tiles and slots since the position function now reads el.w / el.h from the element struct rather than the SHOP_TILE_W constants. Hovering an owned slot shows its tooltip to its right.
Things to look at when you run it:
- Owned slot frame radius (4) vs tile radius (6) — same family or want exact match?
- Owned emoji at 16×16 in 28×28 slot — the 6px padding all around may feel like wasted space, or read as intentional breathing room
- Cursor spring pulse magnitude (0.05) — subtle on purpose, easy to bump if you want it more noticeable
- Owned items 22/24/26 (HIGH VOLTAGE, FIRE, POINTER) don't appear in the grid — semantically odd ("how did I buy them?") but useful for kit testing variety; we can align the demo data later
Make the grid 5x4, add more spacing between slots and grid elements.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. New layout:
Grid — 5×4 = 20 tiles, gap bumped from 4 → 8.
- Width: 272, Height: 216
- Position: x=96..368, y=28..244
Owned column — 2×6 (unchanged), gap bumped from 2 → 4.
- Width: 60, Height: 188
- Position: x=8..68, y=28..216
Gap between owned and grid: 28 (was 12).
Right margin: 112 (was 42) — generous breathing room for future right-side UI.
State indices updated:
- Owned tiles: SHIELD (1), MAGNET (7), COIN (17) — spread across the grid; replaced STAR (idx 21) since it doesn't fit in 5×4
- Unaffordable: unchanged at FOUR LEAF CLOVER (6), HOT PEPPER (14), DIRECT HIT (20)
Things to note:
- Bottom margin shrunk from ~32 to 26 (because grid is taller now). Tight but enough for the 14px-tall button row.
- 5 grid columns × wider 8px gaps make the tiles feel more like a curated catalog and less like a dense inventory grid — more Pixel-Mart-like.
- Items 21–28 (STAR onward) still don't appear on the grid; some are still used in owned slots demo.
Gap between slots higher. Then let's work on the next UI elements, the tier selector. Tier tabs for tier 1, 2, 3, 4 at the top of the grid, selecting a new tier shows new grid items for that tier. For now you can just make them up. If a tier is locked you can't click to swap to it.
Big-ish change. Let me plan:
Slot gap bump: SHOP_OWNED_GAP 4 → 6.
Tier tabs:
- 4 tabs at top of grid, x=96 (matches grid x), y=4, w=65, h=18, gap 4 → totals 272 wide, matches grid width.
- Inactive tab:
fgfill, white label. Hovered:whitefill. Active:yellowfill. Locked:fg_darkfill with 🔒 emoji instead of label. - Spring pulse on hover-enter + cursor flash (like tiles). No continuous wobble — tabs are navigation, not loot.
- Click on unlocked, non-active tab → switches active tier and rebuilds the grid with that tier's items.
Per-tier items: Tiers 1 & 2 unlocked, 3 & 4 locked. Each tier shows 20 items cycled from SHOP_KIT_ITEMS with a per-tier offset, so swapping tabs visibly changes the grid. SHOP_KIT_OWNED / SHOP_KIT_UNAFFORDABLE stay keyed by global item index (an owned item is owned no matter which tier shows it).
Grid rebuild: build_kit_grid(tier_idx) factored out of shop_kit_init; called on init and on every tier change. Clears SHOP_KIT_HOVERED_TILE so stale references don't render.
Implementing now.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now the tier system. Let me add the tier data + tabs storage near the other layout constants.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now extract the grid-building into a function so it can be called on tier change, build the tabs in init, and wire up the tier offset.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now update shop_kit_update to handle tab hover + click.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now add a draw_shop_tier_tab function and update draw_shop_ui_kit to render tabs.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary:
Slot gap: 4 → 6.
Tier tabs at top of the grid:
- 4 tabs at y=4, w=65, h=18, gap 4 — span exactly the grid width (272px starting at x=96).
- Tier 1 & 2 unlocked; Tier 3 & 4 locked (render with the locked padlock emoji instead of label).
- Inactive:
fgfill / Hovered:whitefill / Active:yellowfill / Locked:fg_dark. - Spring pulse on hover-enter + cursor flash via
the_cursor:flash_hover(). No continuous wobble — tabs are navigation, not loot.
Tier-driven grid:
- Each tier has an
offsetintoSHOP_KIT_ITEMS(Tier 1: 0, Tier 2: 7, Tier 3: 14, Tier 4: 21). build_kit_grid(tier_idx)cycles 20 items from that offset.SHOP_KIT_OWNED/SHOP_KIT_UNAFFORDABLEare keyed by global item index — a SHIELD purchase stays "owned" no matter which tier surfaces it.
Click behavior:
- Click on unlocked, non-active tab → switches
SHOP_KIT_ACTIVE_TIERand rebuilds the grid. - Click on active tab → no-op.
- Click on locked tab → no-op (not even hover state applies).
Things to look at:
- Tab label position — should be vertically centered with the same +1 down nudge as banner text.
- Tab width (65) — labels fit but only just; "TIER 1" through "TIER 4" are all 6 chars so they're consistent.
- Hover wobble on tabs — currently OFF on purpose; tell me if you want them to wobble too for consistency with tiles/slots.
- Click feedback — currently no animation, instant grid swap. If you want a transition (fade, slide, particle burst), say the word.
Let's have it be like the reference image, where the tiers are a single strip (rectangle) and then divided internally instead of individual buttons. Also move the grid down a little to give it more space. Also the text inside each tier has the same problem as the text inside buttons had before, slightly below 1 scale or similar which makes it look wrong.
Three changes:
- Single-strip tier selector with internal segment dividers (segmented-control style).
- Move grid + owned column down to give more breathing room from the strip.
- Fix text subpixel issue — text was inheriting the spring scale from the tab's outer
layer_push. Solution: draw the panel with scale, but draw labels at absolute (integer) positions without going through a scaled transform.
For (1), I'm dropping per-tab springs since the visual is now a unified strip — hover feedback is just the white highlight pill, no scaling on individual segments. Cursor pull on hover-enter stays.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now move the grid + owned origin down.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now drop the per-tab spring from build_tabs, and rewrite the rendering as a single draw_shop_tier_strip.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Simplify shop_kit_update's tab loop (no spring anymore).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now replace draw_shop_tier_tab with draw_shop_tier_strip. Text uses absolute integer positions (no scaled push) so it stays pixel-clean.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Replace the per-tab loop in draw_shop_ui_kit with a single strip call.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary:
Tier strip — now a single 272×18 rounded rectangle with 4 segments (68px each) inside.
- Strip background:
fgrounded rect (radius 4) - Active segment: yellow inset pill (radius 3, inset 2px on all sides)
- Hovered segment (non-active, unlocked): white inset pill
- Locked segments: no pill, just a 12×12 padlock emoji centered
- Dividers: 1px vertical lines in
fg_darkat each segment boundary, inset from strip edges by 4px top/bottom so they don't poke into the rounded corners
Grid + owned column moved down to y=34 (was y=28). Gap between strip bottom (y=22) and grid top (y=34) is now 12px (was 6px). Owned column also moved to y=34 for vertical alignment with the grid.
- Grid bottom: y=250, bottom margin 20.
- Owned bottom: y=232, bottom margin 38.
Text subpixel fix — labels and lock icons are now drawn at absolute integer positions with no enclosing scaled transform. The previous per-tab layer_push(..., sc, sc) was scaling the text along with the spring oscillation; even when sc ≈ 1 there were sub-pixel fluctuations that made the glyphs render inconsistently. Now the panel still gets a static, integer-position background, and the text rides on top in pure screen space.
Cursor still flashes on hover-enter for unlocked segments. Click-to-switch and locked-segment-no-op behavior unchanged.
Things to evaluate when you run it:
- Active vs hovered contrast (yellow vs white) — clearly differentiated, or want active brighter / hovered subtler?
- Divider color (
fg_dark) — visible enough, or want a stronger contrast? - Inset margin (2px each side) — too tight, too loose?
- Tab label centering — should be perfectly pixel-aligned now; let me know if any glyphs still look off.
Separate fully vertically, and the entire section for each tier should be highlighted, not just a rectangle inside of it. Currently it's missing the borders of the section.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Two visual changes:
Active / hovered fills the whole segment now. New helper draw_segment_highlight covers the entire segment area instead of the previous inset pill. For first/last segments it uses the rounded-rect-plus-notch-fill technique to round only the outer corners (matching the strip's rounded edges); middle segments are flat rectangles. So:
- TIER 1 active → yellow fills its segment with rounded left corners (matches strip) and sharp right edge.
- TIER 2 / TIER 3 active → yellow flat rect, sharp on both sides.
- TIER 4 active → yellow with rounded right corners and sharp left edge.
Dividers separate fully vertically — top/bottom inset removed, lines now run from strip top to strip bottom. And dividers adjacent to the active segment are skipped so the yellow fill reads as continuous without an interrupting line slicing through it.
Things to check when you run it:
- Active fill should now meet the strip's rounded outer corners on the first/last tier — no gap at the rim.
- Dividers should look like clean vertical strokes spanning the full strip height, except next to whichever segment is currently active.
- Switching tiers should make the dividers visually "regroup" — divider that was hidden against the old active becomes visible, divider next to the new active disappears.
Make the color of the current tier green. Then tell me, what are the other UI elements you implemented?
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Color flipped to green for the active tier.
Recap of UI elements
Original list of 8 from when we started, plus the tier strip I added during this work:
| # | Element | Status |
|---|---|---|
| 1 | Item icon tile | ✅ Done |
| 2 | Hover tooltip | ✅ Done |
| 3 | Tier header (standalone) | ⏭️ Skipped (functionality absorbed into the tier strip) |
| 4 | Owned-items strip / column | ✅ Done |
| 5 | Top-bar bits — gold counter + item value counter | ❌ Not started |
| 6 | Page title + subtitle | ❌ Not started |
| 7 | Buttons — primary + secondary | ❌ Not started |
| 8 | Locked-tier overlay (full grid-section dim) | ❌ Not started (note: tier strip already shows locked tabs, but the original idea was a full section overlay) |
| + | Tier selector strip | ✅ Done (added in this iteration) |
Remaining to build:
- Top bar: gold chip + item value chip (Pixel-Mart-style coin icon + number, possibly with a label).
- Page title / subtitle: "SHOP" / "ROUND N — KILL X" or similar header text.
- Buttons: at minimum a primary continue/next button + a secondary back button, each with default / hovered / disabled states.
- Locked-tier overlay: full grid-section dim with the padlock — though now that tier locking lives in the strip, this may be redundant. We can decide whether to keep it as a different scope (e.g., "future tier" preview).
Let me know which to tackle next.
Try to fit everything else into the current layout, then also let's add an additional number to each slot. I want items in each slot to have levels, so like in the reference image, they should have a little blue emoji number to their top-left side.
[Request interrupted by user]
Skip 3, 8, so do 5, 6, 7
Got it. Skipping 3 + 8, doing 5, 6, 7 + the level badge on each owned slot. Layout plan for the right column (x=368..480, 112px wide):
- y=4: "SHOP" title (mid font)
- y=22: subtitle "ROUND 1/5"
- y=44: gold chip (coin + number)
- y=72: value chip (gem + number, distinguishes from gold)
- y=224: secondary BACK button (right-area width, 18 tall)
- y=246: primary NEXT ROUND button (also right-area width)
For the level badges: small blue keycap digit (1-9) centered near each owned slot's top-left corner. Reuses recolor_shader with a new shop_level_layer intermediate — same pattern as the unaffordable grayscale pass.
Starting with the layer for the level digits.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now add the levels demo + right-area constants near the existing owned constants.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now augment shop_kit_init to set the level on each filled slot.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now update draw_shop_owned_slot to draw the level digit to shop_level_layer.
Read (E:\a327ex\emoji-aimer\main.lua)
1812 if SHOP_KIT_ACTIVE_TIER ~= i and SHOP_KIT_ACTIVE_TIER ~= i + 1 then
1813 local div_x = strip_x + i*seg_w
1814 layer_rectangle(ui_panel_layer, div_x, strip_y, 1, strip_h, fg_dark())
1815 end
1816 end
1817
1818 -- Labels / lock icons at absolute integer positions.
1819 for _, tab in ipairs(SHOP_KIT_TABS) do
1820 local cx = tab.x + tab.w/2
1821 local cy = tab.y + tab.h/2
1822 if tab.locked then
1823 local icon = 12
1824 local s = icon/locked_img.width
1825 layer_push(ui_content_layer, cx, cy, 0, s, s)
1826 layer_image(ui_content_layer, locked_img, 0, 0)
1827 layer_pop(ui_content_layer)
1828 else
1829 local lbl_w = font_get_text_width('main', tab.label)
1830 local text_x = math.floor(cx - lbl_w/2)
1831 local text_y = math.floor(cy - 11/2 + 1) + 1
1832 layer_text(ui_content_layer, tab.label, fonts.main, text_x, text_y, white())
1833 end
1834 end
1835 end
1836
1837 -- 28x28 owned-item slot. Mirrors draw_shop_item_tile structure (panel push
1838 -- with shake + spring transforms, content push with the emoji inside) but
1839 -- without the banner / label / state-tinted frame. Empty slots (item == nil)
1840 -- render as a desaturated rounded rect with no content.
1841 function draw_shop_owned_slot(s)
... [2 more lines]
Read (E:\a327ex\emoji-aimer\main.lua)
1841 function draw_shop_owned_slot(s)
1842 local w, h = s.w, s.h
1843 local cx, cy = s.x + w/2, s.y + h/2
1844
1845 if s.item == nil then
1846 layer_rounded_rectangle(ui_panel_layer, s.x, s.y, w, h, 4, fg_dark())
1847 return
1848 end
1849
1850 local ox, oy, rot = shake_get_effects(s.shake)
1851 ox, oy, rot = ox*s.hover_amount, oy*s.hover_amount, rot*s.hover_amount
1852 local sc = s.spring.main.x
1853 local frame_col = s.hovered and white() or fg()
1854
1855 layer_push(ui_panel_layer, cx + ox, cy + oy, rot, sc, sc)
1856 layer_rounded_rectangle(ui_panel_layer, -w/2, -h/2, w, h, 4, frame_col)
1857 layer_pop(ui_panel_layer)
1858
1859 layer_push(ui_content_layer, cx + ox, cy + oy, rot, sc, sc)
1860 local icon = SHOP_OWNED_ICON
1861 local is = icon/s.item.img.width
1862 layer_push(ui_content_layer, 0, 0, 0, is, is)
1863 layer_image(ui_content_layer, s.item.img, 0, 0)
1864 layer_pop(ui_content_layer)
1865 layer_pop(ui_content_layer)
1866 end
1867
1868 -- Rounded-rect button. state: 'default', 'hovered', 'disabled'.
1869 -- variant: 'primary' (yellow), 'secondary' (fg).
1870 function draw_shop_button(x, y, w, h, label, state, variant)
... [5 more lines]
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now add the level recolor pass in the draw pipeline, right after the grayscale pass.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now update draw_shop_button (pixel-snap text x, primary green, match strip radius 4) and add the right-column rendering to draw_shop_ui_kit.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now render the right-column elements in draw_shop_ui_kit.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Two things added:
Right column UI (elements 5, 6, 7):
- Title "SHOP" at (376, 4) in
fonts.mid(Awesome 9 @ 16). - Subtitle "ROUND 1/5" at (376, 22) in
fonts.main— pulled dynamically fromround_indexand#ROUNDS. - Gold chip at (376, 44) — coin icon + "1,280".
- Value chip at (376, 72) — gem icon + "5,400" (distinct from gold via the icon).
- Secondary BACK button at (376, 224), 96×18.
- Primary NEXT ROUND button at (376, 246), 96×18 — primary variant now uses green to match the active tier accent. Button radius bumped 3 → 4 to match the strip/tile family. Text pixel-snapped +
+1down nudge for consistency with banner text.
Level badges on owned slots:
- Each filled slot has a
level(1..5 demo data). 10×10 blue keycap digit centered at the slot's top-left corner (centered ats.x + 5, s.y + 5so it overlaps the slot's corner area but stays inside the slot bounds). - New
shop_level_layerintermediate. Digits queued there, then in the draw pipeline (right after the grayscale pass) we setrecolor_shader's target color to the palette blue(83, 175, 239)andlayer_draw_fromontoui_content_layer. The outline pass then gives each badge its own black halo.
Things to look at:
- Right-column elements have lots of vertical breathing room between the chips (y=72..96) and buttons (y=224..264) — that's intentional empty space, easy to fill with future stuff (mini-inventory? tier description? selected-item callout?) or tighten if it feels too sparse.
- Subtitle width — "ROUND 1/5" at x=376 should comfortably fit. If you switch to a longer format like "ROUND 1 / 5 — KILL 5" it might overflow the right edge.
- Level badge position — overlapping the slot's top-left corner area. If it should hang OFF the corner instead (mobile-notification-badge style), shift the push position by -2px on each axis.
- Primary button green vs active tier green — same color now; if you want them distinct, easy to switch primary to yellow or orange.
Perfect. Let's swap things around. Item slots on the right, no back button, just next round. Make the next round button smaller horizontally too. Then move the shop + gold pieces to the left, make them all centered on the left column. Also remove the diamond one, gold is the only resource we have ultimately.
Plan:
Left column (replaces what was the right column):
- All elements horizontally centered around x=52 (center of 8..96).
- Title "SHOP" at y=4.
- Subtitle "ROUND 1/5" at y=22.
- Gold chip (coin only) at y=44.
- NEXT ROUND button (primary, green) at y=246 (bottom of column), narrower at w=70 (was 96).
Right column (slots — moved from x=8 → centered in right area):
SHOP_OWNED_ORIGIN_X = 393→ centered in x=368..480 (50px slack split 25/25 either side of the 62-wide column).
Removed: gem-icon value chip, BACK button, old SHOP_RIGHT_X constant.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now swap the right-column rendering for centered-left-column rendering in draw_shop_ui_kit.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Summary:
Owned slots moved to the right: SHOP_OWNED_ORIGIN_X = 393. Column is centered in the right area (368..480) with 25px slack on each side of the 62-wide column. Tooltip positioning auto-flips to the left side of the slots since their right-anchored default would overflow — no extra code change needed.
Left column now hosts (all horizontally centered around x=52):
- Title "SHOP" at y=4
- Subtitle "ROUND 1/5" at y=22
- Gold chip (coin + "1,280") at y=44
- NEXT ROUND button at y=246, width 70 (was 96)
Removed:
- Gem-icon value chip (only gold matters now)
- BACK button
- Old
SHOP_RIGHT_Xconstant — replaced withSHOP_LEFT_CENTER_X
The button uses primary variant (green fill, white text) — same green as the active tier.
Things to look at when you run it:
- Vertical breathing room between gold chip (y=44..68) and button (y=246..264) is ~180px — empty by design, easy to fill or compress later.
- Title and subtitle centering — pixel-snapped via
math.floor; widths are dynamic so they recenter if the text changes. - Owned-column gap to grid is 25px (393 - 368) which is wider than the original 12px left-column gap. If you want them flush against the grid (right-anchored to the grid edge), set
SHOP_OWNED_ORIGIN_X = 376instead.
Next round button on the right. Shop + round 1/5 should be in a singular frame, the top of that frame should be aligned with the top of the tier frame.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Changes:
Shop frame on left — rounded rect at (8, 4) with width 88, height 34, radius 4, fg background.
- Top edge at y=4, aligned with the tier strip's top edge.
- Frame is taller than the tier strip (34 vs 18) because it contains two stacked text lines (mid-font title + main-font subtitle). Black outline applied automatically via
ui_panel_outline. - Inside:
- "SHOP" centered horizontally at y=7 (mid font)
- "ROUND 1/5" centered horizontally at y=25 (main font)
Gold chip sits at y=44 beneath the frame, still centered in the left column.
NEXT ROUND button moved to right — centered horizontally over the owned-slot column (slot column center is x=424). Width 70, y=246, same as before. Button center now matches the column of owned slots, visually pairing them.
Things to look at:
- Frame height (34) vs tier strip height (18) — frame is taller because it contains two lines. If you'd rather have them the same height with the texts side by side ("SHOP" left, "R1/5" right on one line), that's an easy variant.
- Gap between frame bottom (y=38) and gold chip top (y=44) — 6px. Tight but reads as one cluster. Increase to 8-10 for more breathing room if needed.
- Vertical alignment of NEXT ROUND with owned slots — button bottom (y=264) is well below slot column bottom (y=232), leaving the slots clearly grouped above the action button.
Lower width on shop frame, move tier tab down such that distance between its bottom and the top of the start of the grid is the same as the spacing between grid units. Move shop frame to match new tier frame top.
Plan:
- Grid gap is 8. To make tier→grid distance also 8: tier bottom at y=26 → tier_y = 8 (was 4).
- Shop frame moves to y=8 (matching new tier top).
- Frame width 88 → 70 (matches NEXT ROUND button width, more proportionate to its content).
- Title/subtitle Y inside frame shift accordingly: 11 and 29.
- Gold chip shifts to y=50 (8 below new frame bottom, keeping the 8-gap theme).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. Updated positions:
Tier strip moved down: y=4 → y=8. Strip spans y=8..26. Distance from strip bottom (y=26) to grid top (y=34) is now 8px — matches SHOP_KIT_GAP.
Shop frame now narrower and aligned with tier strip's new top:
- y=8 (was 4), matching tier strip top
- w=70 (was 88), matching NEXT ROUND button width — feels like a balanced cluster (frame + button below mirror each other in width)
- Center stays at x=52
- Frame spans (17, 8) to (87, 42)
- Title at y=11, subtitle at y=29 (shifted down +4 from before, in step with the frame)
Gold chip moved to y=50 — 8px below frame bottom (y=42), consistent with the tier→grid and grid-cell-to-cell gap of 8.
Things to verify when you run it:
- Spacing rhythm: tier_bottom → grid_top, grid_cell → grid_cell, frame_bottom → gold_chip_top should all read as 8px gaps, giving a unified vertical breathing pattern across the UI.
- Frame width 70 fits "ROUND 1/5" comfortably; if you have wider subtitles later (e.g. "ROUND 10/10"), watch for overflow.
Move shop and gold frame to the left, they don't seem to be centered like the slots are.
Looking at it — the slot column is centered in the full right area (x=368..480, center 424), but I had the shop frame centered in x=8..96 (center 52). That gave an asymmetric margin: 17px from screen edge, only 9px from the grid edge.
To match the slots' centering, the shop frame should be centered in the full left area x=0..96 (mirror of x=368..480 on the right), so center = 48 instead of 52.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done. SHOP_LEFT_CENTER_X moved from 52 → 48.
This shifts the shop frame, title, subtitle, and gold chip 4px to the left, putting the frame at x=13..83 (13px from screen edge, 13px from grid edge). Now mirrors the slot column's 25px-each-side centering in the right area.
All four left-column elements still use the same SHOP_LEFT_CENTER_X reference, so they shift together as a unit.
Perfect, move the next round button such that the spacing between its bottom and the screen bottom edge is the same as the spacing between the shop/tier frame and the top edge. Then make the button actually work (spring, highlight + click), except without hooking it to the next round yet.
Plan:
- Move button bottom to y=262 (8px from screen bottom, matching the 8px from screen top to frame top). Button top = 244.
- Add persistent button state (spring + hovered) like tabs/tiles/slots.
- Wire hover detection + click detection in
shop_kit_update. Click is a no-op for now (placeholder). - Update
draw_shop_buttonto accept a scale arg; apply spring scale to the panel push, keep text at absolute integer positions (pixel-sharp).
Edit (E:\a327ex\emoji-aimer\main.lua)
<tool_use_error>Found 2 matches of the string to replace, but replace_all is false. To replace all occurrences, set replace_all to true. To replace only one occurrence, please provide more context to uniquely identify the instance.
String: SHOP_KIT_OWNED_SLOTS = {}</tool_use_error>
Grep (SHOP_KIT_OWNED_SLOTS = {})
1951:SHOP_KIT_OWNED_SLOTS = {}
2085: SHOP_KIT_OWNED_SLOTS = {}
Read (E:\a327ex\emoji-aimer\main.lua)
1948 -- blue keycap badge in each filled slot's top-left.
1949 SHOP_OWNED_LEVELS = { 1, 2, 3, 4, 5, 1, nil, 2, nil, nil, nil, nil }
1950
1951 SHOP_KIT_OWNED_SLOTS = {}
1952
1953 -- Left column layout (x=8..96 = grid origin). Hosts title, subtitle,
1954 -- gold chip, and the primary NEXT ROUND button. Everything centered
1955 -- horizontally around SHOP_LEFT_CENTER_X.
1956 SHOP_LEFT_CENTER_X = 48 -- midpoint of the full left area x=0..96, mirroring the way the owned-slot column is centered in the full right area x=368..480
1957 SHOP_BUTTON_W = 70 -- narrower than the previous 96-wide button
1958 SHOP_BUTTON_H = 18
1959
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now build the button state in shop_kit_init (after owned slots loop).
Read (E:\a327ex\emoji-aimer\main.lua)
2098 local s = {
2099 x = x, y = y, w = SHOP_OWNED_SLOT_W, h = SHOP_OWNED_SLOT_H,
2100 item = item_idx and SHOP_KIT_ITEMS[item_idx] or nil,
2101 level = SHOP_OWNED_LEVELS[idx],
2102 kind = 'slot',
2103 }
2104 if s.item then init_hover_state(s) end
2105 SHOP_KIT_OWNED_SLOTS[#SHOP_KIT_OWNED_SLOTS + 1] = s
2106 end
2107 end
2108 end
2109
2110 -- Tick kit interactions: shake + spring physics, hover hit-test,
2111 -- hover_amount lerp. On hover-enter (hovered now, not last frame) a
2112 -- spring_pull gives a one-shot scale pop. The lerped hover_amount fades
2113 -- the continuous shake wobble in/out smoothly.
2114 -- Tick hover behavior for a single element (tile or slot). Updates shake +
2115 -- spring, hit-tests, fires the hover-enter spring pulse + cursor flash,
2116 -- lerps hover_amount toward the target. Returns true if this element is
2117 -- the one currently under the cursor.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now wire button hover + click into shop_kit_update.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Update draw_shop_button to accept a scale arg, applying it only to the panel (not the text).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now use the persistent button object in draw_shop_ui_kit instead of inline calc.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Done.
Button position: y=244 (was 246). Button bottom now at y=262 — 8px above screen bottom, matching the 8px gap from screen top to the shop/tier frame top.
Button is now interactive:
- Persistent state in
SHOP_KIT_NEXT_BUTTON(built once inshop_kit_initso the spring + hover state survive across frames). shop_kit_updateticks the spring, hit-tests for hover, firesspring_pull(0.08)+the_cursor:flash_hover()on hover-enter, and detects click. Click is currently a no-op (TODO marker pointing atexit_shop()for when the real shop flow is wired up).draw_shop_buttonnow accepts ascalearg. Spring scale applies to alayer_push-wrapped panel draw; the label is rendered at absolute integer positions outside the push so it stays pixel-sharp during the pulse (same trick as the tier strip).
Visual behaviors when you run it:
- Hovering NEXT ROUND should bump it 8% bigger briefly (spring pulse), fill turns
white, cursor cursor itself gets a sympathetic flash. - Continuing hover keeps it
white(no more bumps until you leave and re-enter). - Clicking does nothing visible yet — but the click is detected, ready to wire to
exit_shop()when shop progression is implemented.
Great, I think this is it. Now let's hook everything up with the actual game, and also not use fake data, but hook things up such that as we add items we can easily make everything work. First, the inventory/item slots itself have to work. Once we buy an item, gold should be decreased, the item should appear on the inventory. If we can't buy, X mark appears on mouse and the card flashes red (shader) and shakes horizontally in error. If we can buy then the card becomes empty of contents and the item appears in the item slots. All items appear on the item slot as level 1, buying the same item again increases its level to 2, 3, etc. Such increases also have an effect with blue particles spawning from the top-left number itself. So, for now, keep the grid with fake items, slots empty, and then do the buying logic with effects.
Big chunk. Let me start by checking what particle classes are available so I can reuse them for the level-up effect.
Read (E:\a327ex\emoji-aimer\main.lua)
455
456 function hit_effect:new(x, y, args)
457 args = args or {}
458 self.x, self.y = x, y
459 self.r = random_angle()
460 self.sx = args.s or 1
461 self.sy = args.s or 1
462 make_entity(self)
463 self.animation = animation_new('hit1', 0.03, 'once')
464 end
465
466 function hit_effect:update(dt)
467 animation_update(self.animation, dt)
468 if self.animation.dead then self:kill() end
469 end
470
471 function hit_effect:draw()
472 -- 1.35 base scale matches the super-emoji-pop reference; per-instance
473 -- args.s stacks on top of it.
474 local s = 1.35
475 layer_push(effects_layer, self.x, self.y, self.r, self.sx*s, self.sy*s)
476 layer_animation(effects_layer, self.animation, 0, 0)
477 layer_pop(effects_layer)
478 end
479
480 function hit_effect:destroy() end
481
482 -- =============================================================================
483 -- hit_particle — small directional capsule that flies along `direction`,
484 -- accumulates gravity over time, scales down to nothing, then dies.
... [20 more lines]
Grep (function spawn_hit_particle)
1415:function spawn_hit_particle(x, y, args)
Read (E:\a327ex\emoji-aimer\main.lua)
1415 function spawn_hit_particle(x, y, args)
1416 local hp = hit_particle(x, y, args)
1417 effects[#effects + 1] = hp
1418 return hp
1419 end
1420
1421 function spawn_emoji_particle(x, y, image, args)
1422 local ep = emoji_particle(x, y, image, args)
Let me look at the bootstrap to find where to set test gold, and check key spots.
Grep (^gold\s=|^items_owned\s=)
46:gold = color(248, 168, 48)
404:gold = 0
405:items_owned = 0
Big task. Let me audit a few key existing spots first so I can refactor cleanly.
Read (E:\a327ex\emoji-aimer\main.lua)
2147 if hover and not el.hovered then
2148 spring_pull(el.spring, 'main', 0.08)
2149 the_cursor:flash_hover()
2150 end
2151 local target = hover and 1 or 0
2152 el.hover_amount = el.hover_amount + (target - el.hover_amount)*dt*10
2153 el.hovered = hover
2154 return hover
2155 end
2156
2157 function shop_kit_update(dt)
2158 local mx, my = mouse_position()
2159 local clicked = input_pressed('click')
2160 SHOP_KIT_HOVERED_TILE = nil
2161
2162 -- Tier strip segments. Color-only hover (no per-segment scale). Cursor
2163 -- flash on hover-enter so the hover still feels alive. Click on an
2164 -- unlocked, non-active segment swaps the active tier and rebuilds the
2165 -- grid.
2166 for _, tab in ipairs(SHOP_KIT_TABS) do
2167 if not tab.locked then
2168 local hover = mx >= tab.x and mx <= tab.x + tab.w
2169 and my >= tab.y and my <= tab.y + tab.h
2170 if hover and not tab.hovered then
2171 the_cursor:flash_hover()
2172 end
2173 if hover and clicked and tab.index ~= SHOP_KIT_ACTIVE_TIER then
2174 SHOP_KIT_ACTIVE_TIER = tab.index
2175 build_kit_grid(SHOP_KIT_ACTIVE_TIER)
2176 end
Read (E:\a327ex\emoji-aimer\main.lua)
2138 -- Tick hover behavior for a single element (tile or slot). Updates shake +
2139 -- spring, hit-tests, fires the hover-enter spring pulse + cursor flash,
2140 -- lerps hover_amount toward the target. Returns true if this element is
2141 -- the one currently under the cursor.
2142 local function update_hover_element(el, mx, my, dt)
2143 shake_update(el.shake, dt)
2144 spring_update(el.spring, dt)
2145 local hover = mx >= el.x and mx <= el.x + el.w
2146 and my >= el.y and my <= el.y + el.h
2147 if hover and not el.hovered then
Read (E:\a327ex\emoji-aimer\main.lua)
1565 local w, h = SHOP_TILE_W, SHOP_TILE_H
1566 local cx, cy = t.x + w/2, t.y + h/2
1567
1568 -- Hover wobble offsets — multiplied by hover_amount for smooth fade.
1569 local ox, oy, rot = shake_get_effects(t.shake)
1570 ox, oy, rot = ox*t.hover_amount, oy*t.hover_amount, rot*t.hover_amount
1571 local sc = t.spring.main.x -- 1.0 at rest, pulses on hover-enter
1572
1573 -- Split transforms between "card" (outer push) and "emoji" (inner push
1574 -- on the icon only) based on wobble mode. The OTHER side gets identity.
1575 local card_ox, card_oy, card_rot, card_sc = 0, 0, 0, 1
1576 local emoji_ox, emoji_oy, emoji_rot, emoji_sc = 0, 0, 0, 1
1577 if SHOP_KIT_WOBBLE_MODE == 'card' then
1578 card_ox, card_oy, card_rot, card_sc = ox, oy, rot, sc
1579 else
1580 emoji_ox, emoji_oy, emoji_rot, emoji_sc = ox, oy, rot, sc
1581 end
1582
1583 -- State palette: banner color + label.
1584 local banner_col, banner_text
1585 if t.base_state == 'owned' then banner_col, banner_text = green(), 'OWNED'
1586 elseif t.base_state == 'unaffordable' then banner_col, banner_text = gray(), t.item.name
1587 else banner_col, banner_text = yellow(), t.item.name end
1588
1589 -- Frame color: hover → white, unaffordable → fg_dark, else fg.
1590 local frame_col
1591 if t.hovered then frame_col = white()
1592 elseif t.base_state == 'unaffordable' then frame_col = fg_dark()
1593 else frame_col = fg() end
1594
... [22 more lines]
Plan is clear. Let me make all the edits.
Edit 1: Empty the demo data so owned slots start with no items.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 2: Update the slot init loop to start empty (don't read from removed arrays).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 3: Tiles get sold + error feedback fields. Set them in build_kit_grid.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 4: Add cursor:flash_error next to cursor:flash_hover.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 5: Update update_hover_element to skip sold tiles and decrement error timers.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 6: Update draw_shop_item_tile to render sold-as-empty + error flash (red frame) + error horizontal shake.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 7: Add buy logic functions. Insert before shop_kit_update.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 8: Hook click into the tile hover loop.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit 9: Bind the gold chip to the real gold global with a comma formatter, and set a test gold value in bootstrap.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Add the format_with_commas helper near the kit code (above shop_kit_init).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Set a test gold balance in bootstrap so the kit has something to spend.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Let me check the current emoji rendering to spot all base_state references.
Grep (base_state)
1572:-- with item, base_state, hovered, shake, spring, hover_amount fields.
1573:-- base_state ∈ {'available', 'owned', 'unaffordable'}
1615: if t.base_state == 'owned' then banner_col, banner_text = green(), 'OWNED'
1616: elseif t.base_state == 'unaffordable' then banner_col, banner_text = gray(), t.item.name
1624: elseif t.base_state == 'unaffordable' then frame_col = fg_dark()
1631: if t.base_state == 'unaffordable' then
1652: local emoji_layer = (t.base_state == 'unaffordable') and grayscale_layer or ui_content_layer
1667: if t.base_state == 'unaffordable' then
2088: base_state = state,
Read (E:\a327ex\emoji-aimer\main.lua)
2075 for r = 0, SHOP_KIT_ROWS - 1 do
2076 for c = 0, SHOP_KIT_COLS - 1 do
2077 local local_idx = r*SHOP_KIT_COLS + c + 1
2078 local x, y = SHOP_KIT_ORIGIN_X + c*pitch, SHOP_KIT_ORIGIN_Y + r*pitch
2079 local item_idx = ((local_idx - 1 + tier.offset) % #SHOP_KIT_ITEMS) + 1
2080
2081 local state = 'available'
2082 if SHOP_KIT_OWNED[item_idx] then state = 'owned' end
2083 if SHOP_KIT_UNAFFORDABLE[item_idx] then state = 'unaffordable' end
2084
2085 local t = {
2086 x = x, y = y, w = SHOP_TILE_W, h = SHOP_TILE_H,
2087 item = SHOP_KIT_ITEMS[item_idx],
2088 base_state = state,
2089 kind = 'tile',
2090 sold = false,
2091 error_flash = 0,
2092 error_shake_time = 0,
2093 error_shake_duration = 0,
2094 }
2095 init_hover_state(t)
2096 SHOP_KIT_TILES[#SHOP_KIT_TILES + 1] = t
2097 end
2098 end
2099 end
Need to refactor — base_state was a demo construct. With real buy logic, the tile's "unaffordable" state should be dynamic (gold < price each frame), and "owned" doesn't apply anymore (catalog tiles consume into inventory, they aren't pre-owned).
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Now refactor draw_shop_item_tile to derive affordable dynamically instead of reading base_state.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Read (E:\a327ex\emoji-aimer\main.lua)
1646 layer_rounded_rectangle(ui_panel_layer, -w/2, -h/2, w, h, radius, frame_col)
1647 layer_rounded_rectangle(ui_panel_layer, -w/2, banner_y, w, banner_h, radius, banner_col)
1648 layer_rectangle(ui_panel_layer, -w/2, banner_y, radius, radius, banner_col)
1649 layer_rectangle(ui_panel_layer, w/2 - radius, banner_y, radius, radius, banner_col)
1650
1651 -- Emoji — routes to grayscale_layer for unaffordable, else ui_content.
1652 local icon_size = 22
1653 local s = icon_size/t.item.img.width
1654 local emoji_center_y = -h/2 + 6 + icon_size/2
1655 local emoji_layer = (t.base_state == 'unaffordable') and grayscale_layer or ui_content_layer
1656 layer_push(emoji_layer, emoji_ox, emoji_center_y + emoji_oy, emoji_rot, s*emoji_sc, s*emoji_sc)
1657 layer_image(emoji_layer, t.item.img, 0, 0)
1658 layer_pop(emoji_layer)
1659
1660 -- Banner label — pixel-snapped x so odd glyph widths don't render at a
1661 -- half-pixel and produce inconsistent glyph spacing (was visibly broken
1662 -- on SWORD/OWNED before this). Vertically centered in the 14-tall band.
1663 local lbl_w = font_get_text_width('main', banner_text)
1664 local text_x = math.floor(-lbl_w/2)
1665 local text_y = math.floor(banner_y + banner_h/2 - 11/2 + 2)
1666 layer_text(ui_content_layer, banner_text, fonts.main, text_x, text_y, white())
1667
1668 layer_pop(ui_panel_layer)
1669 layer_pop(ui_content_layer)
1670 if t.base_state == 'unaffordable' then
1671 layer_pop(grayscale_layer)
1672 end
1673 end
1674
1675 -- Tooltip geometry constants shared between size + draw.
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Edit (E:\a327ex\emoji-aimer\main.lua)
The file E:\a327ex\emoji-aimer\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)
Grep (base_state|SHOP_KIT_OWNED|SHOP_KIT_UNAFFORDABLE|SHOP_OWNED_DEMO|SHOP_OWNED_LEVELS)
1985:SHOP_KIT_OWNED_SLOTS = {}
2132: SHOP_KIT_OWNED_SLOTS = {}
2145: SHOP_KIT_OWNED_SLOTS[#SHOP_KIT_OWNED_SLOTS + 1] = s
2206: for _, s in ipairs(SHOP_KIT_OWNED_SLOTS) do
2212: for _, s in ipairs(SHOP_KIT_OWNED_SLOTS) do
2305: for _, s in ipairs(SHOP_KIT_OWNED_SLOTS) do
2343: for _, s in ipairs(SHOP_KIT_OWNED_SLOTS) do
Done. Quick verification that no stale references remain.
Grep (base_state|SHOP_KIT_OWNED\s*=|SHOP_KIT_UNAFFORDABLE|SHOP_OWNED_DEMO|SHOP_OWNED_LEVELS)
No matches found
All clean. Summary of what got wired up:
Real data, no demos
- Removed
SHOP_KIT_OWNED,SHOP_KIT_UNAFFORDABLE,SHOP_OWNED_DEMO,SHOP_OWNED_LEVELS, and thebase_statefield on tiles. Tile state is now derived per frame:affordable = gold >= t.item.price→ banner color, frame color, grayscale routing.sold→ empty placeholder rendering, skip in hover/click.
- Owned slots start empty. They become interactive only after
shop_kit_try_buycallsinit_hover_state(slot). - Gold chip reads the actual
goldglobal through a newformat_with_commas(n)helper. Width recomputes each frame so it stays centered as gold changes. - Bootstrap sets
gold = 5000for kit testing.
Buy flow (shop_kit_try_buy)
- Skip if tile is already sold or has no item.
- Look for an existing owned slot with the same item → if found, it's a level-up.
- Otherwise grab the first empty slot.
- If no slot available (inventory full) OR
gold < tile.item.price→ callshop_kit_error(tile)and return. - Otherwise: deduct gold, increment level (or place at level 1 +
init_hover_statefor fresh slot), spawn blue particles on level-up, marktile.sold = true.
Error feedback (shop_kit_error)
tile.error_flash = 0.3— frame turns red for 0.3s.tile.error_shake_*— horizontal decaying sinusoid added to the tile's wobble (math.sin(p*pi*8)*decay*5px, 4 oscillations).the_cursor:flash_error()— swaps cursor image tox_mark_imgfor 0.4s and fires a big spring pulse. Restores original image when the timer expires.
Level-up particle effect (shop_kit_level_up_effect)
- Spawns 8
hit_particlesat the slot's badge position (s.x + 5, s.y + 5). - Color
blue, random velocities 40–100, random durations 0.3–0.5s. - Reuses existing
spawn_hit_particleso the particles inherit the game's standard fade physics and live oneffects_layer.
Things to test when you run it:
- Click an affordable tile → tile becomes empty, gold decreases, item appears in first empty slot at level 1.
- Click that tile's twin (same item in another grid position, after buying again) → existing slot levels up, blue particles emit from the badge.
- Click an unaffordable tile → red flash, horizontal shake, cursor X-mark, gold unchanged.
- Click while inventory is full (12 owned, all unique items, trying to buy a 13th unique) → same error feedback.
- Switch tiers after buying → grid resets with fresh non-sold tiles (since we rebuild on tier change).
Let's end this session here, very good job, we'll continue with improvements in the next session. Name it Emoji Aimer 4
Skill
Launching skill: end-session
Base directory for this skill: E:\a327ex.claude\skills\end-session
End Session Workflow
This skill is invoked from the same conversation where the work was done. You already have the full session context in memory — you do NOT need to read the transcript.
Step 1: Get Session Info
Ask the user for the session title (max 30 characters). Examples: "Anchor Phase 10 Part 5", "Physics Arena Setup", "Timer System Fix", "Thalien Lune Design".
Determine the project yourself from your session context — you know which repo(s) were worked on, which files were created/modified, and where they live. No need to ask. See Step 5 for the list of known project roots; if the session touched something outside the list, infer the root from the paths you actually edited.
Step 2: Write Summary
Write the summary from your conversation memory. You have the full session context — no need to read any files.
The summary should be thorough and detailed. Each major topic deserves its own section with multiple specific bullet points. Don't compress — expand.
Purpose: These summaries serve as searchable records. Future Claude instances will grep through past logs to find how specific topics were handled. The more detail you include, the more useful the summary becomes for finding relevant context later.
Format (this is just an example structure — adapt sections to match what actually happened):
# [Title] ## Summary [1-2 sentence overview of the session's main focus] **[Topic 1 - e.g., "Spring Module Implementation"]:** - First specific detail about what was done - Second detail - include file names, function names - User correction or feedback (quote if notable) - Technical decisions and why **[Topic 2 - e.g., "Camera Research"]:** - What was researched - Key findings - How it influenced implementation **[Topic 3 - e.g., "Errors and Fixes"]:** - Specific error message encountered - Root cause identified - How it was fixed [Continue for each major topic...] --- [Rest of transcript follows]Rules: - Be thorough — If in doubt, include more detail, not less. Each topic should be as detailed as possible while still being a summary. - Think searchability — Future instances will search these logs. Include keywords, function names, error messages that someone might grep for. - One section per major topic — Don't combine unrelated work into one section - Chronological order — Sections should match conversation flow - Specific details — Error messages, file names, function names, parameter values - Include user quotes — When user gave notable feedback, quote it (e.g., "k/d variables are not intuitive at all") - Weight planning equally — Research, proposals, alternatives considered, user feedback on approach are as important as implementation - Weight problems solved — Errors, root causes, fixes, user corrections all matter - Technical specifics — Include formulas, API signatures, parameter changes when relevant
Step 3: Get User Approval
Show the title and summary to the user. Wait for approval before proceeding. If they have corrections, fix them.
Step 4: Convert Transcript and Write the Log File
# Find recent sessions (Claude + Cursor + Codex). Same script lives in Anchor2: python E:/a327ex/Anchor2/scripts/find-recent-session.py --limit 5 # or: python E:/a327ex/Anchor/scripts/find-recent-session.py --limit 5The script shows sessions sorted by when they ended. The first result is the current conversation (since end-session was invoked here). Use it.
Use a lowercase hyphenated slug derived from the title (e.g., "anchor-primitives-hitstop-animation").
Get the end timestamp for the Date frontmatter — this is the wall-clock time when end-session was invoked, NOT the time the JSONL started. Sessions often span multiple days, and the log should be filed under the day the work was wrapped up:
date "+%Y-%m-%d %H:%M:%S"Use this output verbatim. Do not substitute the JSONL start timestamp; the log appears in the sidebar sorted by Date, and a multi-day session with a Date pinned to day 1 will sort below sessions that ended later but started later, hiding the most recent work.
Convert the transcript to markdown:
python E:/a327ex/Anchor2/scripts/jsonl-to-markdown.py [SESSION_PATH] /tmp/session-log.md # or: python E:/a327ex/Anchor/scripts/jsonl-to-markdown.py ...The same script auto-detects Claude Code JSONL vs Cursor/Composer agent JSONL (
~/.cursor/projects/.../agent-transcripts/...) vs Codex rollouts (~/.codex/sessions/...). For Composer sessions, usefind-recent-session.py(it merges all sources) and pick the[cursor]line for the current chat.Replace the default header (
# Session YYYY-MM-DD...) at the top of/tmp/session-log.mdwith the approved title and summary, AND prepend frontmatter. The final file shape:Title: [Title] Date: YYYY-MM-DD HH:MM:SS # [Title] ## Summary [approved summary text from step 2] --- [transcript content from jsonl-to-markdown script]Frontmatter is non-negotiable. Every log file MUST start with
Title:andDate:lines. Without them, the site's sidebar shows the slug as the title and 0 (epoch) as the sort date. The backfill script ina327ex-site/deploy/backfill_metadata.pyis a safety net, not a substitute — write it correctly the first time.Then copy the final file to the log destination:
cp /tmp/session-log.md E:/a327ex/a327ex-site/logs/[slug].mdStep 5: Commit Project Repo
Identify the project repo(s) worked on this session from your own context — you already know which repos were touched and which files changed. For the common projects:
Project Root Stage command Anchor E:/a327ex/Anchorgit add docs/ framework/ engine/ scripts/ reference/Anchor2 E:/a327ex/Anchor2git add framework/ engine/ arena/ reference/ scripts/ docs/ .claude/emoji-ball-battles E:/a327ex/emoji-ball-battlesgit add -Ainvoker E:/a327ex/Invokergit add -Athalien-lune E:/a327ex/thalien-lunegit add -Aa327ex-site E:/a327ex/a327ex-sitegit add -A(this IS one of the web repos — the log file added in Step 4 is staged here automatically)For a project not listed, infer the root from the files you actually created or modified this session and stage those. If multiple candidate roots look valid, ask the user which files to stage.
cdinto the project root, stage, rungit statusto verify before committing.IMPORTANT — FULL SUMMARY IN COMMIT: The commit message MUST include the FULL summary from the log file. Read the summary back from the log file to ensure nothing is missing.
IMPORTANT — COMMIT METHOD: The summary contains backticks, special characters, and markdown that WILL break heredocs and
git commit -m. ALWAYS use the file-based method below. NEVER try a heredoc first — it will fail and produce a malformed commit that needs amending.# Skip until we hit the line "## Summary", then take everything after the next # blank line until the --- separator that precedes the transcript. awk '/^## Summary$/{found=1; next} found && NR>1 && /^---$/{exit} found' \ E:/a327ex/a327ex-site/logs/[slug].md > /tmp/commit_msg.txt # Prepend the title (plain text, no #) and append attribution sed -i "1i [Title]\n" /tmp/commit_msg.txt printf "\nGenerated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n" >> /tmp/commit_msg.txt git commit -F /tmp/commit_msg.txtStep 6: Push the Repos
Two pushes — project (to GitHub) and a327ex-site (to the VPS):
# Project repo to GitHub. Skip this push if the project IS a327ex-site # (handled by the second push below — don't duplicate). git push origin main # a327ex-site to the VPS (post-receive hook restarts the Lua server). cd E:/a327ex/a327ex-site git add -A git commit -m "[Title]" git push prod main 2>&1 | tail -3Failure handling: if either push fails, the other still happens. Local commits stay intact, so the user can re-push manually once they've fixed whatever blocked it. Don't roll back; the committed state on disk is the source of truth.
Step 7: Confirm
Tell the user: - Project commit hash + GitHub push result - a327ex-site commit hash + VPS push result
Format:
Logged — "[Title]". project (Anchor2): abc1234 pushed to GitHub a327ex-site: ghi9012 pushed to a327ex.com (post-receive deployed)If a push failed, surface that explicitly with the error.
Notes
- Frontmatter is non-negotiable. Every log file MUST have
Title:andDate:at the top. Enforced at write time in step 4. The backfill script is a safety net, not a substitute.- If the project IS
a327ex-site(e.g., you spent the session writing the renderer or fixing the theme), there's no separate "project repo to GitHub" push — the a327ex-site push at the end IS the project push. Don't duplicate.- Legacy note: this skill used to also dual-write to
anchor.blot.im/logs/andanchor.blot.im/context/. Post-cutover (May 2026),anchor.blot.imis a JS redirect toa327ex.comand no longer receives content. Drop those steps if you find any older docs that still reference them.ARGUMENTS: Emoji Aimer 4
I have the title: Emoji Aimer 4. Let me draft the summary from session memory.
Emoji Aimer 4
Summary
Built out the entire shop UI for Emoji Aimer iteratively, element by element, culminating in wired-up buy logic with full game-state integration. Worked entirely in emoji-aimer/main.lua (Anchor 2 framework). The session followed a "tune each element in isolation/context, then move to the next" pattern.
Initial scoping & shop mockup critique:
- User shared a Pixel Mart UI mockup (Deadlock-inspired). Provided detailed critique on density vs action-pause context, three-panel chrome consumption, ambiguous "Your Items" vs "Backpack" distinction, redundant compare/detail panels, etc.
- Established design constraints: click-to-continue (no time pressure), no rerolls, no compare panel, no rarity, no selling, all items available from start (price-gated), no actives (all passive items), no inventory hierarchy.
Shop state machine refactor:
- Refactored game state to cleanly separate round vs shop. Extracted
clear_entities()helper. Addedstart_shop()mirroringstart_round(idx).advance_round()now delegates tostart_shop(). - Bootstrap replaced inline
try_spawn_targetloop withround_index = 0; start_shop(). Convention:round_index = 0means "before round 1" (shop UI readsround_index + 1as upcoming round). - Removed the fullscreen dim overlay from the shop draw block (was
color(0,0,0,180)). - Gated wall rendering on
game_state ~= 'shop'so walls don't appear during shop.
Emoji asset download (28 emojis @ 512×512 Twemoji):
- Emojipedia CDN (
em-content.zobj.net) returned 403 to all probes. Discovered wsrv.nl image proxy works as an SVG→PNG rasterizer:https://wsrv.nl/?url=https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/<hex>.svg&w=512&h=512&output=png. - Downloaded 16 new shop emojis: shield, crossed_swords, bow_and_arrow, magic_wand, red_heart, four_leaf_clover, magnet, skull, bomb, feather, eye, test_tube, coffee, hot_pepper, bone, locked.
- Re-downloaded coin/gem/crown at 512×512 (were 256). Later also loaded sparkles, collision as items.
UI kit element implementation:
- Item tile (48×48 initially, then 48×56, then 48×48 with banner): rounded card frame, emoji, banner (yellow/green/gray for available/owned/unaffordable). Banner uses notch-fill trick because
layer_rounded_rectangledoesn't support per-corner radius. - Tooltip: yellow header band with name + right-aligned price chip, body with stat lines + description. Same notch-fill on header's bottom corners. Uses dedicated
ui_top_panel_layer/ui_top_content_layerso outline shader treats tooltip as separate silhouette from tile beneath. - Tier selector: evolved from 4 individual button-style tabs → single strip with internal segment dividers (segmented-control style). Active segment uses notch-fill to round outer corners on first/last segments. Dividers adjacent to active segment hidden so the active fill reads as continuous.
- Owned-items column: 2×6 = 12 slots of 28×28 with 16×16 emoji inside. Each filled slot has level badge (blue keycap digit) at top-left corner.
- Button: rounded rect with primary (green) / secondary (fg) variants and default/hovered/disabled states.
Hover interaction system:
- Each hover-able element (tile, slot, button, tab) has
shake(handcam for continuous wobble),spring(hover-enter scale pulse),hover_amount(smooth 0..1 lerp). - Shared
init_hover_state(el)helper sets up all three. Sharedupdate_hover_element(el, mx, my, dt)ticks them and returns hovered state. - Cursor gets sympathetic
flash_hover()(spring pulse 0.05) on any hover-enter event. Later addedflash_error()(swap to x_mark_img + spring pulse 0.3 + 0.4s timer revert). - Wobble mode
SHOP_KIT_WOBBLE_MODE = 'card' | 'emoji'controls whether the whole tile wobbles or just the icon. Settled on 'card'.
Pixel-art rendering fixes:
- Subpixel text rendering bug: "SWORD" and "OWNED" displayed with broken glyph spacing. Root cause:
font_get_text_widthreturns integer widths, but odd widths divided by 2 (-lbl_w/2) produce fractional positions. Each glyph snapped to a different integer column with nearest-neighbor sampling. Fix:math.floor(-lbl_w/2). - Banner text +1 vertical nudge: combined with LanaPixel's "high in its box" +1 to produce text_y =
math.floor(banner_y + banner_h/2 - 11/2 + 1) + 1(effectively +2 from raw center). - Spring scale on text caused choppy rendering during pulse. Solution: scale only the panel push, draw text at absolute integer positions outside the push. Applied to tabs, buttons, level badges.
Custom shaders:
assets/grayscale.frag: luminance-based desaturation (0.299*r + 0.587*g + 0.114*b), preserves alpha. Createdgrayscale_layerintermediate. Unaffordable tile emojis routed there, thenlayer_draw_from(ui_content_layer, grayscale_layer, grayscale_shader)in the draw pipeline before outline derivation. Heart emoji turns true gray (not just dimmed red).- Level-badge recolor pass: reuses existing
recolor_shaderwith blue target color (palette(83,175,239)). Keycap digit emojis drawn toshop_level_layer, pulled through with blue uniform ontoui_content_layer.
Layout evolution:
- Started with stacked elements in scattered positions.
- Grid evolved: 4 forced-state tiles → 9×4 = 36 grid → 9×3 = 27 → 7×3 = 21 → 5×4 = 20 with larger gaps (4 → 8). Settled on 5×4 with 8px gap.
- Owned column moved from left to right side (centered in x=368..480 area at x=393, mirroring slot placement).
- Shop/gold elements moved from right to left side. Center at x=48 (full left-area midpoint, not the original x=52 which was asymmetric with the slots' centering).
- Tier strip moved from y=4 to y=8 so strip→grid gap matches grid cell gap of 8.
- Shop frame: rounded rect at (13, 8) with width 70, height 34, containing "SHOP" title (mid font) and dynamic "ROUND 1/5" subtitle (reads
round_index + 1and#ROUNDS). - NEXT ROUND button moved to right at y=244 (8px from screen bottom matches 8px from screen top to frame top). Width 70.
Top UI layer separation:
- Created
ui_top_panel_layer/ui_top_content_layer(and outline derivatives) for elements that render above regular UI. Currently used by tooltip. Composite order:ui_panel → ui_content → ui_top_panel → ui_top_content → overlay → cursor → transition. Camera attach mirrors regular UI layers (gated ongame_state ~= 'shop').
Final buy logic implementation:
- Removed all hardcoded demo data:
SHOP_KIT_OWNED,SHOP_KIT_UNAFFORDABLE,SHOP_OWNED_DEMO,SHOP_OWNED_LEVELS, and thebase_statefield on tiles. - Tile state now derived per frame:
affordable = gold >= t.item.pricedrives banner color, frame color, grayscale routing. - New helper functions:
shop_kit_find_owned_slot_with(item),shop_kit_find_empty_owned_slot(),shop_kit_error(tile),shop_kit_level_up_effect(slot),shop_kit_try_buy(tile). - Buy flow: skip if sold; find existing slot (level-up) or empty slot (new); error if no slot or insufficient gold; deduct gold, set/increment level, init_hover_state on freshly-filled slot, mark tile sold.
- Error feedback: red frame flash (0.3s), horizontal decaying sine shake (
sin(p*pi*8)*decay*5px, 4 oscillations), cursor X-mark swap. - Level-up effect: 8 blue
hit_particlesspawn at the slot's badge position with random velocity 40-100 and duration 0.3-0.5s. Reuses existingspawn_hit_particleinfrastructure. - Gold chip binds to real
goldglobal via newformat_with_commas(n)helper. Bootstrap setsgold = 5000for kit testing. - Sold tiles render as
fg_darkrounded rect (matchesSHOP_KIT_EMPTY_CELLSstyle). Switching tiers rebuilds grid, resetting sold state.
User feedback / notable corrections:
- "FatFont at size 8 is actually very big" → switched OWNED label from
fonts.big(FatPixelFont @ 8) tofonts.main(LanaPixel @ 11). - "Use a shader to turn the heart into actual grayscale" → created the grayscale.frag shader instead of relying on multiplicative tint.
- "Lower width on shop frame, move tier tab down such that distance between its bottom and the top of the start of the grid is the same as the spacing between grid units" → tier strip moved to y=8, grid spacing math unified at 8px.
- "Move shop and gold frame to the left, they don't seem to be centered like the slots are" → discovered the slots were centered in x=368..480 (full right area) while the left elements were centered in x=8..96 (with margin). Fixed by moving left center from 52→48 to mirror the slot centering.
- "The text inside each tier has the same problem as the text inside buttons had before" → fixed by drawing labels at absolute integer positions outside the spring-scaled push.
Does this look good to commit? Any edits to the summary or title before I write the log and push?
Yes.
Bash (python E:/a327ex/Anchor2/scripts/find-recent-session.py --limit 5)
2026-05-12T02:07:26.520Z b12de6d0-3e71-4bb4-a209-5b12b0e62ab4 [claude] <-- MOST RECENT
C:\Users\adn\.claude\projects\E--a327ex\b12de6d0-3e71-4bb4-a209-5b12b0e62ab4.jsonl
2026-05-11T15:42:20.841Z 1911f14a-9f08-4c0f-8e89-4aa44a78e8c9 [claude]
C:\Users\adn\.claude\projects\E--a327ex\1911f14a-9f08-4c0f-8e89-4aa44a78e8c9.jsonl
2026-05-11T13:20:18.035Z ee9348c4-4995-4e08-830c-9da35d4a0c8a [claude]
C:\Users\adn\.claude\projects\E--a327ex\ee9348c4-4995-4e08-830c-9da35d4a0c8a.jsonl
2026-05-11T12:35:54.271Z 283bf1b9-b46c-40fd-ae29-0f9c1afbc38e [claude]
C:\Users\adn\.claude\projects\E--a327ex\283bf1b9-b46c-40fd-ae29-0f9c1afbc38e.jsonl
2026-05-11T12:18:37.416Z 075f3871-f99f-40c7-80fd-4c700a62a237 [claude]
C:\Users\adn\.claude\projects\E--a327ex\075f3871-f99f-40c7-80fd-4c700a62a237.jsonl
Bash (date "+%Y-%m-%d %H:%M:%S")
2026-05-11 23:07:57