Thing-editor 2.0b

repository·master·Indexed 19 days ago

https://github.com/megabyteceer/thing-editor

A visual game editor built with TypeScript, Pixi.js, and Vite.js, delivered as an Electron desktop application. It includes a game engine featuring scene management, UI modal systems, asset loading progress tracking, and specialized classes for audio playback (HowlSound), geometric shapes, and Spine skeletal animations.

Tokens
6.6K
Snippets
26
Records
30
Agent score
61%

What's inside thing-editor

  1. Launch Thing-editor via VS Code

    master

    To run the editor in a development environment with a debugger attached:

    1. Open the thing-editor.code-workspace file in VS Code.
    2. Accept all recommended tasks and extensions when prompted.
    3. Launch the [EDITOR] debug configuration.

    The editor will start as an Electron application with the VS Code debugger attached.

  2. Launch Thing-editor via Scripts or Terminal

    master

    Using provided scripts

    • Windows: Run the run-win10.bat file.
    • Linux/Mac: Run the run-ubuntu.sh file.

    Using terminal commands

    Navigate to the thing-editor folder and run the following commands to start the Vite server and the Electron application:

    npx vite &
    npx electron "./thing-editor/electron-main"
  3. Access game state and data

    master

    The Game instance provides several properties for accessing global state:

    • data: A GameData object used as a storage container for variables accessible via data-path selectors.
    • W and H: The current logical width and height of the game.
    • isMobile: Boolean indicating if the user is on a mobile device.
    • isPortrait: Boolean indicating if the current orientation is portrait.
    • keys: The input management system (Keys).
    • settings: The persistent settings manager for the game instance.
  4. Use Spine sequences for complex animation logic

    master

    The Spine class supports SpineSequence objects, which allow you to chain multiple animation items together with delays, speeds, and callback actions.

    SpineSequence Interfaces

    SpineSequence

    Defines a collection of animation items.

    • n: The name of the sequence.
    • s: An array of SpineSequenceItem objects.
    • l?: An optional index for the loop target within the sequence.

    SpineSequenceItem

    A single step in a sequence.

    • n: The name of the animation to play.
    • mixDuration?: Transition duration for this item.
    • delay?: Fixed delay after the animation starts.
    • delayRandom?: A random delay range applied to the item.
    • speed?: Playback speed for this specific item.
    • actions?: An array of SpineSequenceItemAction to execute.

    SpineSequenceItemAction

    An action triggered during a sequence.

    • a: A CallBackPath (string) representing the function to call.
    • t: The time/frame at which the action is triggered.
    const mySequence: SpineSequence = {
      n: 'attack_combo',
      s: [
        {
          n: 'swing_1',
          speed: 1.2,
          actions: [{ a: 'myCallbackPath', t: 10 }]
        },
        {
          n: 'swing_2',
          delay: 5
        }
      ]
    };
  5. Manage global sound and music volumes

    master

    The Sound class provides static methods to control the master volume levels for sound effects (FX) and background music (MUSIC). Volumes are treated quadratically for smoother perceived transitions.

    Volume Controls:

    • Sound.soundsVol: Controls the volume of all sound effects (FX). Range: 0.0 to 1.0.
    • Sound.musicVol: Controls the volume of background music (MUSIC). Range: 0.0 to 1.0.
    • Sound.fullVol: Sets both music and sound volumes to the same value.

    Toggles:

    • Sound.toggleSounds(): Toggles the sound effects on/off.
    • Sound.toggleMusic(): Toggles the music on/off.
    • Sound.toggleFullSound(): Toggles both music and sounds simultaneously.
    Sound.setSoundsVol(0.5); // Set FX volume to 50%
    Sound.setMusicVol(0.8);  // Set Music volume to 80%
    Sound.toggleMusic();      // Toggle music on/off
  6. Manage Spine animations and skins with the Spine class

    master

    The Spine class is a Container used to manage and play Spine skeletal animations within the engine. It handles resource loading, animation playback, skin switching, and complex animation sequences.

    Key Properties

    • spineData: A string representing the resource path to the Spine data.
    • currentAnimation: The name of the animation currently playing.
    • currentSkin: The name of the skin currently applied (defaults to 'default').
    • speed: The playback speed multiplier.
    • loop: Boolean indicating if the current animation should loop.
    • mixDuration: The duration of the transition between animations.
    • sequences: An array of SpineSequence objects defining complex playback logic.
    • isPlaying: Boolean indicating if the Spine is currently playing.
    • tint: A numeric color value applied to the Spine content.
    • useParentTint: If true, the Spine inherits the tint from its parent.
    const spine = new Spine();
    spine.spineData = 'path/to/spine_resource';
    spine.currentAnimation = 'walk';
    spine.currentSkin = 'warrior_skin';
    spine.speed = 1.5;
    spine.loop = true;
  7. Manage persistent settings with the Settings class

    master

    The Settings class provides a mechanism for managing key-value pairs that are persisted to localStorage. It handles automatic serialization to JSON and includes a debounced flushing mechanism to minimize writes to storage.

    Key Features

    • Persistence: Data is stored under a specific storageId in localStorage.
    • Automatic Flushing: Changes are debounced (using a 10ms interval) to prevent excessive writes, unless running in EDITOR mode where changes are flushed immediately.
    • Global Change Listener: You can subscribe to changes across all Settings instances using the static globalOnChanged callback.
    • Lifecycle Management: The class automatically attempts to flush pending changes when the window is unloaded (beforeunload).
    import Settings from 'thing-editor/src/engine/utils/settings';
    
    // Initialize settings with a unique storage ID
    const mySettings = new Settings('user_preferences');
    
    // Set a value
    mySettings.setItem('theme', 'dark');
    
    // Get a value (with an optional default)
    const theme = mySettings.getItem('theme', 'light');
    
    // Remove a value
    mySettings.removeItem('theme');
    
    // Clear all settings in this instance
    mySettings.clear();
  8. Access the global game instance

    master

    The game instance is exported as the default export from src/engine/game.ts. In environments where the EDITOR flag is enabled, the game instance is also attached to the global window object, allowing for direct access via window.game in the browser console.

    Note that several methods on the Game prototype are specifically flagged for the editor's property choosers using internal metadata (e.g., ___EDITOR_isGoodForChooser, ___EDITOR_isHiddenForChooser).

    import game from 'src/engine/game.ts';
    
    // Use the game instance to interact with the engine
    console.log(game.currentScene);
    
    // If in an editor environment, it is also available globally
    // window.game.showScene('myScene');
  9. Initialize the game engine with init()

    master

    To start the game engine, call init(). You can optionally provide a target HTML element, a unique gameId, and pixiOptions to configure the underlying PIXI.js application. The method attaches the canvas to the provided element or document.body by default and initializes core systems like settings, interaction, and fonts.

    // Example initialization
    game.init(document.getElementById('game-container'), 'my-game-id', { backgroundColor: 0x000000 });
  10. Play Spine animations and control playback

    master

    Use the following methods to control the playback of Spine animations:

    • play(animationName: string, mixDuration?: number): Plays a specific animation with an optional mix duration.
    • playFromFrame(frame: number, animationName?: string, mixDuration?: number): Plays an animation starting from a specific frame.
    • playIfDifferent(animationName: string, mixDuration: number, playIfStopped?: boolean): Plays the animation only if it is not already playing or if the state allows.
    • playIfNot(animationName: string, mixDuration: number, playIfStopped?: boolean, animationNamesRegexp: string): Plays the animation only if the current animation does not match the provided regular expression.
    • stop(isNeedRefresh?: boolean): Stops the current animation playback.
    • stopByName(animationName: string, isNeedRefresh?: boolean): Stops playback if the specified animation is the one currently playing.
    • toInitPose(timeFrames: number): Forces the Spine to return to its initial setup pose over a specified number of frames.
    spine.play('run', 0.2);
    spine.stop();
    spine.playIfDifferent('idle', 0.1);
    spine.toInitPose(30);