Runtime value inspection via the F4 Debug Inspector.
The debug system allows you to register game variables for live editing and monitoring. Press F4 to open the Debug Inspector during development.
Features:
Live value editing (sliders, color pickers)
Read-only watches
Grouped organization
Frame control (pause, step, time scale)
Zero overhead in release builds
Register editable values in init(). The debug panel will show controls for these values.
Registers an editable 32-bit signed integer.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_i32(name_ptr: *const u8, name_len: u32, ptr: *const i32)
}
NCZX_IMPORT void debug_register_i32(const uint8_t* name_ptr, uint32_t name_len, const int32_t* ptr);
pub extern fn debug_register_i32(name_ptr: [*]const u8, name_len: u32, ptr: *const i32) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut ENEMY_COUNT: i32 = 5;
fn init() {
unsafe {
debug_register_i32(b"Enemy Count".as_ptr(), 11, &ENEMY_COUNT);
}
}
}
static int32_t enemy_count = 5;
NCZX_EXPORT void init(void) {
debug_register_i32("Enemy Count", 11, &enemy_count);
}
var enemy_count: i32 = 5;
export fn init() void {
debug_register_i32("Enemy Count", 11, &enemy_count);
}
Registers an editable 32-bit float.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_f32(name_ptr: *const u8, name_len: u32, ptr: *const f32)
}
NCZX_IMPORT void debug_register_f32(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
pub extern fn debug_register_f32(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut GRAVITY: f32 = 9.8;
static mut JUMP_FORCE: f32 = 15.0;
fn init() {
unsafe {
debug_register_f32(b"Gravity".as_ptr(), 7, &GRAVITY);
debug_register_f32(b"Jump Force".as_ptr(), 10, &JUMP_FORCE);
}
}
}
static float gravity = 9.8f;
static float jump_force = 15.0f;
NCZX_EXPORT void init(void) {
debug_register_f32("Gravity", 7, &gravity);
debug_register_f32("Jump Force", 10, &jump_force);
}
var gravity: f32 = 9.8;
var jump_force: f32 = 15.0;
export fn init() void {
debug_register_f32("Gravity", 7, &gravity);
debug_register_f32("Jump Force", 10, &jump_force);
}
Registers an editable boolean (checkbox).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_bool(name_ptr: *const u8, name_len: u32, ptr: *const u8)
}
NCZX_IMPORT void debug_register_bool(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
pub extern fn debug_register_bool(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut GOD_MODE: u8 = 0; // 0 = false, 1 = true
fn init() {
unsafe {
debug_register_bool(b"God Mode".as_ptr(), 8, &GOD_MODE);
}
}
}
static uint8_t god_mode = 0; // 0 = false, 1 = true
NCZX_EXPORT void init(void) {
debug_register_bool("God Mode", 8, &god_mode);
}
var god_mode: u8 = 0; // 0 = false, 1 = true
export fn init() void {
debug_register_bool("God Mode", 8, &god_mode);
}
Registers unsigned integers.
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_u8(name_ptr: *const u8, name_len: u32, ptr: *const u8)
fn debug_register_u16(name_ptr: *const u8, name_len: u32, ptr: *const u16)
fn debug_register_u32(name_ptr: *const u8, name_len: u32, ptr: *const u32)
}
NCZX_IMPORT void debug_register_u8(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
NCZX_IMPORT void debug_register_u16(const uint8_t* name_ptr, uint32_t name_len, const uint16_t* ptr);
NCZX_IMPORT void debug_register_u32(const uint8_t* name_ptr, uint32_t name_len, const uint32_t* ptr);
pub extern fn debug_register_u8(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
pub extern fn debug_register_u16(name_ptr: [*]const u8, name_len: u32, ptr: *const u16) void;
pub extern fn debug_register_u32(name_ptr: [*]const u8, name_len: u32, ptr: *const u32) void;
Registers signed integers.
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_i8(name_ptr: *const u8, name_len: u32, ptr: *const i8)
fn debug_register_i16(name_ptr: *const u8, name_len: u32, ptr: *const i16)
}
NCZX_IMPORT void debug_register_i8(const uint8_t* name_ptr, uint32_t name_len, const int8_t* ptr);
NCZX_IMPORT void debug_register_i16(const uint8_t* name_ptr, uint32_t name_len, const int16_t* ptr);
pub extern fn debug_register_i8(name_ptr: [*]const u8, name_len: u32, ptr: *const i8) void;
pub extern fn debug_register_i16(name_ptr: [*]const u8, name_len: u32, ptr: *const i16) void;
Registers an integer with min/max bounds (slider).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_i32_range(
name_ptr: *const u8, name_len: u32,
ptr: *const i32,
min: i32, max: i32
)
}
NCZX_IMPORT void debug_register_i32_range(
const uint8_t* name_ptr, uint32_t name_len,
const int32_t* ptr,
int32_t min, int32_t max
);
pub extern fn debug_register_i32_range(
name_ptr: [*]const u8, name_len: u32,
ptr: *const i32,
min: i32, max: i32
) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut DIFFICULTY: i32 = 2;
fn init() {
unsafe {
debug_register_i32_range(b"Difficulty".as_ptr(), 10, &DIFFICULTY, 1, 5);
}
}
}
static int32_t difficulty = 2;
NCZX_EXPORT void init(void) {
debug_register_i32_range("Difficulty", 10, &difficulty, 1, 5);
}
var difficulty: i32 = 2;
export fn init() void {
debug_register_i32_range("Difficulty", 10, &difficulty, 1, 5);
}
Registers a float with min/max bounds.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_f32_range(
name_ptr: *const u8, name_len: u32,
ptr: *const f32,
min: f32, max: f32
)
}
NCZX_IMPORT void debug_register_f32_range(
const uint8_t* name_ptr, uint32_t name_len,
const float* ptr,
float min, float max
);
pub extern fn debug_register_f32_range(
name_ptr: [*]const u8, name_len: u32,
ptr: *const f32,
min: f32, max: f32
) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut PLAYER_SPEED: f32 = 5.0;
fn init() {
unsafe {
debug_register_f32_range(b"Speed".as_ptr(), 5, &PLAYER_SPEED, 0.0, 20.0);
}
}
}
static float player_speed = 5.0f;
NCZX_EXPORT void init(void) {
debug_register_f32_range("Speed", 5, &player_speed, 0.0f, 20.0f);
}
var player_speed: f32 = 5.0;
export fn init() void {
debug_register_f32_range("Speed", 5, &player_speed, 0.0, 20.0);
}
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_u8_range(name_ptr: *const u8, name_len: u32, ptr: *const u8, min: u32, max: u32)
fn debug_register_u16_range(name_ptr: *const u8, name_len: u32, ptr: *const u16, min: u32, max: u32)
fn debug_register_i16_range(name_ptr: *const u8, name_len: u32, ptr: *const i16, min: i32, max: i32)
}
NCZX_IMPORT void debug_register_u8_range(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr, uint32_t min, uint32_t max);
NCZX_IMPORT void debug_register_u16_range(const uint8_t* name_ptr, uint32_t name_len, const uint16_t* ptr, uint32_t min, uint32_t max);
NCZX_IMPORT void debug_register_i16_range(const uint8_t* name_ptr, uint32_t name_len, const int16_t* ptr, int32_t min, int32_t max);
pub extern fn debug_register_u8_range(name_ptr: [*]const u8, name_len: u32, ptr: *const u8, min: u32, max: u32) void;
pub extern fn debug_register_u16_range(name_ptr: [*]const u8, name_len: u32, ptr: *const u16, min: u32, max: u32) void;
pub extern fn debug_register_i16_range(name_ptr: [*]const u8, name_len: u32, ptr: *const i16, min: i32, max: i32) void;
Registers a 2D vector (two f32s).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_vec2(name_ptr: *const u8, name_len: u32, ptr: *const f32)
}
NCZX_IMPORT void debug_register_vec2(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
pub extern fn debug_register_vec2(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut PLAYER_POS: [f32; 2] = [0.0, 0.0];
fn init() {
unsafe {
debug_register_vec2(b"Player Pos".as_ptr(), 10, PLAYER_POS.as_ptr());
}
}
}
static float player_pos[2] = {0.0f, 0.0f};
NCZX_EXPORT void init(void) {
debug_register_vec2("Player Pos", 10, player_pos);
}
var player_pos: [2]f32 = .{0.0, 0.0};
export fn init() void {
debug_register_vec2("Player Pos", 10, &player_pos);
}
Registers a 3D vector (three f32s).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_vec3(name_ptr: *const u8, name_len: u32, ptr: *const f32)
}
NCZX_IMPORT void debug_register_vec3(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
pub extern fn debug_register_vec3(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
Registers a rectangle (x, y, width, height as four f32s).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_rect(name_ptr: *const u8, name_len: u32, ptr: *const f32)
}
NCZX_IMPORT void debug_register_rect(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
pub extern fn debug_register_rect(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
Registers a color (RGBA as four u8s).
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_color(name_ptr: *const u8, name_len: u32, ptr: *const u8)
}
NCZX_IMPORT void debug_register_color(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
pub extern fn debug_register_color(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut TINT_COLOR: [u8; 4] = [255, 255, 255, 255];
fn init() {
unsafe {
debug_register_color(b"Tint".as_ptr(), 4, TINT_COLOR.as_ptr());
}
}
}
static uint8_t tint_color[4] = {255, 255, 255, 255};
NCZX_EXPORT void init(void) {
debug_register_color("Tint", 4, tint_color);
}
var tint_color: [4]u8 = .{255, 255, 255, 255};
export fn init() void {
debug_register_color("Tint", 4, &tint_color);
}
For games using fixed-point math.
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_fixed_i16_q8(name_ptr: *const u8, name_len: u32, ptr: *const i16)
fn debug_register_fixed_i32_q8(name_ptr: *const u8, name_len: u32, ptr: *const i32)
fn debug_register_fixed_i32_q16(name_ptr: *const u8, name_len: u32, ptr: *const i32)
fn debug_register_fixed_i32_q24(name_ptr: *const u8, name_len: u32, ptr: *const i32)
}
NCZX_IMPORT void debug_register_fixed_i16_q8(const uint8_t* name_ptr, uint32_t name_len, const int16_t* ptr);
NCZX_IMPORT void debug_register_fixed_i32_q8(const uint8_t* name_ptr, uint32_t name_len, const int32_t* ptr);
NCZX_IMPORT void debug_register_fixed_i32_q16(const uint8_t* name_ptr, uint32_t name_len, const int32_t* ptr);
NCZX_IMPORT void debug_register_fixed_i32_q24(const uint8_t* name_ptr, uint32_t name_len, const int32_t* ptr);
pub extern fn debug_register_fixed_i16_q8(name_ptr: [*]const u8, name_len: u32, ptr: *const i16) void;
pub extern fn debug_register_fixed_i32_q8(name_ptr: [*]const u8, name_len: u32, ptr: *const i32) void;
pub extern fn debug_register_fixed_i32_q16(name_ptr: [*]const u8, name_len: u32, ptr: *const i32) void;
pub extern fn debug_register_fixed_i32_q24(name_ptr: [*]const u8, name_len: u32, ptr: *const i32) void;
Watches display values without allowing editing.
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_watch_i8(name_ptr: *const u8, name_len: u32, ptr: *const i8)
fn debug_watch_i16(name_ptr: *const u8, name_len: u32, ptr: *const i16)
fn debug_watch_i32(name_ptr: *const u8, name_len: u32, ptr: *const i32)
fn debug_watch_u8(name_ptr: *const u8, name_len: u32, ptr: *const u8)
fn debug_watch_u16(name_ptr: *const u8, name_len: u32, ptr: *const u16)
fn debug_watch_u32(name_ptr: *const u8, name_len: u32, ptr: *const u32)
fn debug_watch_f32(name_ptr: *const u8, name_len: u32, ptr: *const f32)
fn debug_watch_bool(name_ptr: *const u8, name_len: u32, ptr: *const u8)
fn debug_watch_vec2(name_ptr: *const u8, name_len: u32, ptr: *const f32)
fn debug_watch_vec3(name_ptr: *const u8, name_len: u32, ptr: *const f32)
fn debug_watch_rect(name_ptr: *const u8, name_len: u32, ptr: *const f32)
fn debug_watch_color(name_ptr: *const u8, name_len: u32, ptr: *const u8)
}
NCZX_IMPORT void debug_watch_i8(const uint8_t* name_ptr, uint32_t name_len, const int8_t* ptr);
NCZX_IMPORT void debug_watch_i16(const uint8_t* name_ptr, uint32_t name_len, const int16_t* ptr);
NCZX_IMPORT void debug_watch_i32(const uint8_t* name_ptr, uint32_t name_len, const int32_t* ptr);
NCZX_IMPORT void debug_watch_u8(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
NCZX_IMPORT void debug_watch_u16(const uint8_t* name_ptr, uint32_t name_len, const uint16_t* ptr);
NCZX_IMPORT void debug_watch_u32(const uint8_t* name_ptr, uint32_t name_len, const uint32_t* ptr);
NCZX_IMPORT void debug_watch_f32(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
NCZX_IMPORT void debug_watch_bool(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
NCZX_IMPORT void debug_watch_vec2(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
NCZX_IMPORT void debug_watch_vec3(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
NCZX_IMPORT void debug_watch_rect(const uint8_t* name_ptr, uint32_t name_len, const float* ptr);
NCZX_IMPORT void debug_watch_color(const uint8_t* name_ptr, uint32_t name_len, const uint8_t* ptr);
pub extern fn debug_watch_i8(name_ptr: [*]const u8, name_len: u32, ptr: *const i8) void;
pub extern fn debug_watch_i16(name_ptr: [*]const u8, name_len: u32, ptr: *const i16) void;
pub extern fn debug_watch_i32(name_ptr: [*]const u8, name_len: u32, ptr: *const i32) void;
pub extern fn debug_watch_u8(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
pub extern fn debug_watch_u16(name_ptr: [*]const u8, name_len: u32, ptr: *const u16) void;
pub extern fn debug_watch_u32(name_ptr: [*]const u8, name_len: u32, ptr: *const u32) void;
pub extern fn debug_watch_f32(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
pub extern fn debug_watch_bool(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
pub extern fn debug_watch_vec2(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
pub extern fn debug_watch_vec3(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
pub extern fn debug_watch_rect(name_ptr: [*]const u8, name_len: u32, ptr: *const f32) void;
pub extern fn debug_watch_color(name_ptr: [*]const u8, name_len: u32, ptr: *const u8) void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
static mut FRAME_COUNT: u32 = 0;
static mut FPS: f32 = 0.0;
fn init() {
unsafe {
debug_watch_u32(b"Frame".as_ptr(), 5, &FRAME_COUNT);
debug_watch_f32(b"FPS".as_ptr(), 3, &FPS);
}
}
}
static uint32_t frame_count = 0;
static float fps = 0.0f;
NCZX_EXPORT void init(void) {
debug_watch_u32("Frame", 5, &frame_count);
debug_watch_f32("FPS", 3, &fps);
}
var frame_count: u32 = 0;
var fps: f32 = 0.0;
export fn init() void {
debug_watch_u32("Frame", 5, &frame_count);
debug_watch_f32("FPS", 3, &fps);
}
Starts a collapsible group in the debug panel.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_group_begin(name_ptr: *const u8, name_len: u32)
}
NCZX_IMPORT void debug_group_begin(const uint8_t* name_ptr, uint32_t name_len);
pub extern fn debug_group_begin(name_ptr: [*]const u8, name_len: u32) void;
Ends the current group.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_group_end()
}
NCZX_IMPORT void debug_group_end(void);
pub extern fn debug_group_end() void;
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn init() {
unsafe {
debug_group_begin(b"Player".as_ptr(), 6);
debug_register_vec3(b"Position".as_ptr(), 8, PLAYER_POS.as_ptr());
debug_register_f32(b"Health".as_ptr(), 6, &PLAYER_HEALTH);
debug_register_f32(b"Speed".as_ptr(), 5, &PLAYER_SPEED);
debug_group_end();
debug_group_begin(b"Physics".as_ptr(), 7);
debug_register_f32(b"Gravity".as_ptr(), 7, &GRAVITY);
debug_register_f32(b"Friction".as_ptr(), 8, &FRICTION);
debug_group_end();
}
}
}
NCZX_EXPORT void init(void) {
debug_group_begin("Player", 6);
debug_register_vec3("Position", 8, player_pos);
debug_register_f32("Health", 6, &player_health);
debug_register_f32("Speed", 5, &player_speed);
debug_group_end();
debug_group_begin("Physics", 7);
debug_register_f32("Gravity", 7, &gravity);
debug_register_f32("Friction", 8, &friction);
debug_group_end();
}
export fn init() void {
debug_group_begin("Player", 6);
debug_register_vec3("Position", 8, &player_pos);
debug_register_f32("Health", 6, &player_health);
debug_register_f32("Speed", 5, &player_speed);
debug_group_end();
debug_group_begin("Physics", 7);
debug_register_f32("Gravity", 7, &gravity);
debug_register_f32("Friction", 8, &friction);
debug_group_end();
}
Actions create buttons in the debug panel that trigger game functions when clicked. They’re useful for testing scenarios, spawning entities, or triggering events during development.
Registers a simple action button with no parameters.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_register_action(
name_ptr: *const u8, name_len: u32,
func_name_ptr: *const u8, func_name_len: u32
)
}
NCZX_IMPORT void debug_register_action(
const uint8_t* name_ptr, uint32_t name_len,
const uint8_t* func_name_ptr, uint32_t func_name_len
);
pub extern fn debug_register_action(
name_ptr: [*]const u8, name_len: u32,
func_name_ptr: [*]const u8, func_name_len: u32
) void;
Parameters:
Name Type Description
name_ptr *const u8Pointer to button label string
name_len u32Length of button label
func_name_ptr *const u8Pointer to exported WASM function name
func_name_len u32Length of function name
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
#[no_mangle]
pub extern "C" fn spawn_enemy() {
// Called when button is clicked
unsafe {
ENEMY_COUNT += 1;
}
}
#[no_mangle]
pub extern "C" fn reset_game() {
// Reset all game state
unsafe {
PLAYER_X = 0.0;
PLAYER_Y = 0.0;
ENEMY_COUNT = 0;
}
}
fn init() {
unsafe {
debug_group_begin(b"Actions".as_ptr(), 7);
debug_register_action(
b"Spawn Enemy".as_ptr(), 11,
b"spawn_enemy".as_ptr(), 11
);
debug_register_action(
b"Reset Game".as_ptr(), 10,
b"reset_game".as_ptr(), 10
);
debug_group_end();
}
}
}
NCZX_EXPORT void spawn_enemy(void) {
/* Called when button is clicked */
enemy_count++;
}
NCZX_EXPORT void reset_game(void) {
/* Reset all game state */
player_x = 0.0f;
player_y = 0.0f;
enemy_count = 0;
}
NCZX_EXPORT void init(void) {
debug_group_begin("Actions", 7);
debug_register_action("Spawn Enemy", 11, "spawn_enemy", 11);
debug_register_action("Reset Game", 10, "reset_game", 10);
debug_group_end();
}
export fn spawn_enemy() void {
// Called when button is clicked
enemy_count += 1;
}
export fn reset_game() void {
// Reset all game state
player_x = 0.0;
player_y = 0.0;
enemy_count = 0;
}
export fn init() void {
debug_group_begin("Actions", 7);
debug_register_action("Spawn Enemy", 11, "spawn_enemy", 11);
debug_register_action("Reset Game", 10, "reset_game", 10);
debug_group_end();
}
Begins building an action with parameters. Use with debug_action_param_* functions and debug_action_end() to create actions with input fields.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_action_begin(
name_ptr: *const u8, name_len: u32,
func_name_ptr: *const u8, func_name_len: u32
)
}
NCZX_IMPORT void debug_action_begin(
const uint8_t* name_ptr, uint32_t name_len,
const uint8_t* func_name_ptr, uint32_t func_name_len
);
pub extern fn debug_action_begin(
name_ptr: [*]const u8, name_len: u32,
func_name_ptr: [*]const u8, func_name_len: u32
) void;
Parameters:
Name Type Description
name_ptr *const u8Pointer to button label string
name_len u32Length of button label
func_name_ptr *const u8Pointer to exported WASM function name
func_name_len u32Length of function name
Adds an i32 parameter input field to the pending action.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_action_param_i32(name_ptr: *const u8, name_len: u32, default_value: i32)
}
NCZX_IMPORT void debug_action_param_i32(
const uint8_t* name_ptr, uint32_t name_len,
int32_t default_value
);
pub extern fn debug_action_param_i32(
name_ptr: [*]const u8, name_len: u32,
default_value: i32
) void;
Parameters:
Name Type Description
name_ptr *const u8Pointer to parameter label string
name_len u32Length of parameter label
default_value i32Default value shown in input field
Adds an f32 parameter input field to the pending action.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_action_param_f32(name_ptr: *const u8, name_len: u32, default_value: f32)
}
NCZX_IMPORT void debug_action_param_f32(
const uint8_t* name_ptr, uint32_t name_len,
float default_value
);
pub extern fn debug_action_param_f32(
name_ptr: [*]const u8, name_len: u32,
default_value: f32
) void;
Parameters:
Name Type Description
name_ptr *const u8Pointer to parameter label string
name_len u32Length of parameter label
default_value f32Default value shown in input field
Completes the action registration started with debug_action_begin().
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_action_end()
}
NCZX_IMPORT void debug_action_end(void);
pub extern fn debug_action_end() void;
Complete Action with Parameters Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
// Function called when action button is clicked
// Parameters are passed in the order they were registered
#[no_mangle]
pub extern "C" fn spawn_enemies_at(count: i32, x: f32, y: f32) {
for _ in 0..count {
unsafe {
// Spawn enemy at specified position
spawn_enemy(x, y);
}
}
}
#[no_mangle]
pub extern "C" fn teleport_player(x: f32, y: f32) {
unsafe {
PLAYER_X = x;
PLAYER_Y = y;
}
}
fn init() {
unsafe {
debug_group_begin(b"Actions".as_ptr(), 7);
// Action with parameters
debug_action_begin(
b"Spawn Enemies".as_ptr(), 13,
b"spawn_enemies_at".as_ptr(), 16
);
debug_action_param_i32(b"Count".as_ptr(), 5, 3);
debug_action_param_f32(b"X".as_ptr(), 1, 100.0);
debug_action_param_f32(b"Y".as_ptr(), 1, 100.0);
debug_action_end();
// Another parameterized action
debug_action_begin(
b"Teleport Player".as_ptr(), 15,
b"teleport_player".as_ptr(), 15
);
debug_action_param_f32(b"X".as_ptr(), 1, 480.0);
debug_action_param_f32(b"Y".as_ptr(), 1, 270.0);
debug_action_end();
debug_group_end();
}
}
}
/* Function called when action button is clicked */
/* Parameters are passed in the order they were registered */
NCZX_EXPORT void spawn_enemies_at(int32_t count, float x, float y) {
for (int i = 0; i < count; i++) {
spawn_enemy(x, y);
}
}
NCZX_EXPORT void teleport_player(float x, float y) {
player_x = x;
player_y = y;
}
NCZX_EXPORT void init(void) {
debug_group_begin("Actions", 7);
/* Action with parameters */
debug_action_begin("Spawn Enemies", 13, "spawn_enemies_at", 16);
debug_action_param_i32("Count", 5, 3);
debug_action_param_f32("X", 1, 100.0f);
debug_action_param_f32("Y", 1, 100.0f);
debug_action_end();
/* Another parameterized action */
debug_action_begin("Teleport Player", 15, "teleport_player", 15);
debug_action_param_f32("X", 1, 480.0f);
debug_action_param_f32("Y", 1, 270.0f);
debug_action_end();
debug_group_end();
}
// Function called when action button is clicked
// Parameters are passed in the order they were registered
export fn spawn_enemies_at(count: i32, x: f32, y: f32) void {
var i: i32 = 0;
while (i < count) : (i += 1) {
spawn_enemy(x, y);
}
}
export fn teleport_player(x: f32, y: f32) void {
player_x = x;
player_y = y;
}
export fn init() void {
debug_group_begin("Actions", 7);
// Action with parameters
debug_action_begin("Spawn Enemies", 13, "spawn_enemies_at", 16);
debug_action_param_i32("Count", 5, 3);
debug_action_param_f32("X", 1, 100.0);
debug_action_param_f32("Y", 1, 100.0);
debug_action_end();
// Another parameterized action
debug_action_begin("Teleport Player", 15, "teleport_player", 15);
debug_action_param_f32("X", 1, 480.0);
debug_action_param_f32("Y", 1, 270.0);
debug_action_end();
debug_group_end();
}
Check if game is paused via debug panel.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_is_paused() -> i32
}
NCZX_IMPORT int32_t debug_is_paused(void);
pub extern fn debug_is_paused() i32;
Returns: 1 if paused, 0 otherwise
Get the current time scale.
Signature:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn debug_get_time_scale() -> f32
}
NCZX_IMPORT float debug_get_time_scale(void);
pub extern fn debug_get_time_scale() f32;
Returns: Time scale (1.0 = normal, 0.5 = half speed, 2.0 = double)
Example:
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
fn update() {
unsafe {
if debug_is_paused() != 0 {
return; // Skip update when paused
}
let dt = delta_time() * debug_get_time_scale();
// Use scaled delta time
}
}
}
NCZX_EXPORT void update(void) {
if (debug_is_paused() != 0) {
return; // Skip update when paused
}
float dt = delta_time() * debug_get_time_scale();
// Use scaled delta time
}
export fn update() void {
if (debug_is_paused() != 0) {
return; // Skip update when paused
}
const dt = delta_time() * debug_get_time_scale();
// Use scaled delta time
}
Key Action
F3 Toggle Runtime Stats Panel
F4 Toggle Debug Inspector
F5 Pause/unpause
F6 Step one frame (while paused)
F7 Decrease time scale
F8 Increase time scale
Rust
C/C++
Zig
#![allow(unused)]
fn main() {
// Game state
static mut PLAYER_X: f32 = 0.0;
static mut PLAYER_Y: f32 = 0.0;
static mut PLAYER_VEL_X: f32 = 0.0;
static mut PLAYER_VEL_Y: f32 = 0.0;
static mut PLAYER_HEALTH: f32 = 100.0;
// Tuning parameters
static mut MOVE_SPEED: f32 = 5.0;
static mut JUMP_FORCE: f32 = 12.0;
static mut GRAVITY: f32 = 25.0;
static mut FRICTION: f32 = 0.9;
// Debug
static mut GOD_MODE: u8 = 0;
static mut SHOW_HITBOXES: u8 = 0;
static mut ENEMY_COUNT: i32 = 5;
fn init() {
unsafe {
// Player group
debug_group_begin(b"Player".as_ptr(), 6);
debug_watch_f32(b"X".as_ptr(), 1, &PLAYER_X);
debug_watch_f32(b"Y".as_ptr(), 1, &PLAYER_Y);
debug_watch_f32(b"Vel X".as_ptr(), 5, &PLAYER_VEL_X);
debug_watch_f32(b"Vel Y".as_ptr(), 5, &PLAYER_VEL_Y);
debug_register_f32_range(b"Health".as_ptr(), 6, &PLAYER_HEALTH, 0.0, 100.0);
debug_group_end();
// Physics group
debug_group_begin(b"Physics".as_ptr(), 7);
debug_register_f32_range(b"Move Speed".as_ptr(), 10, &MOVE_SPEED, 1.0, 20.0);
debug_register_f32_range(b"Jump Force".as_ptr(), 10, &JUMP_FORCE, 5.0, 30.0);
debug_register_f32_range(b"Gravity".as_ptr(), 7, &GRAVITY, 10.0, 50.0);
debug_register_f32_range(b"Friction".as_ptr(), 8, &FRICTION, 0.5, 1.0);
debug_group_end();
// Debug options
debug_group_begin(b"Debug".as_ptr(), 5);
debug_register_bool(b"God Mode".as_ptr(), 8, &GOD_MODE);
debug_register_bool(b"Show Hitboxes".as_ptr(), 13, &SHOW_HITBOXES);
debug_register_i32_range(b"Enemy Count".as_ptr(), 11, &ENEMY_COUNT, 0, 20);
debug_group_end();
}
}
fn update() {
unsafe {
// Respect debug pause
if debug_is_paused() != 0 {
return;
}
let dt = delta_time() * debug_get_time_scale();
// Use tunable values
PLAYER_VEL_Y += GRAVITY * dt;
PLAYER_VEL_X *= FRICTION;
if button_held(0, BUTTON_RIGHT) != 0 {
PLAYER_VEL_X = MOVE_SPEED;
}
if button_held(0, BUTTON_LEFT) != 0 {
PLAYER_VEL_X = -MOVE_SPEED;
}
if button_pressed(0, BUTTON_A) != 0 {
PLAYER_VEL_Y = -JUMP_FORCE;
}
PLAYER_X += PLAYER_VEL_X * dt;
PLAYER_Y += PLAYER_VEL_Y * dt;
}
}
}
// Game state
static float player_x = 0.0f;
static float player_y = 0.0f;
static float player_vel_x = 0.0f;
static float player_vel_y = 0.0f;
static float player_health = 100.0f;
// Tuning parameters
static float move_speed = 5.0f;
static float jump_force = 12.0f;
static float gravity = 25.0f;
static float friction = 0.9f;
// Debug
static uint8_t god_mode = 0;
static uint8_t show_hitboxes = 0;
static int32_t enemy_count = 5;
NCZX_EXPORT void init(void) {
// Player group
debug_group_begin("Player", 6);
debug_watch_f32("X", 1, &player_x);
debug_watch_f32("Y", 1, &player_y);
debug_watch_f32("Vel X", 5, &player_vel_x);
debug_watch_f32("Vel Y", 5, &player_vel_y);
debug_register_f32_range("Health", 6, &player_health, 0.0f, 100.0f);
debug_group_end();
// Physics group
debug_group_begin("Physics", 7);
debug_register_f32_range("Move Speed", 10, &move_speed, 1.0f, 20.0f);
debug_register_f32_range("Jump Force", 10, &jump_force, 5.0f, 30.0f);
debug_register_f32_range("Gravity", 7, &gravity, 10.0f, 50.0f);
debug_register_f32_range("Friction", 8, &friction, 0.5f, 1.0f);
debug_group_end();
// Debug options
debug_group_begin("Debug", 5);
debug_register_bool("God Mode", 8, &god_mode);
debug_register_bool("Show Hitboxes", 13, &show_hitboxes);
debug_register_i32_range("Enemy Count", 11, &enemy_count, 0, 20);
debug_group_end();
}
NCZX_EXPORT void update(void) {
// Respect debug pause
if (debug_is_paused() != 0) {
return;
}
float dt = delta_time() * debug_get_time_scale();
// Use tunable values
player_vel_y += gravity * dt;
player_vel_x *= friction;
if (button_held(0, NCZX_BUTTON_RIGHT) != 0) {
player_vel_x = move_speed;
}
if (button_held(0, NCZX_BUTTON_LEFT) != 0) {
player_vel_x = -move_speed;
}
if (button_pressed(0, NCZX_BUTTON_A) != 0) {
player_vel_y = -jump_force;
}
player_x += player_vel_x * dt;
player_y += player_vel_y * dt;
}
// Game state
var player_x: f32 = 0.0;
var player_y: f32 = 0.0;
var player_vel_x: f32 = 0.0;
var player_vel_y: f32 = 0.0;
var player_health: f32 = 100.0;
// Tuning parameters
var move_speed: f32 = 5.0;
var jump_force: f32 = 12.0;
var gravity: f32 = 25.0;
var friction: f32 = 0.9;
// Debug
var god_mode: u8 = 0;
var show_hitboxes: u8 = 0;
var enemy_count: i32 = 5;
export fn init() void {
// Player group
debug_group_begin("Player", 6);
debug_watch_f32("X", 1, &player_x);
debug_watch_f32("Y", 1, &player_y);
debug_watch_f32("Vel X", 5, &player_vel_x);
debug_watch_f32("Vel Y", 5, &player_vel_y);
debug_register_f32_range("Health", 6, &player_health, 0.0, 100.0);
debug_group_end();
// Physics group
debug_group_begin("Physics", 7);
debug_register_f32_range("Move Speed", 10, &move_speed, 1.0, 20.0);
debug_register_f32_range("Jump Force", 10, &jump_force, 5.0, 30.0);
debug_register_f32_range("Gravity", 7, &gravity, 10.0, 50.0);
debug_register_f32_range("Friction", 8, &friction, 0.5, 1.0);
debug_group_end();
// Debug options
debug_group_begin("Debug", 5);
debug_register_bool("God Mode", 8, &god_mode);
debug_register_bool("Show Hitboxes", 13, &show_hitboxes);
debug_register_i32_range("Enemy Count", 11, &enemy_count, 0, 20);
debug_group_end();
}
export fn update() void {
// Respect debug pause
if (debug_is_paused() != 0) {
return;
}
const dt = delta_time() * debug_get_time_scale();
// Use tunable values
player_vel_y += gravity * dt;
player_vel_x *= friction;
if (button_held(0, Button.right) != 0) {
player_vel_x = move_speed;
}
if (button_held(0, Button.left) != 0) {
player_vel_x = -move_speed;
}
if (button_pressed(0, Button.a) != 0) {
player_vel_y = -jump_force;
}
player_x += player_vel_x * dt;
player_y += player_vel_y * dt;
}
See Also: System Functions