OhMyGame
OhMyGame is the open-source studio for making games with AI. Design, build, playtest, and publish games in one app, with your own model keys.
Edit and build .gdlvl level files in the browser
AI summary · website content
GamesJavaScript · CSSGitHub @MegaCode111REALOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Read, edit and write Geometry Dash .gdlvl level files from JavaScript (Node 18+ and browsers).
import { readFileSync, writeFileSync } from "node:fs";
import { Level, inRect } from "./src/gdlvl.js";
const level = Level.fromFileText(readFileSync("level.gdlvl", "utf8"));
level.add(8, 900, 15, { rotation: 90, groups: [5] }); // add an object
level.remove(inRect(790, 0, 800, 10)); // delete objects in an area
level.update({ id: 1 }, { color_1: 1004 }); // edit properties
level.move({ id: 1 }, 0, 30); // shift objects
level.setColor(1000, 20, 20, 60); // background colour
// Triggers are objects too. Properties are checked against the object's class.
level.add(901, 300, 105, { // 901 = Move trigger
target_group: 5, move_x: 120, duration: 1.5, easing: "ease_in_out",
});
writeFileSync("out.gdlvl", level.toFileText());
A static page (no build step, no server code) that opens, edits and exports .gdlvl files.
npm run serve # then open http://localhost:8080/web/
ES modules need http://, so it won't work from a file:// URL. To host it, serve the repository
root as static files (for example GitHub Pages from main, root folder): the root index.html
redirects to web/, and the page imports the library from src/.
.gdlvl on the page. The level is autosaved in your browser.target_group, move_x, duration, easing and so on. Colour channels are editable too.W A S D move (Shift = 1 unit), Q / E rotate 90 counter-clockwise / clockwise, Alt+Q / Alt+E flip X / Y,
1 / 2 / 3 Build / Edit / Delete mode, F1 / F2 previous / next build tab, Ctrl+Z undo, Ctrl+Shift+Z redo,
Ctrl+C / Ctrl+D / Ctrl+V copy / duplicate / paste, Left / Right previous / next group,
R Rotate toggle (drag to rotate), T Swipe toggle (drag to select), F Free move toggle, G Snap toggle,
mouse wheel moves the view up and down (Shift = sideways, Ctrl = zoom), + / - zoom.
Also Del delete, Ctrl+A select all, Home fit level, Esc cancel. Pan with middle or right mouse button, or Space + drag.
Enter (playtest) and Ctrl+Enter (play music) show a message: the editor can't play levels.Art: the editor loads the bundled UHD Geometry Dash sprite sheets and their matching plist metadata from data/spritesheets/, crops frames (including packed rotations and offsets), and uses original frames where the object-to-frame association can be inferred. The texture menu can disable original textures, load custom art, or clear runtime-loaded art. Unmatched objects still use placeholders. See web/assets/README.md.
Not built yet: playing the level, live trigger previews, editor layers, free transform, warp tools.
Each object's class comes from its object ID, and the class decides which properties exist, what
they are called and what type they have (see data/schema.json).
const t = level.find({ id: 901 })[0];
t.className; // "MoveTrigger"
t.get("easing"); // "ease_in_out" (enums read as names)
t.set("move_x", 50); // names or raw key numbers: t.set(28, 50)
t.set("moveX", 50); // camelCase also works
t.set("move_z", 1); // throws: Unknown property "move_z" for MoveTrigger ...
t.properties(); // every property of this class with its current value
level.validate(); // objects holding keys their class doesn't define
Int/Float, booleans for Bool, number[] for group lists.level.find({ groups: 5 }) matches objects that are in group 5.classOf(id), fieldsOf(className), idsForClass(className) expose the schema directly,
e.g. to build a property panel for an editor.3,986 object IDs have names, for building an object palette or searching by name.
import { objectName, findObjects } from "./src/gdlvl.js";
objectName(8); // "Black Gradient Spike"
findObjects("move trigger"); // [{ id: 901, name: "Move Trigger", className: "MoveTrigger" }]
findObjects("spike black", 20); // every word must match, in any order; second argument limits results
level.objects[0].name; // name of an object already in a level
.gdlvl = base64url( gzip( plist XML ) )k2 name, k4 level data, k48 object count, ...)k4 = base64url( gzip( header;obj;obj;... ) )key,value,key,value,... (1 = object ID, 2 = x, 3 = y, ...)Unknown fields and object properties are preserved on save. The k48 object count is kept in sync
automatically.
Node uses the built-in zlib. Browsers and bundlers use src/codec.browser.js (a small built-in gzip reader/writer, no dependencies) through the browser condition
in package.json. Files written by the browser codec are valid gzip but not compressed, so they are larger than the game's own; they have not been tried in the game yet.
npm test # library tests (schema, names, codec, round trips)
npm run test:web # headless-browser test of the editor (needs Playwright)
npm run build:assets # rescan web/assets/objects/ and rebuild web/assets/manifest.json
npm run build:data # regenerate src/schema-data.js and src/names-data.js from data/
node test/demo.mjs test/fixtures/sample.gdlvl /tmp/out.gdlvl
add() get only the properties you give them, not the editor's defaults
(for example color_1_index, which every object in the sample level carries).The property schema and object names come from GD Info Explorer. Thanks to Alphalaneous and the community for naming the objects. See NOTICE.md.