---@meta
-- Generated by usagi 0.6.1. Run `usagi refresh` to update.
-- Usagi API stubs for lua-language-server.
-- Declarations only; this file is never executed by the runtime.

---Pico-8 palette, indices 0-15.
---@class Usagi.Gfx
---@field COLOR_BLACK        integer  0
---@field COLOR_DARK_BLUE    integer  1
---@field COLOR_DARK_PURPLE  integer  2
---@field COLOR_DARK_GREEN   integer  3
---@field COLOR_BROWN        integer  4
---@field COLOR_DARK_GRAY    integer  5
---@field COLOR_LIGHT_GRAY   integer  6
---@field COLOR_WHITE        integer  7
---@field COLOR_RED          integer  8
---@field COLOR_ORANGE       integer  9
---@field COLOR_YELLOW       integer  10
---@field COLOR_GREEN        integer  11
---@field COLOR_BLUE         integer  12
---@field COLOR_INDIGO       integer  13
---@field COLOR_PINK         integer  14
---@field COLOR_PEACH        integer  15
gfx = {}

---Clears the screen to the given color.
---@param color integer  a gfx.COLOR_* constant
function gfx.clear(color) end

---Draws text at (x, y) in the given color. Uses the bundled monogram
---font at its 16px design size (a 5×7 pixel font with 16px line height).
---@param text  string  string to render
---@param x     number  left edge in game-space pixels
---@param y     number  top edge in game-space pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.text(text, x, y, color) end


---Draws a rectangle outline.
---@param x     number  left edge in game-space pixels
---@param y     number  top edge in game-space pixels
---@param w     number  width in pixels
---@param h     number  height in pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.rect(x, y, w, h, color) end

---Draws a filled rectangle.
---@param x     number  left edge in game-space pixels
---@param y     number  top edge in game-space pixels
---@param w     number  width in pixels
---@param h     number  height in pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.rect_fill(x, y, w, h, color) end

---Draws a circle outline centered at (x, y).
---@param x     number  center x in game-space pixels
---@param y     number  center y in game-space pixels
---@param r     number  radius in pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.circ(x, y, r, color) end

---Draws a filled circle centered at (x, y).
---@param x     number  center x in game-space pixels
---@param y     number  center y in game-space pixels
---@param r     number  radius in pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.circ_fill(x, y, r, color) end

---Draws a line from (x1, y1) to (x2, y2).
---@param x1    number  start x in game-space pixels
---@param y1    number  start y in game-space pixels
---@param x2    number  end x in game-space pixels
---@param y2    number  end y in game-space pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.line(x1, y1, x2, y2, color) end

---Sets a single pixel.
---@param x     number  x in game-space pixels
---@param y     number  y in game-space pixels
---@param color integer  a gfx.COLOR_* constant
function gfx.pixel(x, y, color) end

---Draws a 16×16 sprite from the loaded sheet at (x, y). The sheet is
---`sprites.png` next to the game's main .lua; indices run left-to-right,
---top-to-bottom. Alpha-channel pixels render as transparent.
---@param index integer  one-based sprite index (1 = top-left cell)
---@param x     number   destination left edge in game-space pixels
---@param y     number   destination top edge in game-space pixels
function gfx.spr(index, x, y) end

---Extended `spr`: draws a 16×16 sprite with required flip flags. Same
---indexing as `gfx.spr`.
---@param index  integer  one-based sprite index (1 = top-left cell)
---@param x      number   destination left edge in game-space pixels
---@param y      number   destination top edge in game-space pixels
---@param flip_x boolean  flip horizontally (mirror left/right) when true
---@param flip_y boolean  flip vertically (mirror top/bottom) when true
function gfx.spr_ex(index, x, y, flip_x, flip_y) end

---Draws an arbitrary (sx, sy, sw, sh) rectangle from `sprites.png` at
---(dx, dy) at its original size. `s*` args index into the source sheet
---in pixels; `d*` args are the destination on screen.
---@param sx number  source rect left edge on `sprites.png` (pixels)
---@param sy number  source rect top edge on `sprites.png` (pixels)
---@param sw number  source rect width in pixels
---@param sh number  source rect height in pixels
---@param dx number  destination left edge in game-space pixels
---@param dy number  destination top edge in game-space pixels
function gfx.sspr(sx, sy, sw, sh, dx, dy) end

---Extended `sspr`: source rect stretched to (dw, dh) at the destination
---with required flip flags. All ten args required; write a thin
---wrapper if a particular flag combination shows up often in your
---code.
---@param sx     number   source rect left edge on `sprites.png` (pixels)
---@param sy     number   source rect top edge on `sprites.png` (pixels)
---@param sw     number   source rect width in pixels
---@param sh     number   source rect height in pixels
---@param dx     number   destination left edge in game-space pixels
---@param dy     number   destination top edge in game-space pixels
---@param dw     number   destination width in pixels (stretches the source)
---@param dh     number   destination height in pixels (stretches the source)
---@param flip_x boolean  flip horizontally (mirror left/right) when true
---@param flip_y boolean  flip vertically (mirror top/bottom) when true
function gfx.sspr_ex(sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y) end

---Activates a post-process fragment shader. Loads `shaders/<name>.fs`
---(and optional `<name>.vs`) and runs it as the final pass when the
---game render target is blitted to the window. Pass nil to clear.
---On web the loader prefers `<name>_es.fs` (GLSL ES 100); on desktop
---it prefers `<name>.fs` (GLSL 330). Shader source live-reloads on
---save in `usagi dev`.
---@param name string|nil  shader name (file stem under `shaders/`), or nil to clear
function gfx.shader_set(name) end

---Sets a uniform on the active shader. The value type drives the
---uniform type: a number maps to float, a 2/3/4-length numeric table
---maps to vec2 / vec3 / vec4. Queues the write; the engine flushes
---queued uniforms once per frame before the post-process pass.
---@param name  string                                    uniform name as declared in the shader source
---@param value number|number[]                           float, or {x, y} / {x, y, z} / {x, y, z, w}
function gfx.shader_uniform(name, value) end

---@class Usagi.Sfx
sfx = {}

---Plays a sound effect by name. Names are file stems from the `sfx/`
---directory next to the game's main .lua (e.g. `sfx/jump.wav` → "jump").
---Unknown names silently no-op. Calling while already playing restarts.
---@param name string  file stem of a `.wav` under `sfx/`
function sfx.play(name) end

---@class Usagi.Music
music = {}

---Plays a music track once and stops at the end. Names are file stems
---from the `music/` directory next to the game's main .lua (e.g.
---`music/intro.ogg` → "intro"). Recognized extensions: ogg, mp3, wav,
---flac. Stops the currently-playing track first if there is one.
---Unknown names silently no-op. Callable from `_init` so a title
---track can start the moment the window opens.
---@param name string  file stem under `music/`
function music.play(name) end

---Plays a music track and loops it forever. Stops the currently-
---playing track first. Callable from `_init`.
---@param name string  file stem under `music/`
function music.loop(name) end

---Stops whatever music is currently playing. No-op when nothing is.
function music.stop() end

---Abstract input actions. Each is a union over keyboard keys, gamepad
---buttons, and analog-stick directions:
---
---- LEFT:  arrow left, A, dpad left, left stick left
---- RIGHT: arrow right, D, dpad right, left stick right
---- UP:    arrow up, W, dpad up, left stick up
---- DOWN:  arrow down, S, dpad down, left stick down
---- BTN1:  Z, J; gamepad south face (Xbox A, PS Cross)
---- BTN2:  X, K; gamepad east face  (Xbox B, PS Circle)
---- BTN3:  C, L; gamepad north + west face (Xbox Y/X, PS Triangle/Square)
---
---Mouse buttons (separate from the action constants above):
---
---- MOUSE_LEFT:  left mouse button
---- MOUSE_RIGHT: right mouse button
---
---Source identifiers for `input.last_source()` and the source-aware
---`input.mapping_for`:
---
---- SOURCE_KEYBOARD: "keyboard"
---- SOURCE_GAMEPAD:  "gamepad"
---@class Usagi.Input
---@field LEFT             integer
---@field RIGHT            integer
---@field UP               integer
---@field DOWN             integer
---@field BTN1             integer
---@field BTN2             integer
---@field BTN3             integer
---@field MOUSE_LEFT       integer
---@field MOUSE_RIGHT      integer
---@field SOURCE_KEYBOARD  string
---@field SOURCE_GAMEPAD   string
---@field KEY_A            integer
---@field KEY_B            integer
---@field KEY_C            integer
---@field KEY_D            integer
---@field KEY_E            integer
---@field KEY_F            integer
---@field KEY_G            integer
---@field KEY_H            integer
---@field KEY_I            integer
---@field KEY_J            integer
---@field KEY_K            integer
---@field KEY_L            integer
---@field KEY_M            integer
---@field KEY_N            integer
---@field KEY_O            integer
---@field KEY_P            integer
---@field KEY_Q            integer
---@field KEY_R            integer
---@field KEY_S            integer
---@field KEY_T            integer
---@field KEY_U            integer
---@field KEY_V            integer
---@field KEY_W            integer
---@field KEY_X            integer
---@field KEY_Y            integer
---@field KEY_Z            integer
---@field KEY_0            integer
---@field KEY_1            integer
---@field KEY_2            integer
---@field KEY_3            integer
---@field KEY_4            integer
---@field KEY_5            integer
---@field KEY_6            integer
---@field KEY_7            integer
---@field KEY_8            integer
---@field KEY_9            integer
---@field KEY_F1           integer
---@field KEY_F2           integer
---@field KEY_F3           integer
---@field KEY_F4           integer
---@field KEY_F5           integer
---@field KEY_F6           integer
---@field KEY_F7           integer
---@field KEY_F8           integer
---@field KEY_F9           integer
---@field KEY_F10          integer
---@field KEY_F11          integer
---@field KEY_F12          integer
---@field KEY_SPACE        integer
---@field KEY_ENTER        integer
---@field KEY_ESCAPE       integer
---@field KEY_TAB          integer
---@field KEY_BACKSPACE    integer
---@field KEY_DELETE       integer
---@field KEY_LEFT         integer
---@field KEY_RIGHT        integer
---@field KEY_UP           integer
---@field KEY_DOWN         integer
---@field KEY_LSHIFT       integer
---@field KEY_RSHIFT       integer
---@field KEY_LCTRL        integer
---@field KEY_RCTRL        integer
---@field KEY_LALT         integer
---@field KEY_RALT         integer
---@field KEY_BACKTICK     integer
---@field KEY_MINUS        integer
---@field KEY_EQUAL        integer
---@field KEY_LBRACKET     integer
---@field KEY_RBRACKET     integer
---@field KEY_BACKSLASH    integer
---@field KEY_SEMICOLON    integer
---@field KEY_APOSTROPHE   integer
---@field KEY_COMMA        integer
---@field KEY_PERIOD       integer
---@field KEY_SLASH        integer
input = {}

---Returns true the frame any source bound to `action` first went down.
---@param action integer  one of input.LEFT / RIGHT / UP / DOWN / BTN1 / BTN2 / BTN3
---@return boolean
function input.pressed(action) end

---Returns true while any source bound to `action` is held.
---@param action integer  one of input.LEFT / RIGHT / UP / DOWN / BTN1 / BTN2 / BTN3
---@return boolean
function input.held(action) end

---Returns true the frame any source bound to `action` first went up
---(transitioned from held to released). Mirrors `input.pressed` for the
---release edge.
---@param action integer  one of input.LEFT / RIGHT / UP / DOWN / BTN1 / BTN2 / BTN3
---@return boolean
function input.released(action) end

---Label of the active input source's primary binding for `action` (e.g.
---"Z" on keyboard, "Pad-A" on gamepad). Honors any keymap remap the
---player set via the pause menu's Configure Keys flow. Useful for
---rendering contextual control prompts. Returns `nil` for unknown
---actions or when the active source has no binding for `action`.
---@param action integer  one of input.LEFT / RIGHT / UP / DOWN / BTN1 / BTN2 / BTN3
---@return string?
function input.mapping_for(action) end

---The input source that most recently fired any bound action. Returns
---`input.SOURCE_KEYBOARD` ("keyboard") or `input.SOURCE_GAMEPAD`
---("gamepad"). Switches only when a *bound* input fires, so menu keys
---and idle activity don't flip it.
---@return string  matches one of input.SOURCE_KEYBOARD / input.SOURCE_GAMEPAD
function input.last_source() end

---Cursor position in game-space pixels (so it lines up with `gfx.*`
---coords regardless of window size or pixel-perfect scaling). Returns
---two values: `x, y`. When the cursor sits over the letterbox bars,
---the values fall outside `0..usagi.GAME_W` / `0..usagi.GAME_H` —
---bounds-check before treating them as in-game coords.
---@return integer x  game-space x in pixels
---@return integer y  game-space y in pixels
function input.mouse() end

---Returns true while the given mouse button is held.
---@param button integer  one of input.MOUSE_LEFT / input.MOUSE_RIGHT
---@return boolean
function input.mouse_held(button) end

---Returns true the frame the given mouse button first went down.
---@param button integer  one of input.MOUSE_LEFT / input.MOUSE_RIGHT
---@return boolean
function input.mouse_pressed(button) end

---Returns true the frame the given mouse button first went up
---(transitioned from held to released).
---@param button integer  one of input.MOUSE_LEFT / input.MOUSE_RIGHT
---@return boolean
function input.mouse_released(button) end

---Returns true while the given keyboard key is held.
---
---Direct keyboard reads bypass the keymap override and gamepad
---bindings — prefer `input.held(action)` for game actions players
---should be able to remap or play with a controller. Use this for dev
---hotkeys (toggling debug overlays, F-key shortcuts) and for
---keyboard-and-mouse-only games.
---@param key integer  one of the input.KEY_* constants
---@return boolean
function input.key_held(key) end

---Returns true the frame the given keyboard key first went down. See
---`input.key_held` for the bypass-the-keymap caveat.
---@param key integer  one of the input.KEY_* constants
---@return boolean
function input.key_pressed(key) end

---Returns true the frame the given keyboard key first went up
---(transitioned from held to released). See `input.key_held` for the
---bypass-the-keymap caveat.
---@param key integer  one of the input.KEY_* constants
---@return boolean
function input.key_released(key) end

---Show or hide the OS cursor over the game window. Persists until
---changed. Callable from `_init` so games can hide the cursor before
---the first frame draws (e.g. when rendering a custom in-game cursor).
---@param visible boolean  true to show, false to hide
function input.set_mouse_visible(visible) end

---Returns true when the OS cursor is currently shown over the window.
---Reflects the latest `input.set_mouse_visible` call synchronously, so
---it's safe to use as part of a toggle:
---`input.set_mouse_visible(not input.mouse_visible())`.
---@return boolean
function input.mouse_visible() end

---Engine-level info. The per-domain APIs (`gfx`, `input`) are top-level
---globals, not fields on this table.
---@class Usagi
---@field GAME_W      number   game render width in pixels
---@field GAME_H      number   game render height in pixels
---@field SPRITE_SIZE integer  side length, in pixels, of one cell in `sprites.png` (drives `gfx.spr` indexing)
---@field IS_DEV      boolean  true under `usagi dev`; false for `usagi run` and compiled binaries
---@field elapsed     number   wall-clock seconds since session start; updated once per frame before _update
usagi = {}

---Measures `text` in the bundled font and returns its rendered size
---in pixels. Returns two values: `width, height`. Available from any
---callback (`_init`, `_update`, `_draw`) — useful for pre-computing
---layout once in `_init` and reusing the result every frame.
---@param text string  string to measure
---@return integer width   pixel width
---@return integer height  pixel height (equals the font's line height)
function usagi.measure_text(text) end

---Persist a Lua table as JSON. Saves are per-game, namespaced by
---`game_id` from `_config()`. One file per game; nest your own
---structure inside (settings, run state, unlocks).
---@param t table   table to serialize. functions, userdata, NaN, and cycles error
function usagi.save(t) end

---Read the persisted save table back. Returns `nil` on first run
---(no save file). Idiomatic call: `state = usagi.load() or { ... defaults ... }`.
---@return table?
function usagi.load() end

---Config table returned by `_config()`. All fields optional except
---`game_id`, which is only required if you call `usagi.save` /
---`usagi.load`. Missing fields fall back to engine defaults.
---@class Usagi.Config
---@field name? string  display name. Window title, macOS .app bundle directory, and (slugged) archive/binary names on `usagi export` (default: project directory name)
---@field pixel_perfect? boolean false (default) = any scale that fits the window while preserving aspect ratio; true = integer scale only with letterbox bars
---@field game_id? string  reverse-DNS identifier (e.g. "com.you.mygame"), required for save/load
---@field icon? integer  1-based tile index into sprites.png to use as the window icon (same indexing as gfx.spr); omit for the default Usagi bunny
---@field game_width? number  game render width in pixels (default 320). Tested range 160..640
---@field game_height? number  game render height in pixels (default 180). Tested range 90..360
---@field sprite_size? integer  side length, in pixels, of one cell in sprites.png (default 16). Drives gfx.spr indexing, the tilepicker tool's grid, and the window-icon slicer. sprites.png must be a multiple of this value on both axes.

---Optional. Returns engine config read once before the window opens.
---Omit if the defaults are fine.
---@return Usagi.Config?
function _config() end

---Called once when the game starts. Use for loading assets and initializing state.
function _init() end

---Called every frame to update game state. Runs before _draw.
---@param dt number  delta-time: seconds since last frame
function _update(dt) end

---Called every frame to render. Runs after _update.
---@param dt number  delta-time: seconds since last frame
function _draw(dt) end

---@class Usagi.Vec2
---@field x number
---@field y number

---@class Usagi.Rect
---@field x number
---@field y number
---@field w number
---@field h number

---@class Usagi.Circ
---@field x number
---@field y number
---@field r number

---Drop-in math/geometry helpers. Pure Lua, no engine state. Source
---lives in `runtime/util.lua` — read it for full implementations or
---fork it if you want different semantics.
---@class Usagi.Util
util = {}

---Clamps `v` into `[lo, hi]`.
---@param v number
---@param lo number
---@param hi number
---@return number
function util.clamp(v, lo, hi) end

---Returns -1, 0, or 1 according to the sign of `v`.
---@param v number
---@return integer
function util.sign(v) end

---Half-up rounding to the nearest integer. Pixel snapping is the
---driving use case in 2D pixel-art games.
---@param v number
---@return integer
function util.round(v) end

---Moves `current` toward `target` by at most `max_delta`, never
---overshooting. Per-frame smoothing primitive — pass a delta
---scaled by `dt` for frame-rate independence.
---@param current number
---@param target number
---@param max_delta number
---@return number
function util.approach(current, target, max_delta) end

---Linear interpolation. `t = 0` returns `a`, `t = 1` returns `b`.
---Values of `t` outside `[0, 1]` extrapolate (no clamping).
---@param a number
---@param b number
---@param t number
---@return number
function util.lerp(a, b, t) end

---Wraps `v` into `[lo, hi)`. Useful for cyclic values like angles or
---looped indexing. Works for negative `v`: `util.wrap(-1, 0, 4) == 3`.
---@param v number
---@param lo number
---@param hi number
---@return number
function util.wrap(v, lo, hi) end

---Boolean from time. Toggles `hz` times per second — the on/off
---interval is `1/hz` seconds. For invincibility flicker, UI blinks,
---low-health warnings.
---@param t number  seconds
---@param hz number  toggles per second
---@return boolean
function util.flash(t, hz) end

---Normalizes a `{x, y}` vector to unit length. Returns a new table;
---the input is unchanged. A zero vector returns `{x = 0, y = 0}`.
---@param v Usagi.Vec2
---@return Usagi.Vec2
function util.vec_normalize(v) end

---Distance between two `{x, y}` points.
---@param a Usagi.Vec2
---@param b Usagi.Vec2
---@return number
function util.vec_dist(a, b) end

---Squared distance between two `{x, y}` points. Cheaper than
---`vec_dist` (skips the sqrt); use for "is X closer than Y?" by
---comparing against `r * r`.
---@param a Usagi.Vec2
---@param b Usagi.Vec2
---@return number
function util.vec_dist_sq(a, b) end

---Builds a vector at `angle` (radians) with magnitude `len`. `len`
---defaults to 1 for a unit vector. Pair with `math.atan(dy, dx)` to
---convert any direction into a velocity.
---@param angle number  radians
---@param len? number   magnitude (default 1)
---@return Usagi.Vec2
function util.vec_from_angle(angle, len) end

---True when the `{x, y}` point is inside the rect `{x, y, w, h}`.
---Half-open: left/top edges are inside, right/bottom edges are
---outside. Matches typical sprite-rect hit testing.
---@param p Usagi.Vec2
---@param r Usagi.Rect
---@return boolean
function util.point_in_rect(p, r) end

---True when the `{x, y}` point is strictly inside the circle
---`{x, y, r}`. Points on the boundary are considered outside.
---@param p Usagi.Vec2
---@param c Usagi.Circ
---@return boolean
function util.point_in_circ(p, c) end

---True when the two AABBs share interior area. Edge-adjacent rects
---are considered non-overlapping.
---@param a Usagi.Rect
---@param b Usagi.Rect
---@return boolean
function util.rect_overlap(a, b) end

---True when the two circles overlap. Tangent circles are
---considered non-overlapping.
---@param a Usagi.Circ
---@param b Usagi.Circ
---@return boolean
function util.circ_overlap(a, b) end

---True when a circle and a rect overlap. Uses the closest-point
---method: clamp the circle center to the rect, test distance.
---@param c Usagi.Circ
---@param r Usagi.Rect
---@return boolean
function util.circ_rect_overlap(c, r) end

---Engine-level juice primitives: hitstop, screen shake, flash, and
---slow-motion. Each call sets per-session state that decays once per
---frame. Stacking rule across all four: longer duration wins; for
---the magnitude param, the latest call wins. Spam-calling is safe.
effect = {}

---Freezes the game's `_update` loop for `time` seconds. `_draw` keeps
---running so the world stays on-screen. The classic juice trick for
---weighty hits: pair with `effect.screen_shake` and `effect.flash` on
---impact. If a longer hitstop is already in flight, this call is a
---no-op (longer wins).
---@param time number  seconds to freeze update
function effect.hitstop(time) end

---Shakes the rendered view for `time` seconds with up to `intensity`
---game-pixel offset. Magnitude decays linearly to zero across the
---duration. The shake is applied to the RT-to-screen blit, so
---overlays drawn outside the world (error, REC indicator) stay
---stable.
---@param time      number  seconds to shake
---@param intensity number  maximum offset in game pixels (try 2-6)
function effect.screen_shake(time, intensity) end

---Flashes a full-screen overlay of palette color `color` over the
---rendered view for `time` seconds. Alpha decays linearly from
---opaque to transparent. White on hits, red on damage, etc.
---@param time  number   seconds the flash is visible
---@param color integer  a gfx.COLOR_* constant
function effect.flash(time, color) end

---Scales the `dt` passed to `_update` for `time` seconds. `scale=0.5`
---is half-speed; `scale=0` freezes update (use `effect.hitstop` for
---that explicitly); `scale>1` plays faster. Wall-clock decay is
---unaffected; the slow_mo timer itself counts down at real time.
---@param time  number  seconds the scale is applied
---@param scale number  dt multiplier; 0..1 for slow, >1 for fast
function effect.slow_mo(time, scale) end
