AltimitSystems / mv-plugins

Altimit Systems RPG Maker MV Plugin collection
18 stars 13 forks source link

RFC suggestion for "Extra Frames" module #22

Closed vico93 closed 6 years ago

vico93 commented 7 years ago

Hi!

Wondering about this for a while, i thought in a different (and more organized) way to achieve this kind of feature in your plugin.

In my experiences making Minecraft resource packs i learn about the way the game stores data to render a animated texture, and i thought if this structure could be brought to RPG Maker, since it uses JavaScript and JSON is its data subset format.

Basically, the structure is: instead to register all the information (frame count, etc) direct in the image filename, Minecraft read a companion JSON file with the same name (and in the same folder) than the character png image, but with a different extension (like texture.png it would read a companion texture.mcmeta, which is nothing more than a JSON-formatted file), with a structured information about that char inside it.

The organization is far more better than have several characters on the sprite filename (eg.: !Celes(6 , 6 , 7, 8).png), something would broke in web servers due to the possibility to have weird characters in its name.

The full specification can be found here and here.

So, what you think about, in the case you start to implement advanced sprite control in your plugin. to organize it in a mode like this? And sorry if i wasnt much clear, my English isnt perfect.

felixjones commented 7 years ago

Existing animation definition formats

Best approach may be to look into an existing sprite animation format with an editing tool and use that. Gain some animation tool support along with extra frames - similar to the recent support for TileD polygon collisions through the TileD editor.

A quick Google search shows there isn't an obvious sprite-animation definition standard with a tool so we may end up finding nothing - in which case we'd need to design and document a small format for how animation frames are defined in this file.

Altimit custom animation definition format

I'd like to retain as much editor-support as possible, so I think our custom definition should extend from the current MV image-naming format scheme so default images can be displayed as expected in-editor and default sprite behaviour is retained.

Accessing extra frames, directions and animation presets could be done through Plugin commands for individual characters. Perhaps all extra frames are handled on a completely separate sprite-sheet with their animation loops, directions, etc defined in the definition format. Could optionally define extra frames on the parent image - more options means more power to the end user.

Actor1.png would have Actor1.json/Actor1.xml which points to the extra image files to be used and defines frame-count, frame-rate, directions, labels, etc for the extra frames. We could also sneak-in in-file collider definition for Actor1.png in this file, so 100% of the map-information for Actor1.png would be defined in this JSON/XML file.

JSON vs XML

JSON is great for developers, but end-users tend to find it confusing. End-users without coding experience usually find XML much easier - to the surprise of many. If we are unable to find a subtle format with an editor, I think XML should be the 2nd choice with JSON support at an optional later date.

Conclusion

I think we should use this issue to start defining an extra-frames format. My original plan was to have extra-frames as an extension module, as described, however the allure of being able to define per-sprite sheet colliders in this file makes me now think it would be good to have this as a built-in feature of the main Plugin - it would be "meta sprite-sheet information in a file" rather than specific to extra-frames.

This file could later be expanded to include things like foot-prints, shadows, normal-maps for a 3D lighting Plugin and rotational sprite frames for a 3D maps Plugin.

If someone does find an existing sprite editor with a good format to use, we should investigate that to see if it fits our needs before jumping on creating a new format.

vico93 commented 7 years ago

Well, lets reply case by case:

vico93 commented 7 years ago

I've created a mockup JSON meta file for you visualize what i mean:

{ "frames": 7, "standcol": 1 }

The frames property is basically the number of frames the charset have; and standcol is what column have the specific stand sprites. This JSON would be a companion for this spritesheet (sorry the misalign, its a mockup): image

EDIT: The files would be named $Crono.png and $Crono.json

felixjones commented 6 years ago

Here are my thoughts with XML. This example would be extra frames for any character using Actor1.png.

Actor1.xml

<animation tag="standing" sheet="Actor1_stand_diagonal" rate="4" direction="7"> <!-- Numpad direction, up-left -->
    <frame x="0" y="0" width="32" height="48" />
    <frame x="32" y="0" width="32" height="48" />
    <frame x="48" y="0" width="32" height="48" repeat="2" />
    <frame x="32" y="0" width="32" height="48" />
</animation>

<animation tag="standing" sheet="Actor1_stand_straight" rate="5" direction="6"> <!-- Numpad direction, right -->
    <frame x="0" y="96" width="32" height="48" />
    <frame x="32" y="96" width="32" height="48" />
    <frame x="48" y="96" width="32" height="48" repeat="2" />
    <frame x="32" y="96" width="32" height="48" />
</animation>

So Actor1.png characters will search for "Actor1.xml" entries for animation frames related to specific tags. There would be in-built tags, like "standing", "walking", "dashing". Tags could be combined like "standing|injured".

Default frame-rate would be whatever MV uses for the normal speed.

Each frame is a section on the sprite sheet. The system would only display these frames when the requirements for the "tags" are set - so to play custom animations you'd just need to set the character's tag to your named tag in the XML.

The "sheet" parameter is a bit nuanced. I think you should be able to use a file name like Actor1_standing.png, but also be able to index a reference sheet from the Plugin manager's parameters - this would be a good way of adding additional sprite sheets to the project and avoid it breaking with "Exclude unused files". Would also make it super easy to point your sheets to use a different file during development of the game, without needing to rename all the files in all the XMLs (or backup and copy files about).

Another option would be to have the animations as entries in a set, so the directions can be kept together as part of a single sheet:

<set tag="standing" sheet="Actor1_stand_diagonal">
    <animation rate="4" direction="7">
        <frame x="0" y="0" width="32" height="48" />
        <frame x="32" y="0" width="32" height="48" />
        <frame x="48" y="0" width="32" height="48" repeat="2" />
        <frame x="32" y="0" width="32" height="48" />
    </animation>
</set>
<set tag="standing" sheet="Actor1_stand_straight">
    <animation rate="5" direction="6">
        <frame x="0" y="96" width="32" height="48" />
        <frame x="32" y="96" width="32" height="48" />
        <frame x="48" y="96" width="32" height="48" repeat="2" />
        <frame x="32" y="96" width="32" height="48" />
    </animation>
</set>

Using sets would allow nesting tags, so a "standing" set could have an animation with tag "injured", accessible with the tag "standing|injured".

This is what it the first XML example would look like in JSON:

{
    "animations": [
        {
            "tag": "standing",
            "sheet": "Actor1_stand_diagonal",
            "direction": "7",
            "rate": "4",
            "frames": [
                {
                    "x": 0,
                    "y": 0,
                    "width": 32,
                    "height": 48
                },
                {
                    "x": 32,
                    "y": 0,
                    "width": 32,
                    "height": 48
                },
                {
                    "x": 48,
                    "y": 0,
                    "width": 32,
                    "height": 48,
                    "repeat": 2
                },
                {
                    "x": 32,
                    "y": 0,
                    "width": 32,
                    "height": 48
                }
            ]
        },
        {
            "tag": "standing",
            "sheet": "Actor1_stand_straight",
            "direction": "6",
            "rate": "5",
            "frames": [
                {
                    "x": 0,
                    "y": 96,
                    "width": 32,
                    "height": 48
                },
                {
                    "x": 32,
                    "y": 96,
                    "width": 32,
                    "height": 48
                },
                {
                    "x": 48,
                    "y": 96,
                    "width": 32,
                    "height": 48,
                    "repeat": 2
                },
                {
                    "x": 32,
                    "y": 96,
                    "width": 32,
                    "height": 48
                }
            ]
        }
    ]
}

I think this demonstrates why I believe XML is more friendly than JSON when it comes to hand-crafted files.

vico93 commented 6 years ago

But does XML have a friendly editor like JSON? It can be troublesome for begginers

felixjones commented 6 years ago

I think it's better to expect beginners to have no editor at all, in that circumstance I think XML is far more approachable than JSON - I say this out of experience, I am an avid fan of JSON but I don't let that blind me.

XML is also very old, so there's likely more editors for XML than JSON. I don't think the existence of GUI editors should be the deciding factor. There's no reason why we can't add JSON support as well, but I think the primary format should be XML because it is much easier to handle in text format.

Look at how much cleaner and smaller the XML example is compared to JSON. XML also supports real comments which would help developers wanting to add notes in their files (very useful in team environments!).

felixjones commented 6 years ago

I've now added a preliminary XML animation format. Add an XML file to the img/characters folder with the same name as the character graphic you want to add extra frames to.

An example animation file that adds diagonal frames to Actor1 (with a character sheet named _Actor18dir.png) would be:

<set tag="standing" sheet="Actor1_8dir">
    <!-- Standing state uses Actor1_8dir.png -->
    <animation direction="down_left">
        <frame x="48" y="0" width="48" height="48" />
    </animation>
    <animation direction="up_left">
        <frame x="48" y="48" width="48" height="48" />
    </animation>
    <animation direction="up_right">
        <frame x="48" y="96" width="48" height="48" />
    </animation>
    <animation direction="down_right">
        <frame x="48" y="144" width="48" height="48" />
    </animation>
</set>

<set tag="moving|dashing" sheet="Actor1_8dir">
    <!-- Moving & Dashing states also use Actor1_8dir.png -->
    <animation rate="3" direction="down_left">
        <!-- Animates at rate of 3 FPS -->
        <frame x="0" y="0" width="48" height="48" />
        <frame x="48" y="0" width="48" height="48" />
        <frame x="96" y="0" width="48" height="48" />
    </animation>
    <animation rate="3" direction="up_left">
        <!-- Animates at rate of 3 FPS -->
        <frame x="0" y="48" width="48" height="48" />
        <frame x="48" y="48" width="48" height="48" />
        <frame x="96" y="48" width="48" height="48" />
    </animation>
    <animation rate="3" direction="up_right">
        <!-- Animates at rate of 3 FPS -->
        <frame x="0" y="96" width="48" height="48" />
        <frame x="48" y="96" width="48" height="48" />
        <frame x="96" y="96" width="48" height="48" />
    </animation>
    <animation rate="3" direction="down_right">
        <!-- Animates at rate of 3 FPS -->
        <frame x="0" y="144" width="48" height="48" />
        <frame x="48" y="144" width="48" height="48" />
        <frame x="96" y="144" width="48" height="48" />
    </animation>
</set>

<!-- Also supports XML defined colliders, applies to entire character -->
<collider>
  <circle cx='0.5' cy='0.75' r='0.5' />
</collider>

The obvious limitation at the moment is a lack of support for actor sprite index (at the moment, it applies to any character using the image, even if they have a sprite index). I'll add support for this some point in the future.

vico93 commented 6 years ago

Thanks a lot for this! I cant wait to see a beta version of the plugin with this standard on action!

felixjones commented 6 years ago

We've been testing this aspect of Altimit Movement out for a while and I'm now considering extracting it into its own Plugin that's compatible with vanilla.

The XML standard may change during this time, so if anyone has any suggestions and ideas now is the time to suggest them.

vico93 commented 6 years ago

I support splitting the plugin in modules, to make things easier. Anyway, just FYI, there's a way to make a poll inside a issue with this: https://github.com/apex/gh-polls Perharps would be a good thing to make a new issue to let people to vote. Or use the function on Degica forums...

felixjones commented 6 years ago

I wanted to directly gauge the opinion of the people who are more familiar with the Plugin, rather than do a poll. I tested out removing the extra frames module and that all worked out fine, so now I'm creating a new extra frames Plugin.

Once it has feature parity with the Altimit Movement implementation I'll remove it entirely from Altimit Movement and publish the new Plugin.

At the moment the new Plugin uses Javascript to apply your animations, so you'll have to do a bit of Javascript to write your character animation logic - this makes the Plugin incredibly powerful and makes it a million times easier for me to develop, but comes with the requirement of needing a bit of Javascript.

If you don't know Javascript, I expect this would be a good way to get gently introduced to the language. I might expand the format in the future to have some logic in XML/Javascript, but when I started on this path it became incredibly bloated and complex and difficult to manage (was pretty much write a new programming language in XML - what a nightmare).

felixjones commented 6 years ago

I'm closing this issue now as it is no longer part of Altimit Movement. Discussion is now held at issue https://github.com/AltimitSystems/mv-plugins/issues/31