Rpg Maker MZ Next : The modern rpg maker MZ framework

Update!

Bitmap.drawText();

is now functionalble and now use pixijs Text rendering. However, it is quite similar to the canvas rendering. I was planning to use bitmapText but sadly does not offers enough control to what RM user would be accustomed to.

big differences to the normal RM system, it will now use textstyle! which will offers a LOTS of control on many aspect of text. I will make sure to allow easy access to this.
probably via a simple function :

bitmap.changeTextStyle({});

now I shall rest because god dang it was an hurdle to debug a weird bug!

1 Like

the new API change is :
Windows now have anchor for better position!

The library also provide per-existing anchor presets for sprites and windows anchors!

const rect = new Rectangle(10,10,100,100);
const window = new WindowDummy(rect);
window.anchor.copyFrom(AnchorPresets.Center);
// or 
window.anchor.x = 0.5;
window.anchor.y = 0.5;

it should help you guys position windows in a better way!

for the more technical aspect on how anchors are implemented it is quite simple :

  get anchor(): Point {
    return this._anchor;
  }

  set anchor(value: PointData | number) {
    if (typeof value === 'number') {
      this._anchor.set(clamp(value, 0, 1), clamp(value, 0, 1));
    } else {
      this._anchor.set(clamp(value.x, 0, 1), clamp(value.y, 0, 1));
    }
    this.updatePivot();
  }

  private updatePivot() {
    this.pivot.set(
      this._anchor.x * this._width,
      this._anchor.y * this._height
    );
  }
// some code ommited but it also update on width and height resizing.

it is basically an alias / setter for pivot which are based on the container localTransform.

more updates!

SceneLayer

its an experimental features but it allows for grouping Sprites into fully functional scene layers. imagine basically having virtually infinite layers to allow to push custom layers to the Scene_Map (.ie fog, even lighting!)

the technical implementation is like this and can work for virtually anything.

/**
 * The class that manage multiples scene layers. 
 * 
 * its a collections of ```RenderLayer``` that allow to 
 * group efficiently any containerChild into *layers*
 * @experimental this require still a lots of implementation for it.
 */
export class SceneLayerContainer extends Container<ContainerChild> {
  
  private readonly _layers: Map<string, RenderLayer>;

  // Track which physical children belong to which layer name
  private _layerTracking: Map<string, Set<ContainerChild>>;

  get layers(): Map<string, RenderLayer> {
    return this._layers;
  }

  getLayer(name: string): RenderLayer {
    const layer = this._layers.get(name);
    if (!layer) throw new Error(`Layer "${name}" not found`);
    return layer;
  }

  constructor() {
    super();
    this._layers = new Map();
    this._layerTracking = new Map();
    this.sortableChildren = true;
  }

  addLayer(name: string, layer: RenderLayer, zIndex: number | null = null) {
    if (this._layers.has(name)) {
      throw new Error(`Layer name "${name}" already exists`);
    }

    this._layers.set(name, layer);
    this._layerTracking.set(name, new Set());

    if (zIndex !== null) {
      layer.zIndex = zIndex;
    }

    this.addChild(layer);
  }

  addToLayer(layerName: string, ...children: ContainerChild[]) {
    const layer = this.getLayer(layerName);
    const trackedSet = this._layerTracking.get(layerName)!;

    this.addChild(...children);
    layer.attach(...children);

    for (const child of children) {
      trackedSet.add(child);
    }
  }

  removeFromLayer(layerName: string, ...children: ContainerChild[]) {
    const layer = this.getLayer(layerName);
    const trackedSet = this._layerTracking.get(layerName)!;

    layer.detach(...children);
    this.removeChild(...children);

    for (const child of children) {
      trackedSet.delete(child);
    }
  }

  removeLayer(name: string, destroyChildren: boolean = false) {
    const layer = this._layers.get(name);
    if (!layer) throw new Error(`Layer "${name}" not found`);

    const trackedChildren = this._layerTracking.get(name);

    if (trackedChildren) {
      // Safely process all components tied to this specific layer registry
      for (const child of trackedChildren) {
        this.removeChild(child);
        if (destroyChildren) {
          child.destroy({ children: true });
        }
      }
    }
    layer.detachAll();
    this.removeChild(layer);
    this._layers.delete(name);
    this._layerTracking.delete(name);
  }
}

you could say that SceneLayerContainer are just fancy container! with the new

RenderLayer

API it make all of this easier.

however this is still fairly experimental and I am still juggling with it. but I really hope it will help you guys to attach new content to the SceneMap or any scene wya easier!

1 Like

Excited to see where this goes, especially ESModules support!

Would this still be compatible with the vanilla editor and export to NW.JS?
Even if I dont use the editor a whole lot for mechanics it is still great for tiles and events.
And the wide JS/TS on desktop market seems to have moved to Electron, although I still have a softspot for NW.

While I love the decorators for override alias etc, I’m not sure if we should still encourage those patterns? For an actual codebase aliasing is both parts useful and bloat-prone. We may also be able to move away from ClassName.prototype.funcName as that’s 10 year old syntax.

As for compatibility, I’m conflicted on if rewriting the corescripts is worth it over contributing to another open “maker” like RPGPaperMaker or GodotRpgFramework, especially if the end goal is to have “a whole new rpgmaker engine minus the editor”.

There’s a world out there where some of the core is rewritten but we also implement all prototypes from the old MZ corescript (but rewire their behavior to act upon the new system). Not sure how feasible or helpful that’d be though.

1 Like

Would this still be compatible with the vanilla editor and export to NW.JS?
Even if I don’t use the editor a whole lot for mechanics, it is still great for tiles and events.
And the wide JS/TS on desktop market seems to have moved to Electron, although I still have a soft spot for NW.

This is 100% compatible with the old editor + Nw.js.

Right now I use Vite just for simplicity (it natively supports TS so it bundles faster).

While I love the decorators for override alias etc, I’m not sure if we should still encourage those patterns? For an actual codebase aliasing is both parts useful and bloat-prone. We may also be able to move away from ClassName.prototype.funcName as that’s 10 year old syntax.

As for this, this is something I am slowly thinking about with the current restriction of RPG Maker MZ (it’s not like Unity where we can just extend a class and attach it to a game object), but I was thinking of some native hook. But I am unsure YET how to approach this. If I was in C#, this is as simple as using an Event Listener. But the workflow for RPG Maker plugins is very big on monkey patching, so forcing users into not using this is slightly more complicated.

As for compatibility, I’m conflicted on if rewriting the core scripts is worth it over contributing to another open “maker” like RPGPaperMaker or GodotRpgFramework, especially if the end goal is to have “a whole new RPG Maker engine minus the editor”.

There’s a world out there where some of the core is rewritten, but we also implement all prototypes from the old MZ core script (but rewire their behavior to act upon the new system). Not sure how feasible or helpful that’d be though.

As for compatibility, I get ya. Originally my plan was just: man, I really wish RPG Maker would have a modern PixiJS ecosystem! and I started porting it for pure fun and interest (yes, I am weird). This project was purely born out of pure curiosity TBH.

A lot of the breaking changes are purely because of going from V5 → V8 in PixiJS, which broke so many things. I guess I want to bring RPG Maker to a more updated state because of how old the tech (very old libraries) it is actually sitting on, and contrary to Ruby or C#, web updates so fast it’s quite insane, and I do want to give some more years to MZ.

But I won’t deny that even sometimes I sit and wonder if it’s worth my time, as it is a huge undertaking, but the more I push effort and scrape at it, slowly it’s fun to see it slowly come to life and solving issues. But again, I think I am just weird lmao.

As for RPG Paper Maker, I am actually the runtime designer for the V2 core scripts with Wano lmao. However, I fairly learned a lot since last time, and I gotta return to refresh the V3 core script to be more modular and flexible! Didn’t have time recently, sadly.

1 Like