send_o notes

Target version: 6.12.9 Hexagon (請注意:中文(臺灣)內容設於下方)

Game Introduction

send_o is a sandbox puzzle game composed of texts. Players place various elements (conveyor, spring, piston, etc.) to guide particles from spawner(s) to collector(s), reaching a target count to clear each level.
The game also features a sandbox level, allowing players to freely design, export, and import custom levels.

It's recommended to use desktop version of Chrome (Blink) or Firefox (Gecko) browsers to play this game. Both have been tested and should not have big problems.

There is also a lite version for same puzzles and mechanics, with reduced visual effects.

Basic Controls

Mouse

• Left click: place element / select element
• Left click + drag: continuous placement / move element (requires "SELECT" tool)
• Right click + drag / middle click + drag: pan the view
• Right click: open quick action menu (copy, paste, rotate, delete, etc.)
• Drag the "send_o" title: move the sidebar
• Double click the "send_o" title: reset the sidebar position
• Left click HUD: toggle HUD hide

Keyboard Shortcuts

• Space: start / pause
• 1: switch to "SELECT" tool
• 2: switch to "CONVEYOR" tool
• 3: switch to "SPRING" tool
• 4: switch to "PORTAL" tool
• 5: switch to "WALL" tool
• 6: switch to "FILTER" tool
• 7: switch to "PISTON" tool
• 8: switch to "SPAWNER" tool
• 9: switch to "COLLECTOR" tool
• R: rotate
• D / Delete: delete
• CTRL (or ⌘) + Z: undo
• CTRL + Y / ⌘ + shift + Z: redo
• CTRL (or ⌘) + C / CTRL (or ⌘) + X / CTRL (or ⌘) + V: copy / cut / paste
• F2: save level preview (PNG)
• Shift + F2: save live level preview (PNG)
• Escape: deselect / cancel paste mode

Touch

• Single finger: same as left mouse (place, select, drag)
• Long press: open the quick action menu
• Two fingers: pinch to zoom, drag to pan, twist to rotate
• Tap HUD: toggle HUD hide

View & Camera

• Mouse wheel: zoom in / out (0.35× – 4×), centered on the cursor; snaps to 1× with a brief catch
• Right click + drag / middle click + drag: pan the view
• Two-finger pinch: zoom and pan simultaneously
• Two-finger rotate: rotate the playfield view; snaps to 0°/90°/180°/270° with a brief catch
• Switching levels or resizing the window resets zoom, pan, and rotation

Game Modes

• Level mode: Play built-in levels (1. GRAVITY, 2. WALLs, 3. PORTALS, etc.). Players can place elements in empty cells to guide particles. Upon clearing, the level automatically switches to post-clear movable.
• Post-clear movable: Entered after clearing a level. All elements (including preset level elements) can be freely moved and deleted. Spawner, collector, and portal tools are fully unlocked. Importing with the "MOVABLE" checkbox sets the level's movable flag instead — same unrestricted editing, but not the post-clear runtime state.
• Sandbox (0. SANDBOX): Always unrestricted (same editing freedom as movable / post-clear movable). Comes with a randomly generated maze for player to kill time. Supports importing and exporting custom levels.

Element Reference

Conveyor >

Continuously applies a directional force to any particle touching it.
Valid rotations: 0°, 45°, 90°, 135°, 180°, 225°, 270°, 315°.

Spring U

When a particle touches it, launches the particle at high speed in the spring's facing direction, then enters a cooldown (symbol changes to V). Resets when cooldown finishes.
Valid rotations: 0°, 45°, 90°, 135°, 180°, 225°, 270°, 315°.

Portal P

Consists of a start (purple) and an end (blue). Particles that touch the start are instantly teleported to the end position with a brief cooldown to prevent re-triggering.
Place the start first, then click to place the end and pair them.
Cannot be rotated.

Wall #

A static obstacle. Particles bounce off according to their angle of incidence.
Valid rotations: 0°, 90°, 180°, 270°.

Horizontal walls (90° or 270°) are immovable by pistons — boundary walls default to this orientation. In post-clear movable, sandbox, or when the level's movable flag is set, boundary walls can be rotated to allow piston interaction.

Filter F

A type-selective wall. The filter is color-coded to a particle type (filterType): matching particles pass straight through as if it weren't there, while all other particles treat it exactly like a solid wall.
Cannot be rotated.

Piston [T]

When a particle approaches, the piston head extends in its facing direction, pushing elements ahead and applying velocity to particles. On retraction, it pulls elements behind the head back.
Valid rotations: 0°, 90°, 180°, 270°.
Stops its push chain upon encountering a horizontal wall, but can still push elements that have free space before the wall. Max piston chain 25.

Spawner [G]

Periodically spawns particles below itself (default: every 90 ticks). Pauses when the on-field particle count reaches the level's maxParticles.
Valid rotations: 0°, 90°, 180°, 270°.

Collector [@]

Collects any particle of its matching type (collectType) that enters its cell, incrementing the count and playing a sound effect. Particles of other types pass through without being collected.
The collector is color-coded to its collectType. When its own targetCount is reached, it dims to signal completion and stop collecting; a collector with targetCount 0 means infinite and never dims. If targetCount > 0, a lighter-colored number at the bottom-right shows how many more particles are needed. While the level clear condition is met, the HUD counter turns green.
Valid rotations: 0°, 90°, 180°, 270°.

Particle Types

Particles come in seven color-coded types, each with distinct physical properties. Spawners, collectors, and filters all reference these types.

o white — baseline: normal weight, gravity, friction and bounce
* yellow — light: falls slowly under reduced gravity, drifts more
= red — heavy: strong gravity, falls and stacks fast
# cyan — bouncy: very high restitution, rebounds energetically
+ green — near anti-gravity: barely falls and floats around the field
$ purple — sticky & heavy: very high friction, low bounce, slows down on conveyors, stacks easily, and is hard to launch off springs
~ orange — slippery: very low friction, low bounce, normal gravity, and moves faster on conveyors

Game UI

Sidebar

The sidebar provides various basic game controls. Here is a detailed info of each feature:
• LEVELS: a drop-down menu for selecting levels, use it to switch between levels
• LEVEL DESC.: displays the name and description of the current level
• TOOLS: a list of tools, click to switch tools, or use the shortcut keys ([1] to use select, [2] to use conveyor, etc.), the use of some tools may be restricted in some levels
• Control panel:
  — START / PAUSE:start or pause
  — RESET: kill all particles from the playfield and reset all collected counts
  — CLEAR ALL: Completely clean up the level, clearing all elements placed by the player and rebuild the level to its initial state
  — IMPORT (sandbox only): load a level by selecting a JSON file or pasting JSON text
  — EDIT (custom levels only): open the built-in JSON editor directly to modify level data
  — EXPORT (sandbox and custom levels only): export the current level as a JSON file, export dialog includes BOUNDARY (include boundary walls in the file) and MINIFY (output compact single-line JSON to reduce file size)
  — CUSTOMIZE (sandbox only): customize global colors and fonts (TTF/OTF, recommended to use monospace), more info below.

Quick Action Menu

Right-clicking a selected element opens the quick action menu (copy, paste, rotate, delete, etc.).
For spawners, collectors, and filters the menu also shows an element property panel:
• PARTICLE: click the - / + buttons to adjust particle type, or press and hold for rapid continuous adjustment
• INTERVAL (spawner only) / TARGET (collector only): click the − / + buttons to adjust by 1, or press and hold for rapid continuous adjustment.
Level-preset elements that cannot be edited in the current mode still show the property panel but appear grayed out and cannot be changed.
For mobile device, you can use "Level Preview" option to save level preview without pressing F2 key (normal touch: level preview, long press: live level preview).

HUD

The HUD (Heads-Up Display) is located in the top-right corner of the playfield canvas. It displays the following information:
• STATUS: simulation stat, displays :D (green) when running, and :| (orange) when paused
• CURSOR: the current grid cell coordinates of mouse cursor or touch point
• PARTICLES: the current number of active particles and the level's limit (current / level's maxParticles)
• COLLECTED: the total collected particles and the level's target (current / level's targetCount), the text turns green when the target is reached.

Others

Add ?debug=1 through ?debug=4 to the URL to show a debug overlay in the bottom-right corner. The panel is split into three sections — performance (top), device (middle), level (bottom):

?debug=1: performance basics (FPS text) and level summary
?debug=2: full performance section (FPS / 1% low / frametime charts, memory, physics / grid / renderer timings, fonts, lite) plus level size
?debug=3: device section (UA, viewport, SW, audio, etc.) and full level mode flags
?debug=4: full level section (entities, pointer, input, camera, clear state, etc.), hitboxes and guide overlays, plus element serialId labels and internal layout index on the canvas.

Debug mode also unlocks some test levels. Some of those levels have large amount of particles of entities and may cause stutter on your PC.

Level JSON Format

Top-level Fields

id (required): level identifier, allow lowercase letters, digits, -, ., _, max 50 chars. Exported files are named send_o-<id>.json (or send_o-<id>-preview.png).
name (required): display name shown in the level selector, max 100 chars
description: level description, max 500 chars
width / height: playfield size in grid cells (columns × rows), used to build boundary walls when buildBoundary is true, default 25 × 18
startX / startY: cartesian origin of the playfield rectangle (bottom-left corner), when buildBoundary is true, boundary walls are generated on this ring (with width / height), does not shift elements x/y coordinates, keep these aligned with your layout, a wrong origin can spawn walls in the wrong place, or even worse, make the game treat coincidental horizontal walls on that ring as redundant boundary walls and omit them on export
buildBoundary: whether to generate boundary walls around the playfield edges, true (default) or false, player-placed elements are kept, except horizontal walls on the playfield perimeter are ignored and omitted on export
maxParticles: maximum on-field particle count (non-negative integer), spawners pause when this limit is reached, set to 0 to prevent any spawning, default 20
targetCount: level clear target — total particles collected across all collectors (used when clearCondition is level or both), set to 0 for infinite, default 10
clearCondition: how the level is cleared — level (default), collectors (every collector with targetCount > 0 reaches its goal; HUD shows N / *), or both
disallowedTools: array of placement tools disabled during normal play (ignored in post-clear movable, sandbox, or when movable is true), valid values: conveyor, spring, portal, wall, filter, piston, portal (default), spawner (default), collector (default)
speed: level speed multiplier, values > 1 = speed up, values < = 1 slow down, default 1
gravity: gravity scale, 0 = zero-g, negative = upward gravity, 1 = default normal gravity
spawnNum: total particles each Spawner produces per active session, 0 (default) = unlimited
elements (required): array of element objects (may be empty)

Elements Array

Each element object contains:

serialId: unique integer within the level, used for portal pairing (required for portal)
tool (required): element type, one of: conveyor, spring, portal, wall, filter, piston, spawner, collector
x / y (required): grid position in cartesian coordinates (origin at bottom-left, x increases right, y increases up)
rotation (required for wall, conveyor, spring, piston): integer rotation angle in degrees
  — conveyor, spring: 0, 45, 90, 135, 180, 225, 270, 315
  — wall, piston: 0, 90, 180, 270
  — filter, portal, spawner, collector: field not needed (rotation has no effect)
  — any other value (e.g. 123, -1, 114.514, "x x xxx") is not allowed
role (portal only, required): start or end
pairedSerialId (portal only, required): the serialId of the paired portal
filterType (filter only): particle type allowed to pass through — o, *, =, #, +, $, ~ (default o)
spawnType (spawner only): particle type — o, *, =, #, +, $, ~ (default o)
interval (spawner only): spawn interval in ticks, default 90 (≈ 1.5 s at 60 Hz)
collectType (collector only): particle type the collector accepts — o, *, =, #, +, $, ~ (default o)
targetCount (collector only): per-collector collection target, 0 = infinite; a remaining-count badge appears at the collector's bottom-right corner

Rotation Reference

Angles are in clockwise degrees. The default facing direction varies by element type:
• Wall: 0° = vertical #
• Conveyor: 0° = pointing right
• Spring: 0° = launches upward
• Piston: 0° = pushes upward

JSON Format Example

{
  "id": "mylevel1",
  "name": "MY BEST LEVEL",
  "description": "This the best level you have ever seeeeeem.",
  "width": 25,
  "height": 18,
  "startX": 0,
  "startY": 0,
  "buildBoundary": true,
  "maxParticles": 32767,
  "targetCount": 0,
  "clearCondition": "level",
  "disallowedTools": ["portal", "spawner", "collector"],
  "speed": 1,
  "gravity": 1,
  "spawnNum": 0,
  "elements": []
}

Theme JSON Format

In sandbox mode, use CUSTOMIZE to load a theme JSON. Settings are saved in your browser. Use RESET in CUSTOMIZE to clear stored theme data.

Here's some example theme JSON:
"Default" theme JSON
"Example" theme JSON
"Paper" theme JSON
"Slate" theme JSON
"Starry" theme JSON

ui — game UI colors

Applied to the sidebar, window, buttons, etc.
bg: page / panel background
terminal: primary text and borders
terminalDark: secondary text
terminalDim: dimmed labels and hints
terminalLight: bright text (e.g. window titles)
accent: accent highlights (e.g. paused HUD tone, spring element default)
danger: important actions (CANCEL, RESET, delete spark effects)
hudRunning: color of :D
hudPaused: color of :|
hudCleared: HUD COLLECTED text when the clear target is met
modalBackdrop: dimmed area behind modal windows
panelBg, hoverBg, glow, subtleFill, accentHoverBg, dangerHoverBg: overrides for derived UI fills; leave empty ("") to auto-derive from bg / terminal / accent / danger

fonts — typography

game: name for game main font, also used for the send_o brand and window titles
ui: name for game UI
uiScale: multiplier applied to all UI text sizes, positive number between 0.2 and 8, default 1
uiSizes: optional per-component UI text multipliers, each key stacks on top of uiScale, same 0.2–8 range, default 1:
  — brand (send_o logo), sectionTitle, levelSelect (level dropdown), levelInfo (level description box), toolButton, toolGlyph (tool icons), tips, controlButton
  — hud, contextMenu (right-click menu), modalTitle, modalText, modalButton, formLabel, formInput, themeExport, fontAlign (font align panel), debugOverlay
bitmapFill: legacy export field, glyph colors come from canvas tints
elementOffsets: per-element glyph nudge inside each grid cell (pixels), keys match element types, each has offsetX / offsetY:
  — conveyor, spring, portal, wall, filter, piston ([T] idle body), pistonHead (extended T / [ ]), spawner, collector, particle
  — positive X moves right, positive Y moves down relative to the cell center crosshair
elementSizes: per-element glyph font size (pixels), same keys as elementOffsets.

canvas — playfield rendering

background: playfield background behind the grid
defaultTint: fallback tint for elements / particles without a dedicated entry
serialDebugLabel: tint for level JSON serialId labels on built-in elements (plain number, e.g. 5) when debug overlay level = 4 or higher
layoutSerialDebugLabel: tint for player-placed layout index labels (plain number with different color from serialDebugLabel, e.g. 0) when debug overlay level = 4 or higher
placementPreviewAlpha: opacity of the tool / paste placement ghost (0–1, default 0.55)

canvas.grid — grid dots / LOD cells
color: grid line / dot color
previewFillAlpha / previewStrokeAlpha: fill and outline of the placement preview cell under the cursor
lodFillAlpha / lodStrokeAlpha: grid dot fill and cell outline opacity
lodStrokeWidth: background cell outline width in screen pixels

canvas.selection — multi-select marquee on the playfield
color: selection box stroke color
fillAlpha: selection box fill opacity
strokeWidth: selection box line width in screen pixels

canvas.elements — fixed element glyph tints (bitmap text on the grid)
wall, conveyor: static element color
spring: default spring color; springReady / springCooldown: spring ready vs. on-cooldown states
piston, pistonHead: idle body ([T]) vs. extended head / bracket (T / [ ])
portalStart, portalEnd: portal start vs. end glyphs
• Filter, spawner, and collector glyphs are tinted by their particle type — see canvas.particles below, not this section

canvas.particles — particle and type-colored element tints (keys are particle type characters)
o white, * yellow, = red, # cyan, + green, $ magenta, ~ orange
• Also drives filter / spawner / collector colors according to their configured particle type

canvas.fx — short-lived effect colors
place: spark effects when placing elements
delete: spark effects when deleting
copy / cut: clipboard operation spark effects
spawn: spawner emit spark effects
select: selection-change spark effects
floatingText: floating COPY / CUT / PASTE labels

canvas.collector — collector full / badge styling
dimFactor: multiply tint when collector target is met (default 0.45)
badgeLighten: lighten factor for the remaining-count badge (default 0.55)

Theme color values

Most theme color fields accept #rgb / #rrggbb or integer tints on canvas / debug.
For cycling RGB lighting, use a chroma object instead of a plain color:
{ "chroma": { "colors": ["#ff0080", "#00e5ff", "#a855f7"], "speed": 1.2 } }
colors: at least two hex colors, cycled in array order
speed: full cycles per second (default 1); higher = faster
Chroma works on UI colors, canvas tints, and debug overlay colors. Optional rgba UI overrides (panelBg, etc.) cannot use chroma.

effects — page overlays (full send_o only)

crtOverlay: scanline RGB overlay, default true
crtGlow: inset screen glow, default true
crtFlicker: full-screen flicker layer, default true
modalGlow: pulsing glow on window content, default true
hoverReveal: cursor-following highlight on UI buttons, default true

debug — debug overlay

hitboxPenetrable, hitboxSolid, hitboxPhysics, hitboxCollectorFull: playfield hitbox colors
direction, portalLink, pointerCell, pointerCellOutside, playfieldBounds, fitBounds: guide overlays
fpsChart, lowFpsChart, longFrameMarker: performance charts
overlayText, overlayBorder, overlayBg: debug panel chrome (dark themes; light themes still derive panel colors from ui)

Answers

Here's some walkthroughs for hard or tutorial levels (PS: These may not be perfect, you can find better ways to complete them).

Issues

Go to about page for contact info.

Known issue:
• Hold SE does not play correctly in desktop Safari (WebKit) browsers
(Test environment: MacBook Pro 2024 / macOS Tahoe 26.5.1 / Safari (I forgot the version)).

Source

Matter.js - Matter.js physics engine
PixiJS - PixiJS renderer
Share Tech - Game default UI font
• unsafe-eval — PixiJS text rendering adapter
VT323 - Game default main font

This game contains AI-assisted code

For sources used by pages other than send_o, see the source page

遊戲介紹

send_o 是一款以文字組成的沙盒遊戲。玩家需要透過放置各種元素(conveyor、spring、piston 等),引導從 spawner(s) 產生的粒子抵達 collector(s),達到目標數量即可通關。
遊戲同時提供沙盒模式與關卡創作功能,允許玩家自由設計並匯出、匯入自訂關卡。

本遊戲建議使用電腦版 Chrome (Blink) 或 Firefox (Gecko) 系列瀏覽器遊玩,這兩種都測試過了不會有太大問題。

遊戲也有機制相同,但減少了視覺效果的 簡易版 遊戲。

基本鍵位

滑鼠

• 左鍵點擊:放置元素 / 選取元素
• 左鍵拖曳:連續放置 / 移動元素(需使用 "SELECT" 工具)
• 右鍵拖曳 / 中鍵拖曳:平移視野
• 右鍵點擊:開啟右鍵選單(複製、貼上、旋轉、刪除等)
• 拖曳側欄上的「send_o」標題:移動側欄
• 雙擊側欄上的「send_o」標題:重置側欄位置
• 點擊 HUD:切換 HUD 隱藏

鍵盤快捷鍵

• 空白鍵:開始 / 暫停
• 1:切換至 SELECT 工具
• 2:切換至 CONVEYOR 工具
• 3:切換至 SPRING 工具
• 4:切換至 PORTAL 工具
• 5:切換至 WALL 工具
• 6:切換至 FILTER 工具
• 7:切換至 PISTON 工具
• 8:切換至 SPAWNER 工具
• 9:切換至 COLLECTOR 工具
• R:旋轉
• D / Delete:刪除
• CTRL(或 ⌘)+ Z:復原
• CTRL + Y / ⌘ + shift + Z:重做
• CTRL(或 ⌘)+ C / CTRL(或 ⌘)+ X / CTRL(或 ⌘)+ V:複製 / 剪下 / 貼上
• F2:儲存關卡預覽(PNG)
• Shift + F2:儲存即時關卡預覽(PNG)
• Escape:取消選取 / 取消貼上模式

觸控

• 單指:等同滑鼠左鍵(放置、選取、拖曳)
• 長按:開啟右鍵選單
• 雙指:捏合縮放、拖曳平移、扭轉旋轉
• 點擊 HUD:切換 HUD 隱藏

視野與畫面

• 滑鼠滾輪:以游標為中心縮放(0.35× ~ 4×),接近 1× 時會短暫吸住
• 右鍵拖曳 / 中鍵拖曳:平移視野
• 雙指捏合(觸控):同時縮放與平移
• 雙指旋轉(觸控):旋轉遊戲場地視角,接近 0°、90°、180°、270° 時會短暫吸住
• 切換關卡或視窗大小改變時,會重設縮放、平移與旋轉

遊戲模式

• 關卡模式:遊玩內建關卡(1. GRAVITY、2. WALLS、3. PORTALS 等),玩家可在空格放置元素協助引導粒子,通關後自動切換為 post-clear movable 讓玩家繼續遊玩。
• Post-clear movable:通關後進入。在此狀態下,所有元素(包含關卡預設配置)均可自由移動與刪除,spawner、collector、portal 等強到飛起的工具也全部開放。匯入時勾選 MOVABLE 則是設定關卡的 movable 旗標 — 編輯自由度相同,但不是通關後的 runtime 狀態。
• 沙盒(0. SANDBOX):永遠無限制(與 movable / post-clear movable 同樣的編輯自由度),附帶隨機迷宮供玩家耍廢,可隨意改動場地、匯入、匯出自訂關卡。

元素說明

Conveyor >

對接觸的粒子施加持續推力,使粒子朝指定方向移動。
可用角度:0°、45°、90°、135°、180°、225°、270°、315°。

Spring U

感測到粒子時,將粒子以較高速度向彈簧朝向的方向彈射出去,之後進入冷卻(符號變為 V),冷卻結束後恢復可用。
可用角度:0°、45°、90°、135°、180°、225°、270°、315°。

Portal P

分為起點(紫色)和終點(藍色)。粒子接觸起點後瞬間傳送到終點位置,有短暫冷卻防止重複觸發。
放置時先點擊起點,再點擊終點以配對。不可旋轉。

Wall #

靜態障礙物,粒子碰到後會被彈開。
可用角度:0°、90°、180°、270°。

橫向牆壁(90° 或 270°)具有特殊特性:活塞無法推動或拉回它們,邊界牆預設即為橫向。在 post-clear movable、沙盒,或關卡設定了 movable 時,可旋轉邊界牆使活塞能正常互動。

Filter F

依粒子類型選擇性通過的牆壁。Filter 會以對應粒子類型(filterType)的顏色標示:符合類型的粒子會像它不存在一樣直接穿過,其它類型的粒子則把它當成普通實心牆壁。
不可旋轉。

Piston [T]

感測到粒子靠近時,活塞頭向指定方向伸出,推動前方的元素並對粒子施加速度;縮回時拉回後方的元素。
活塞本體([T] / [ ])為實體;伸出的活塞頭(T)為虛體 — 粒子可穿過,但仍會受到推力。
可用角度:0°、90°、180°、270°。
遇到橫向牆壁時停止推進鏈,但仍可推送橫向牆前方有空間的元素。活塞鏈最多 25。

Spawner [G]

定時在其下方生成粒子(預設每 90 個 tick 一顆)。當場上粒子數達到關卡的 maxParticles 時暫停生成。
可用角度:0°、90°、180°、270°。

Collector [@]

只收集進入其格子且類型相符(collectType)的粒子,計數加一並播放音效提醒;其它類型的粒子會直接穿過不被收集。
Collector 會以其 collectType 的顏色標示。當它自己的 targetCount 達成時會調暗顏色以示完成並停止收集;targetCount 為 0 代表無限,永遠不會調暗。targetCount > 0 時,右下角會顯示還差幾顆。關卡通關條件達成時 HUD 上的 COLLECTED 數字會轉為綠色。
可用角度:0°、90°、180°、270°。在沙盒中新放置的 collector 預設 targetCount 為 0(無限)。

粒子類型

粒子分為七種以顏色標示的類型,各自具有不同的物理特性。Spawner、collector、filter 都會參照這些類型。

o 白 — 基準:正常的重量、重力、摩擦與彈性。
* 黃 — 輕盈:重力較小,下落緩慢、較會飄。
= 紅 — 沉重:重力強,下落與堆疊都很快。
# 青 — 彈跳:彈性極高,會充滿活力地反彈。
+ 綠 — 近反重力:幾乎不下落,會在場上飄浮。
$ 紫 — 又黏又重:摩擦極高、彈性極低,在輸送帶上會減速、容易堆疊,也很難被彈簧彈走。
~ 橘 — 滑溜:摩擦極低、彈性偏低,維持正常重力,在輸送帶上會跑得更快。

遊戲介面

側欄

側欄提供遊戲的各項基礎功能。以下是具體的功能介紹:
• LEVELS:關卡選擇下拉選單,可切換關卡
• LEVEL DESC.:顯示目前關卡的名稱與描述
• TOOLS:放置工具列表,點擊即可切換工具,或按對應捷徑鍵(如 [1] 切換選取、[2] 切換傳送帶等),某些關卡可能會限制使用部分工具
• 控制面板:
  — START / PAUSE:開始或暫停
  — RESET:清除場上所有粒子並將所有收集器的計數歸零
  — CLEAR ALL:完全重置關卡,清除玩家放置的所有元素並回復至關卡初始狀態
  — IMPORT(沙盒專用):透過選擇 JSON 檔案或貼上 JSON 文字來載入關卡
  — EDIT(自訂關卡專用):直接開啟內建 JSON 編輯器來修改關卡資料
  — EXPORT(沙盒、自訂關卡專用):將目前的關卡匯出為 JSON 檔案,匯出時可勾選 BOUNDARY(是否包含邊界牆)與 MINIFY(輸出壓縮單行 JSON 以縮小檔案)
  — CUSTOMIZE (沙盒專用):自訂全域配色表或自訂字體(TTF / OTF,建議使用等寬字體),更多資訊設於下方。

快速操作選單

對選取的元素按右鍵會開啟右鍵選單(複製、貼上、旋轉、刪除等)。
若選取的是 spawner、collector 或 filter,選單會顯示元素屬性面板:
• PARTICLE:點一下 − / + 按鈕調整粒子類型,長按則可快速連續調整
• INTERVAL(spawner 專用)/ TARGET(collector 專用):點一下 − / + 按鈕調整 1,長按則可快速連續調整。
在目前模式下不可編輯的關卡預設元素仍會顯示屬性區塊,但會以灰階呈現且無法修改。
對於觸控裝置,你可以使用「Level Preview」選項來儲存關卡預覽(短按:關卡預覽,長按:即時關卡預覽)。

HUD

HUD (Heads-Up Display) 顯示面板位於畫面右上角。主要顯示以下遊戲狀態:
• STATUS:模擬狀態,執行時顯示 :D(綠色),暫停時顯示 :|(橘色)
• CURSOR:游標或觸控點所在的網格座標
• PARTICLES:目前場上的粒子數量與該關卡的粒子上限(目前 / 關卡的 maxParticles
• COLLECTED:已收集的粒子數量與通關目標(目前 / 關卡的 targetCount),達標時字體會轉為綠色。

其它

在網址加上 ?debug=1?debug=4 可開啟右下角 debug overlay。面板分為三區——上方效能、中間裝置、下方關卡:

?debug=1:效能基本資訊(FPS 文字)與關卡摘要
?debug=2:完整效能區(FPS / 1% low / frametime 圖表、記憶體、物理 / 網格 / 渲染耗時、字體、lite)以及關卡尺寸
?debug=3:裝置區(UA、viewport、SW、audio 等)與完整關卡模式旗標
?debug=4:完整關卡區(實體數、游標、輸入、鏡頭、通關狀態等)、碰撞箱與輔助線疊層,以及畫布上的元件 serialId 與內部佈局索引

除錯狀態會一併開放部分測試用關卡,不過部分測試關卡粒子、實體較多,在電腦上可能造成卡頓。

關卡 JSON 格式

全域欄位

id(必填):關卡識別碼,接受小寫英文字母、數字、-、.、_,最多 50 個字元。匯出檔名為 send_o-<id>.json(預覽圖為 send_o-<id>-preview.png)。
name(必填):顯示於選單的關卡名稱,最多 100 個字元
description:關卡描述,最多 500 個字元
width / height:遊戲場地寬高(格子數,欄 × 列),在 buildBoundary 被設為 true 時會以此生成邊界牆,預設 25 × 18
startX / startY:場地矩形的直角座標原點(左下角),當 buildBoundary 為 true 時,邊界牆會沿此原點搭配 width / height 的外圈生成,不會改動 elementsx/y,請讓它們對齊實際佈局,原點設錯可能把自動邊界牆生到錯的地方,或甚至剛好壓在該圈上的橫置牆會被當成冗餘邊界牆、匯出時被省略(消失)
buildBoundary:是否在場地四周生成邊界牆,true(預設)或 false,邊界牆生成區域上其它玩家放置的元素仍會保留,但場地周界上與邊界牆材料重複的橫置牆會被忽略且匯出時省略
maxParticles:場上粒子上限,接受非負整數,超過此數量後 spawner 暫停生成,填 0 表示不產生任何粒子,預設 20
targetCount:關卡通關目標(所有 collector 收集總量,用於 clearConditionlevelboth 時),接受正整數,填 0 表示無限,預設 10
clearCondition:通關條件 — level(預設)、collectors(每個 targetCount > 0 的 collector 都達標;HUD 顯示 N / *)、both(兩者皆須達成)
disallowedTools:一般遊玩時禁用的放置工具陣列(post-clear movable、沙盒,或 movable 為 true 時不受限),可填 conveyor、spring、portal、wall、filter、piston、portal(預設)、spawner(預設)、collector(預設)
speed:遊戲速度倍率,接受大於 0 的數值(0.5 = 0.5 倍速,2 = 兩倍速),預設 1
gravity:重力大小,0 = 現在處於無重力,-1 = 輕飄飄,1 = 正常重力
spawnNum:Spawner 單次 active 狀態產生的粒子總數,0(預設)= 無限制持續生成
elements(必填):元素物件陣列(可為空陣列)

elements 陣列

每個元素包含以下欄位:

serialId:元素的序列號,用於 portal 配對,同一關卡內不可重複(portal 必填)
tool(必填):元素類型,可選值:conveyor、spring、portal、wall、filter、piston、spawner、collector
x / y(必填):元素在直角座標系的格子座標(左下角為原點 (0,0),向右 x 增加,向上 y 增加)
rotation(wall、conveyor、spring、piston 必填):元素旋轉角度(整數度數)
  — conveyor、spring:0, 45, 90, 135, 180, 225, 270, 315
  — wall、piston:0, 90, 180, 270
  — filter、portal、spawner、collector 不需要此欄位(旋轉無效)
  — 不接受其它未提到的數值(如 123、-1、114.514、"x x xxx")
role(portal 專用,必填):start(起點)或 end(終點)
pairedSerialId(portal 專用,必填):配對另一端的 serialId
filterType(filter 專用):允許通過的粒子類型,可選:o、*、=、#、+、$、~(預設 o)
spawnType(spawner 專用):粒子類型,可選:o、*、=、#、+、$、~(預設 o)
interval(spawner 專用):生成間隔(tick 數),預設 90(約 1.5 秒)
collectType(collector 專用):此 collector 收集的粒子類型,可選:o、*、=、#、+、$、~(預設 o)
targetCount(collector 專用):此 collector 的收集目標數,0 = 無限,collector 會在右下角顯示還差幾顆

旋轉角度參考

角度為順時針度數。各元素預設朝向如下:
• Wall:0° = 直向 #
• Conveyor:0° = 向右推力
• Spring:0° = 向上彈射
• Piston:0° = 向上推送

JSON 格式範例

{
  "id": "mylevel1",
  "name": "為什麼飯不能咬太久",
  "description": "因為會飯太碎",
  "width": 25,
  "height": 18,
  "startX": 10,
  "startY": 10,
  "buildBoundary": true,
  "maxParticles": 32767,
  "targetCount": 0,
  "clearCondition": "level",
  "disallowedTools": ["portal", "spawner", "collector"],
  "speed": 1,
  "gravity": 1,
  "spawnNum": 0,
  "elements": []
}

外觀主題 JSON 格式

沙盒關卡中,於 CUSTOMIZE 選擇 theme JSON 後按 APPLY 即可載入。設定會儲存在你的瀏覽器;若要清除,可在 CUSTOMIZE 使用 RESET。

這裡有些外觀主題 JSON 可以讓你玩玩看:
預設外觀主題 JSON
範例外觀主題 JSON
「Paper」外觀主題 JSON
「Slate」外觀主題 JSON
「Starry」外觀主題 JSON

ui — 遊戲介面配色

套用至側欄、對話框、按鈕等頁面元素。
bg:頁面、面板背景
terminal:主要文字與邊框
terminalDark:次要文字
terminalDim:較淡的標籤與提示
terminalLight:較亮的文字(如視窗標題)
accent:強調色
danger:重要操作(CANCEL、RESET、刪除的火花效果)
hudRunning::D 的顏色
hudPaused::| 的顏色
hudCleared:達成通關目標時 HUD COLLECTED 字樣的顏色
modalBackdrop:modal 視窗後方遮罩
panelBghoverBgglowsubtleFillaccentHoverBgdangerHoverBg:衍生 UI 填色的可選覆寫;留空("")則依 bg / terminal / accent / danger 自動推算

fonts — 字型相關

game:遊戲主要使用的字型名稱,也用於 send_o 標題與視窗標題
ui:遊戲介面使用的字型名稱
uiScale:套用到所有 UI 文字大小的倍率,接受 0.2 至 8 之間的正數,預設 1
uiSizes:可選的各部件 UI 文字倍率,每個鍵會疊加在 uiScale 之上,同樣為 0.2~8,預設 1:
  — brand(send_o 標誌)、sectionTitlelevelSelect(關卡下拉選單)、levelInfo(關卡說明框)、toolButtontoolGlyph(工具圖示)、tipscontrolButton
  — hudcontextMenu(右鍵選單)、modalTitlemodalTextmodalButtonformLabelformInputthemeExportfontAlign(字型對齊面板)、debugOverlay
bitmapFill:匯出相容欄位,實際字形顏色由 canvas tint 決定
elementOffsets:各元素字形在格子內的位移(像素),鍵名對應元素類型,每項含 offsetX / offsetY
  — conveyorspringportalwallfilterpiston(收合態 [T])、pistonHead(伸出態 T / [ ])、spawnercollectorparticle
  — X 正值向右、Y 正值向下,相對於格子中心十字線
elementSizes:各元素字形字級(像素),鍵名同 elementOffsets

canvas — 遊戲場地繪製

background:網格後方的場地背景色
defaultTint:沒有專屬設定的元素、粒子之預設著色
serialDebugLabel:除錯顯示等級 4 以上時,關卡內建元件的 JSON serialId 標籤(純數字,如 5)顏色
layoutSerialDebugLabel:除錯顯示等級 4 以上時,玩家放置元件的佈局索引標籤(與 serialDebugLabel 顏色不同的純數字,如 0)顏色
placementPreviewAlpha:放置/貼上預覽幽靈元件透明度(0–1,預設 0.55)

canvas.grid — 網格點與 LOD 簡化格線
color:網格點、格線顏色
previewFillAlpha / previewStrokeAlpha:游標下放置預覽格的填色與描邊透明度
lodFillAlpha / lodStrokeAlpha:網格點填色與格線描邊透明度
lodStrokeWidth:背景格線線寬(螢幕像素)

canvas.selection — 場上框選區域
color:選取框邊線顏色
fillAlpha:選取框填色透明度
strokeWidth:選取框線寬(螢幕像素)

canvas.elements — 固定元素字形的著色(場上點陣文字)
wallconveyor:靜態元素顏色
spring:彈簧預設色;springReady / springCooldown:可觸發 / 冷卻中
pistonpistonHead:收合本體([T])與伸出頭部/括號(T / [ ]
portalStartportalEnd:傳送門起點與終點
• filter、spawner、collector 依其粒子類型著色,請看下面的 canvas.particles,不在這裡

canvas.particles — 粒子與依類型著色之元素的顏色(鍵名為粒子字元)
o 白、* 黃、= 紅、# 青、+ 綠、$ 洋紅、~
• 亦決定 filter / spawner / collector 依所設粒子類型顯示的顏色

canvas.fx — 短暫特效顏色
place:放置元素時的火花效果
delete:刪除時的火花效果
copy / cut:剪貼簿操作的火花效果
spawn:spawner 生成粒子時的火花效果
select:選取變更時的火花效果
floatingText:COPY / CUT / PASTE 等浮動文字

canvas.collector — collector 滿載/徽章樣式
dimFactor:達標後字形 tint 乘算係數(預設 0.45)
badgeLighten:剩餘數量徽章的提亮係數(預設 0.55)

主題色欄位格式

多數主題色欄位可填 #rgb / #rrggbbcanvas / debug 的整數 tint。
若要電競鍵盤式的循環 RGB,可改用 chroma 物件:
{ "chroma": { "colors": ["#ff0080", "#00e5ff", "#a855f7"], "speed": 1.2 } }
colors:至少兩個 hex 色,依陣列順序輪播
speed:每秒完整循環次數(預設 1),越大越快
chroma 可用於 UI、canvas tint、debug 色;rgba 衍生 UI 覆寫(panelBg 等)不支援 chroma。

effects — 頁面疊加效果(僅完整版 send_o)

crtOverlay:掃描線 RGB 疊層,預設 true
crtGlow:內緣螢幕光暈,預設 true
crtFlicker:全畫面閃爍層,預設 true
modalGlow:視窗內容脈動光暈,預設 true
hoverReveal:UI 按鈕的游標跟隨高光,預設 true

debug — 除錯 overlay

hitboxPenetrablehitboxSolidhitboxPhysicshitboxCollectorFull:場上 hitbox 顏色
directionportalLinkpointerCellpointerCellOutsideplayfieldBoundsfitBounds:輔助線與指標
fpsChartlowFpsChartlongFrameMarker:效能圖表
overlayTextoverlayBorderoverlayBg:除錯面板外觀(淺色主題仍多由 ui 推算面板色)

參考答案

這裡 有一部分教學性質或高難度關卡的範例(可能不完美,你應該可以找到比我好的方法通關)。

問題與回報

前往關於我頁面取得聯繫方式。

已知問題:
• 電腦版 Safari (WebKit) 系列瀏覽器無法正常播放長按音效
(測試環境:MacBook Pro 2024 / macOS Tahoe 26.5.1 / Safari(忘了版本))。

素材來源

Matter.js - Matter.js 物理引擎
PixiJS - PixiJS 渲染引擎
Share Tech - 遊戲預設介面字體
• unsafe-eval — PixiJS 文字渲染配接器
VT323 - 遊戲預設主要字體

本遊戲有使用 AI 輔助程式碼

send_o 以外的其它網頁素材來源請見 source 頁面

• 剛開始搞創作關卡功能的時候第一個做出來測試的關卡是 far in the blue sky... 的轉譜
• 原來這個遊戲的預設主題是想要有點復古的 CRT 風所以用綠色,我後來覺得太土太花就換成白色了
• 到了 3.0 才確定每一代都有一個大版本代號以及代表關卡,例如 3.0 Triangle 就是第 5 關 Triangles、4.0 Square 是第 10 關 Squares,5.0 Pentagon 因為我不知道怎麼畫好看的五邊形所以以 5.0 的特色(多種類的粒子)做了第 15 關 Rainbow
• 活塞很難做很難做很難做很難做很難做很難做很難做很難做很難做
• 有 bug 一定要告訴我啊我一個人不一定測試的出所有 bug