OhMyGame
OhMyGame은 AI로 게임을 만들 수 있는 오픈소스 스튜디오로, 디자인·구축·플레이테스트·출판을 하나의 앱에서 모델 키와 함께 수행합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 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.