open-manifold / Open-Manifold

A free and open-source clone of Rhythm 'n' Face for PC.
Other
10 stars 2 forks source link

Implement "tile.json" to control tile BGFX behavior #18

Closed SuperFromND closed 1 year ago

SuperFromND commented 1 year ago

Currently, the tile background effect is set up in a rather unusual way; as the wiki currently puts it:

Plays a tiled animation at a constant rate, sourced from a level's tile.png file. tile.png should have a resolution such that the width is a multiple of the height (e.g. 256x64, where 256 is exactly 4 times 64, for 4 frames) and consist of square frames in left-to-right order, like a film strip.

This was somewhat sensible when it was originally written and there were no JSON files that Open Manifold recognized besides level.json, but it comes across as archaic given that characters get more customizable frame data in the form of character.json.

I think that a new JSON file should be introduced for handling tiles, named tile.json. The fundamental layout should work similarly to character.json in that it uses this setup for frame data:

[
    {"x":0,  "y":  0,"w":128,"h":128},
    {"x":0,  "y":128,"w":128,"h":128},
    {"x":128,"y":  0,"w":128,"h":128},
    {"x":128,"y":128,"w":128,"h":128}
]

Since there's only ever one tile that gets modified, we can just read every element in this array and loop it. Doing this approach would also have the bonus of allowing for non-square tile sizes, or even tile sizes that change mid-animation, which could lead to all kinds of strange and interesting effects.

And if tile.json isn't found or malformed, we can then reimplement the old way of doing things as a fallback, calculating the frame data based on the tile image. The steps would be something like:

SuperFromND commented 1 year ago

Some late-night concept-scribbling: I don't think it'd be too unreasonable to have tile.json include a header as well similar to level.json, albeit obviously with different parameters.

Specifically, I want to implement a parameter for time, a constant that specifies how long each frame should be displayed for, so that it can be controlled by the user rather than being enforced to one speed by the game. Making it a header value would still limit animations to a constant rate of playback, but it would also be easier to program and it could allow for accurate previews of tile frame animations (e.g. a tiny 24fps animation in something like Blender could be exported as frames, stitched together, and then put in a level with a time value of (1000 / 24 = ~41) to get near-identical playback!)

I also got a suggestion from xen-osd about an alternate format which defines the size of a single tile and then calculates the rest off of that, which is something that I may consider as well (although not with this exact formatting):

// example written by xen-osd

[
    {"flags":[
      {"blockMode":1}
    ]},
    {"blockW":128, "blockH":128, "lineBreak":4, "startX":0, "startY":0}
]
SuperFromND commented 1 year ago

This has now been implemented by the above commit. Here's a demonstration using the test tile.png and the following tile.json contents:

[
    {"placeholder": "placeholder"},
    {"x":0,  "y":0,"w":16,"h":16},
    {"x":16,  "y":0,"w":16,"h":16},
    {"x":32,  "y":0,"w":16,"h":16},
    {"x":48,  "y":0,"w":16,"h":16},
    {"x":64,  "y":0,"w":16,"h":16},
    {"x":80,  "y":0,"w":16,"h":16},
    {"x":96,  "y":0,"w":16,"h":16},
    {"x":112,  "y":0,"w":16,"h":16},
    {"x":96,  "y":0,"w":16,"h":16},
    {"x":80,  "y":0,"w":16,"h":16},
    {"x":64,  "y":0,"w":16,"h":16},
    {"x":48,  "y":0,"w":16,"h":16},
    {"x":32,  "y":0,"w":16,"h":16},
    {"x":16,  "y":0,"w":16,"h":16}
]

https://user-images.githubusercontent.com/22881403/227755868-1c388c29-88ee-4c20-b02e-2804772e0748.mp4