Sample Scene
The SDK ships a working sample under the bundled sample/ project that demonstrates real-time Contact detection and rendering. This page focuses on the Touch Canvas and ends with pointers to the other domains the sample also exercises.
For a clean scaffolding path, see the bundled bootstrap skill for greenfield Board Godot projects.
What It Demonstrates
- Real-time detection and tracking of Pieces and finger Contacts.
- A live model picker that swaps the active Piece Set at runtime.
- Visual feedback for
glyph_id,orientation, and finger vs Piece classification. - A sidebar that exercises every other SDK domain (
session,save,avatar,pause,application).
Running the Sample
Open sample/project.godot in Godot and install the Custom Android Build Template once via Project > Install Android Build Template. The first time you do this, add noCompress "pck", "sparsepck" to the aaptOptions block in android/build/build.gradle, right after the ignoreAssetsPattern line — Godot’s stock template doesn’t set this, and without it the PCK is deflated inside the APK and cold boot takes ~2 minutes instead of a few seconds.
Then export the APK with Godot’s own Android export — no separate build step or script:
- Editor: Project > Export Project… > Android.
- Headless:
godot --headless --export-debug "Android" sample.apk.
The Android export preset has gradle_build/use_gradle_build enabled, so the export runs the Gradle build, bundles the addon’s board.aar (so libboard.so is present for the install gate) and the Piece Set Model into the PCK, and signs with the debug keystore. The model loads from the PCK, so a vanilla export Just Works — no asset staging.
To install, open the Board Connect web UI in a browser (the Board shows its address under Settings > System) and drag sample.apk onto it, then launch the sample from the Library. The right side is a full-height sidebar; the rest of the screen is the touch canvas.
Agent install: Use the
board-connectCLI (the agent-facing Board Connect client, installable from dev.board.fun/connect/install — no ADB, no scripts). Runboard-connect pair <host>once (tap Approve on the device); that saves the Board as the default, so later commands need no address. Thenboard-connect install sample.apk --launch(orboard-connect install sample.apkthenboard-connect launch <package>).
Touch Canvas Walkthrough
The canvas lives at sample/touch_canvas.gd. It subscribes to Board.input.contacts_received and re-draws on every inference frame:
extends Node2D
func _ready() -> void:
if not Engine.has_singleton("BoardSDK"):
return
Board.input.contacts_received.connect(_on_contacts)
Board.input.subscribe()
func _on_contacts(contacts: Array) -> void:
_contacts = contacts
queue_redraw()
func _draw() -> void:
for c in _contacts:
var pos := Vector2(float(c.x), float(c.y))
if int(c.glyph_id) > 0:
draw_circle(pos, 28.0, Color(1.0, 0.42, 0.61, 0.85))
var rad := deg_to_rad(float(c.orientation))
draw_line(pos, pos + Vector2(cos(rad), sin(rad)) * 28.0,
Color.WHITE, 3.0)
else:
draw_circle(pos, 20.0, Color(0.0, 0.825, 1.0, 0.85))
Patterns worth copying:
- Differentiate by
glyph_id—glyph_id == 0means finger,1+means a Piece type. To follow a single Piece instance across frames, track it bycontact_idinstead, since two identical Pieces share aglyph_id. - Coordinates are display-pixel, Y-down, no rotation —
c.x/c.ymap directly to screen pixels. orientationis degrees, screen-CW positive.
Live Model Picker
The sidebar’s Touch section is a live model browser. On startup it fetches the manifest at https://dev.board.fun/downloads/models/manifest.json and lists every available Piece Set. Entries bundled into the export are selectable — picking one calls Board.input.activate("models/<filename>") and the canvas immediately starts recognizing that Piece Set’s Glyphs.
Note: Runtime download isn’t supported — the native plugin reads models from the read-only PCK packaged inside the APK. To add a Piece Set, drop its
.tfliteunder the project’sassets/models/directory (the SDK loads fromres://assets/plus the model path) so the export bundles it into the PCK, then re-export and reinstall.
Debug Overlay UI
The Godot SDK has no in-editor debug overlay; the equivalent is the diagnostic log stream. The sample logs every meaningful event (Contact begin/end, session changes, save CRUD, pause-context push) via print(), so the app’s logs over Board Connect are your debug overlay. Pull them with board-connect logs <package>, then filter by SDK module:
board-connect logs fun.board.smoketest
# Each line is tagged with its originating domain, e.g.:
[Board.input] contact begin id=3 glyph_id=1
[Board.session] player joined slot=2
Add --follow to stream the logs live until Ctrl-C while you reproduce a bug: board-connect logs fun.board.smoketest --follow.
Each line is tagged with the originating domain so you can grep for [Board.input], [Board.session], and so on. Java-side Log.d(...) lines from the AAR show up in the same stream.
Testing with Hardware
Once the sample launches, verify:
- Plugin loaded — Sidebar Status shows
on_device: true. - Touch input live — Drag a finger across the canvas; a blue disc tracks it.
- Piece detection — Place a Piece from the active Piece Set; a pink disc with orientation tick and
glyph_idappears. - Pause overlay — Tap “Set context” in the sidebar, tap the system menu button (top-right, shown automatically by the OS), tap Resume; the result label updates.
- Logs clean — the
board-connect logsstream shows noSCRIPT ERRORorFATAL.
Adapting to Your Game
The sample is intentionally comprehensive. A typical starting point:
- Keep
Board.initialize(APP_ID)and the input subscription pattern fromtouch_canvas.gd. - Replace the
_drawbody with your game’s per-Contact rendering or state machine. - Wire
Board.session,Board.save, andBoard.pauseonly when you need players, persistence, or the pause overlay.
Other Domains in the Sidebar
The sample’s right sidebar also exercises every other SDK domain:
- Session — Player list, OS Player selector, AI player registration, Profile switcher. See Player Management and Profile Switcher.
- Saves — Save game CRUD with cover images and metadata. See Save Games.
- Avatar —
Board.avatar.await_load_avatar(int(player.avatar_id))returns a cached, ready-to-displayImageTexturefor a known player’s avatar. - Pause — Interactive editor for the pause-overlay context. See Pause Menu.
- Application —
Board.application.quit()(always preferred overget_tree().quit()on-device).
Next Steps
- Quick Start — fastest scaffolding path
- Setup Reference — full project configuration
- Deploy — export, install, and run on a Board
- Touch System — what the sensor sees