Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/g-js-api/G.js/llms.txt

Use this file to discover all available pages before exploring further.

G.js exposes a clean event system that maps directly onto Geometry Dash’s trigger layer. Every event is a GJsEvent value that you pass to on(), which wires up a GD trigger so your callback group fires automatically whenever the event fires during gameplay. This means you never have to manually manage touch triggers, collision triggers, or on-death triggers — just describe what you want to react to and G.js emits the correct objects for you.

on(event, callback)

on is the entry point for the entire event system. Call it at the top level of your script (or inside a trigger function) to register a listener:
on(touch(), trigger_function(() => {
  // runs every time the player touches the screen
}));
event
GJsEvent
Any value returned by one of the event constructor functions below.
callback
TriggerFunctionGroup | $group
A trigger function (from trigger_function(...)) or a raw group to call when the event fires.

Touch Events

touch(dual_side?)

Fires when the player touches the screen.
on(touch(), trigger_function(() => {
  // player pressed the screen
}));

on(touch(true), trigger_function(() => {
  // dual-mode: only the dual side
}));
dual_side
boolean
default:"false"
When true, only listens to input on the dual side of the screen.

touch_end(dual_side?)

Fires when the player releases the screen.
on(touch_end(), trigger_function(() => {
  // player lifted their finger
}));
dual_side
boolean
default:"false"
When true, only listens on the dual side.

Collision Events

collision(a, b, P1?, P2?)

Fires when two collision blocks start overlapping.
const wall  = block(1);
const spike = block(2);

on(collision(wall, spike), trigger_function(() => {
  // wall block touched spike block
}));
a
$block
First collision block.
b
$block
Second collision block.
P1
boolean
When true, Player 1 acts as block a.
P2
boolean
When true, Player 2 acts as block a.

collision_exit(a, b, P1?, P2?)

Fires when the two blocks stop overlapping. Takes the same parameters as collision.
on(collision_exit(wall, spike), trigger_function(() => {
  // blocks are no longer touching
}));

Player Events

death()

Fires when the player dies.
on(death(), trigger_function(() => {
  // reset counters, show UI, etc.
}));

x_position(position)

Fires once when the player’s X coordinate reaches a specific position.
on(x_position(600), trigger_function(() => {
  // player reached x = 600
}));
position
number
The X coordinate (in GD units) that triggers the event.

Item / Count Events

count(it, hits, multi?)

Fires when a counter (item) reaches a specific value.
const coins = counter(0);

on(count(coins.item, 3), trigger_function(() => {
  // player collected 3 coins
}));
it
any
The item ID to watch. Retrieve it from your_counter.item.
hits
number
The number the item must reach to fire the event.
multi
boolean
When true, the event fires every time the value hits the target (not just once).

Frame Events

G.js distinguishes between ticks (fixed 1/240 s intervals, independent of frame rate) and render frames (variable, depends on the player’s FPS setting).

frame()

Fires every game tick — exactly once every 1/240 second, regardless of frame rate. Use this for deterministic, physics-accurate logic.
on(frame(), trigger_function(() => {
  // runs 240 times per second
}));

render_frame()

Fires every rendered frame. The interval varies with the player’s FPS settings. Use this for visual-only effects where exact timing doesn’t matter.
on(render_frame(), trigger_function(() => {
  // runs at the player's current FPS
}));
Prefer frame() for gameplay logic (counters, movement, collision responses) and render_frame() for purely cosmetic effects. The control-flow equivalents frame_loop() and render_frame_loop() provide the same distinction with an easier stop mechanism — see the Control Flow guide.

Custom Event Trigger

event(ev, extra_id?, extra_id2?)

Wraps GD’s Event trigger, which lets you fire named events from elsewhere in the level and listen to them here.
// Define a custom event identifier
const MY_EVENT = 1;

// Listen for it
on(event(MY_EVENT), trigger_function(() => {
  // fired whenever the event trigger with id 1 activates
}));
ev
any
The event identifier or event object to listen to.
extra_id
number
Optional extra ID 1 for the Event trigger.
extra_id2
number
Optional extra ID 2 for the Event trigger.

Gamescene Input Controls

gamescene() returns a Gamescene object that abstracts the in-game button inputs, making it easy to bind logic to the jump/action buttons without dealing with raw touch coordinates.
const gs = gamescene();

on(gs.button_a(), trigger_function(() => {
  // player pressed jump / button A
}));

on(gs.button_b(), trigger_function(() => {
  // player pressed the secondary button (B)
}));

on(gs.button_a_end(), trigger_function(() => {
  // player released button A
}));

on(gs.button_b_end(), trigger_function(() => {
  // player released button B
}));
The Gamescene interface:
Property / MethodTypeDescription
button_a()GJsEventButton A (jump) pressed.
button_b()GJsEventButton B pressed.
button_a_end()GJsEventButton A released.
button_b_end()GJsEventButton B released.
hidden_group$groupA group that is hidden by the gamescene context.

Examples

Touch to Spawn a Group

import '@g-js-api/g.js';

await $.exportConfig({ type: 'savefile', options: { info: true } });

const flash_group = unknown_g();

on(touch(), trigger_function(() => {
  flash_group.call();
}));

Collision-based Logic

import '@g-js-api/g.js';

await $.exportConfig({ type: 'savefile' });

const platform = block(1);
const player_block = block(2);
const hp = counter(3);

// Damage the player when they hit a spike
on(collision(player_block, platform), trigger_function(() => {
  hp.subtract(1);
  hp.if_is(EQUAL_TO, 0, trigger_function(() => {
    // game over
  }));
}));

X-Position Sequence Trigger

import '@g-js-api/g.js';

await $.exportConfig({ type: 'savefile' });

const boss_group = group(5);

// Start boss fight when player reaches x=1200
on(x_position(1200), trigger_function(() => {
  boss_group.call();
}));

Frame Loop vs. Frame Event

import '@g-js-api/g.js';

await $.exportConfig({ type: 'savefile' });

const tick_count = counter(0);

// Option 1: use the frame() event
on(frame(), trigger_function(() => {
  tick_count.add(1);
}));

// Option 2: use frame_loop from control-flow (easier to stop)
const loop = frame_loop(trigger_function(() => {
  tick_count.add(1);
}));

// stop the loop after 5 seconds
call_with_delay(5, trigger_function(() => {
  loop.stop();
}));

Control Flow

frame_loop, for_loop, and sequence for structured timing.

Counters

Track game state with item-backed counters.

Events API

Full API reference for all event functions.

Groups & Colors

How groups, colors, and blocks map to GD IDs.

Build docs developers (and LLMs) love