尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 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.