Resource Armor Stand Animator Class

Discussion in 'Spigot Plugin Development' started by bram0101, Jun 4, 2016.

  1. Hello everybody!
    So, I've been doing some plugin development after a while and one of the things I made is a way to animate armor stands. I thought, why not share it on here. I have no idea if there's already an api out here or something like that, but I thought my class works, so why not share it.

    How does this work?
    Everything is packed into 1 class.
    You create one instance for every armor stand you want to animate and in the constructor you give the path to the animation file and the armor stand to animate. The class will then load it and when you call it's update method it'll set the pose of the armor stand and teleport it to what is specified in the animation file.

    What are the features?
    - All the instances don't do anything to each other so you can specify different animations for different armor stands.
    - You can Play/Pause/Stop an animation
    - There's a linear interpolate allowing you to not have to specify all the key frames.
    - Whenever an animation file is parsed, it's cached so it only has to do it once.
    - It's not that hard to setup, all you have to do is create an instance and call the update method.

    How does this animation file you're talking about look like?
    The animation file has a simple layout.
    This is a simple animation.
    The yaw value is something that doesn't really like to be updated that much in my testing experience!

    How would it look like if I would use this class?
    If you want to make the instance of the class then this is all you have to do:
    Code (Text):
    new ArmorStandAnimator(new File(getDataFolder(), "ani2.animc"), armorstand);
    As you can see it's pretty easy. You just give it a file and the bukkit armorstand class.
    You should notice that I don't save it to a variable. This is because whenever you create a new instance of the class it automatically adds itself to a list. Then I can later on call a special method that will update all the instances registered.
    So if I want to create an armor stand and animate it then all I have to do is this:
    Code (Text):
    ArmorStand as = Bukkit.getWorld("world").spawn(new Location(Bukkit.getWorld("world"), 0, 4, 0), ArmorStand.class); //spawn the armor stand
                    as.setAI(false); //set some stuff
                    new ArmorStandAnimator(new File(getDataFolder(), "ani2.animc"), as); //actually register the armor stand
    Now there's one thing. The animator class doesn't register a repeating task. It depends on YOU to update it. This is useful because with this you can specify how many updates you have. All the code that you have to perform to update ALL the armor stands is this:
    Code (Text):

    Are there any current problems?
    Yes. This was made originally as a concept and it's not a full API thingy.
    You can very easily make it error if your animation file isn't correct. For example if you remove one of the lines that specify the rotations or body parts then it'll give you a null pointer exception.
    There are probably also some other things but I don't have any other problems I can think of out of my head.
    If you found a problem just say it.
    Another thing is that the yaw that you can specify can bug a lot. It won't give errors, but the animation would be the way it should be.

    OMG Do you have any GIFS?!?!
    This is a gif of an animation.

    The next gif was a bug, the animation file had the rotations in degrees and bukkit takes it's rotation values in radians so I forgot to convert it. It has been fixed but it looked funny.

    The gifs I just showed weren't interpolated. This is how it would look if I would've removed keyframes and made it interpolated. (Ignore the sudden jump in the yaw. For some reason the yaw doesn't like to work properly)

    Questions and Answers
    These are some questions I think you might have

    Q: Can I use this in any plugin?
    Yes you can. But, you can't claim it as your own and you can't remove the license part at the top.

    Q: What if I want to update an animation file, do I have to reload the server because of that cache?
    No, there's a method called clearCache() in the class that'll clear the cache.

    Q: Are there loads of comments added that explain what things do?
    Yes! There are!

    Q: Are those comments funny?
    No they aren't. Sorry.

    Q: What is the maximum amount of frames per second?
    The maximum amount of frames per second is 20. Because there are 20 ticks per second.
    The minimum can be whatever you want because you are the person updating it.
    This means that you could have a statue that changes position every so often.

    Q: Whenever I try to teleport the armor stand, it teleports back! Help?
    This is because you can change it's location in the animation file. The location in the animation file is relative from the starting location on when you initialized the armor stand animator class. You can change the starting location to teleport the armor stand with this method:
    Code (Text):
    setStartLocation(Location location)
    Q: Can I just take a snippet of this code and give it to people for help on how to do things or for my own work?
    I personally would rather have you use the whole class. But you are allowed to take a part of the code, IF you keep the copyright notice! If you use this code to help somebody by giving this code to them, I'd rather have you link them to this thread instead. There's just a lot of useful information in here and then they know that I made it.

    Q: What license are you using?
    I'm using the MIT License.
    Why this license? This license says that everybody can use it, public and private developers, and you just have to make sure that you keep the copyright notice

    Generating the animation file
    So the animation file can easily be made by yourself. But it will take a while.
    So, if you have an animation program and you know how to make scripts for that program, then you are able to create a script that exports the animation. That is actually what I did. I made a script that allows me to make an armor stand in my animation program and export it. And that's probably the reason why the first 2 gifs looked better than the last one. Because the first 2 gifs were exported with that script and didn't had the interpolation on, because all the frames were already generated by that script.

    Can I please see the code right now?!
    Sure! This is the code:

    I hope this class will be useful and if you've found any errors or anything like that, just tell me here.
    I would love to hear what you guys think of this.
    #1 bram0101, Jun 4, 2016
    Last edited: Jun 5, 2016
    • Useful x 14
    • Like x 12
    • Funny x 2
    • Agree x 1
    • Winner x 1
    • Informative x 1
    • Creative x 1
  2. Very usefull tutorial!
    • Friendly Friendly x 1
  3. The reason why that happens is that you can move the armor stand in the actual animation file. You can teleport him by setting the start location. I've got a method for that.
    Code (Text):
    setStartLocation(Location location)
    That will change the location on the next time he updates.
    I'll add this to the questions part
  4. Thanks, I deleted my question before you replied ;o lol
  5. This is amazing :D
  6. MiniDigger


    could you a bit more into detail on that?
    what program did you use? could you share that script?
    your class looks really cool (and you use mit, so I can actually use it, yeah ^^)
  7. He is just using a NotePad file with a custom extension.
  8. MiniDigger


    no, he is talking about an animation program with an export script. read the faq post that I quoted.
  9. I actually just used MAYA for animating and I remade that armor stand, and with the script I just exported all the frames.
    I'll post the script
    Code (Text):
    proc runArmorStandExport(){
        string $result[] = `fileDialog2 -fileFilter "*.animc" -dialogStyle 2 -fileMode 0 -cap "Save Ani File" -okc "Save" -cc "Cancel"`;
        if(size($result) > 0){
            string $file = $result[0];
            string $selection[] = `ls -sl`;
            string $armorBase = $selection[0];
            float $minTime = `playbackOptions -q -minTime`;
            float $maxTime = `playbackOptions -q -maxTime`;
            string $frameData[];
            int $i = 0;
            $fileId = `fopen $file "w"` ;
            float $length = $maxTime - $minTime;
            string $lengthString = "length " + $length + "\n";
            fprint $fileId $lengthString;
            for($frame = $minTime; $frame <= $maxTime; $frame++){
                currentTime $frame;
                string $data = "";
                float $dframe = $frame - $minTime;
                $data = $data + "frame " + $dframe + "\n";
                string $childs[] = `listRelatives -c`;
                for($ii = 1; $ii < size($childs); $ii++){
                    $data = $data + $childs[$ii] + " ";
                    float $rot[] = `xform -q -ro $childs[$ii]`;
                    $data = $data + $rot[0] + " " + $rot[1] + " " + $rot[2] + "\n";
                $frameData[$i] = $data;
                fprint $fileId $data;
            pclose $fileId;
        print("Saved the file!");

    The only thing is that you will have to use this script in MAYA, and you have to make that armor stand, and you have to name all the objects correctly because of the way I made this script.
  10. Just a small optimization: I think it's better to use line.split(" ") one time and save the array in a local variable instead of creating 3 new arrays every time you want to get the x y z coords at the 1 2 3 indexes.
  11. MiniDigger


    thank you, gonna check that out if I have time
  12. That would be better, but this is only performed once you load an animation. and normally the code is fast enough like this. And because it saves the already parsed files, you will only really need it when you have to parse a lot of different animation files every second or so. and if the animation files are HUUUGE. But if you want to, you can just change that part to optimize it. The MIT license allows that
    • Like Like x 1
  13. Another thing (probably going to be a simple solution as my above post lol) but when I try making a 2nd armor stand and put the animator on him he only does one frame >.> (can only make one stand with an animation)
  14. you need to call the update method every tick in a repeating task yourself.
  15. I don't understand how to put this into plugin form, could you do a video on it or something :)
    #15 Cmsalvo, Aug 5, 2016
    Last edited: Aug 5, 2016
    • Funny Funny x 2
  16. This isn't its own plugin, it's a resource/utility. He posted examples and how to use it throughout the thread, you just have to import the class into your project and follow the instructions. If you're new to programming or don't know how to program at all, you can't "just put it into a plugin". If you've tried working with the class and had issues however, there's nothing wrong with asking, so as long as you have the source code with it :p
  17. ok thank you for clarifying
    • Friendly Friendly x 1
  18. I'm extremely confused on how to actually create the animations, I downloaded Maya but, how do you get the armor stand model in there or where do you even get a model of the armor stand.

    Could you also put the armor stand 3d model on here to download :)
    #18 Cmsalvo, Aug 6, 2016
    Last edited: Aug 6, 2016
  19. The model was something I made myself and I then used a script I made to export it. You don't need to use what I use. You can always just take an existing animation file and edit it in notepad.
  20. Neat-o
    • Like Like x 1