1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Guest, PO has ceased our separate tiering and adopted Smogon tiers for SM. More information and updates here.

    Dismiss Notice

[Guide] Making move animations

Discussion in 'Arts and Graphics' started by coyotte508, Dec 15, 2011.

Thread Status:
Not open for further replies.
  1. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    The whole of the animations is in the qml folder. What's good is that if you change something in the qml folder, it'll change for the next battle, without even having to restart PO.

    Editing QML files

    Well, you can try downloading Notepad++ and changing the langage to Javascript. Or, you can download the whole PO source and open the BattleManager project, and edit stuff with QtCreator (help here).

    Any other text editor is fine, but it's always cooler with syntaxic coloring.

    Resources for learning about QML

    QML is a programming language, among other things. For those of you more interested there's here and here and here.

    Otherwise, what i'm going to explain below should be enough. Minimal knowledge about programming/javascript wouldn't hurt though.

    The QML Code

    Look up qml/BattleDataQML/PokeballAnimation.qml. If you change col: 6 into another number, for example 1, 2, 3, 4, 5, 7, ..., you'll have a different pokeball when you send out a pokemon!

    If you look at qml/images/pokeballs.png, you'll understand why.

    So this is a very basic change and simple introduction.

    Basically there are two kind of files: QML files, which are more or less description of graphic elements with parameters and all, and also some code inside, and javascript files, which are pure code.

    Let's look at the QML structure. Well, let's look at a QML file (qml/battlescene.qml) so i can start explaining stuff:

    [secret]
    Code (javascript):
    1. import QtQuick 1.0
    2. import pokemononline.battlemanager.proxies 1.0
    3. import "BattleDataQML" 1.0
    4. import "BattleDataQML/weather.js" as Weather
    5.  
    6. Item {
    7.     id: scene;
    8.  
    9.     width: 500
    10.     height: 400
    11.  
    12.     /* Separate element so that it can have a negative Z and be separate from the rest */
    13.     Image {
    14.         source: "images/grass.png"
    15.         anchors.fill: parent;
    16.         z: -500;
    17.     }
    18.  
    19.     property bool loaded: false;
    20.     property int playerFront: battle.scene.reversed ? 0: 1;
    21.     property int playerBack: battle.scene.reversed ? 1: 0;
    22.  
    23.     property variant fieldPokemons: battle.scene.reversed ? [poke2, poke1] : [poke1, poke2];
    24.  
    25.     /* Rectangle used by the weather */
    26.     Rectangle{
    27.         id: weatherOverlay;
    28.         anchors.fill: parent;
    29.         opacity: 0;
    30.  
    31.         Behavior on opacity {
    32.             NumberAnimation {
    33.                 duration: 250;
    34.             }
    35.         }
    36.     }
    37.  
    38.     Team {
    39.         id: team1
    40.         anchors.right: parent.right
    41.         anchors.rightMargin: 20
    42.         anchors.bottom: parent.bottom
    43.         anchors.bottomMargin: 20
    44.         width: 96
    45.         height: 64
    46.         team: battle.data.team(playerBack)
    47.     }
    48.  
    49.     Team {
    50.         id: team2
    51.         team: battle.data.team(playerFront)
    52.         width: 96
    53.         height: 64
    54.         anchors.left: parent.left
    55.         anchors.leftMargin: 20
    56.         anchors.top: parent.top
    57.         anchors.topMargin: 20
    58.     }
    59.  
    60.     FieldPokemon {
    61.         id: poke1
    62.         back: true
    63.         spot: playerBack;
    64.         fieldPokemon: battle.data.field.poke(playerBack)
    65.         pokemon: team1.team.poke(0)
    66.         anchors.left: parent.left
    67.         anchors.leftMargin: 55
    68.         anchors.bottom: parent.bottom
    69.         anchors.bottomMargin: 55
    70.     }
    71.  
    72.     FieldPokemon {
    73.         id: poke2
    74.         back: false
    75.         spot: playerFront;
    76.         fieldPokemon: battle.data.field.poke(playerFront)
    77.         pokemon: team2.team.poke(0)
    78.         anchors.right: parent.right
    79.         anchors.rightMargin: 65
    80.         anchors.top: parent.top
    81.         anchors.topMargin: 55
    82.     }
    83.  
    84.     Connections {
    85.         target: team1
    86.         onFieldPokemonChanged: {
    87.             poke1.pokemon = team1.team.poke(pokemon)
    88.         }
    89.     }
    90.  
    91.     Connections {
    92.         target: team2
    93.         onFieldPokemonChanged: {
    94.             poke2.pokemon = team2.team.poke(pokemon)
    95.         }
    96.     }
    97.  
    98.     Loader {
    99.         anchors.fill: parent;
    100.         id: weather
    101.     }
    102.  
    103.     Connections {
    104.         target: battle.data.field
    105.         onWeatherChanged: {
    106.             Weather.trigger(weather, battle.data.field.weather);
    107.         }
    108.     }
    109.  
    110.     Connections {
    111.         target: battle.scene
    112.         onAttackUsed: {
    113.             fieldPokemons[spot].useAttack(attack, fieldPokemons[1-spot]);
    114.         }
    115.     }
    116. }
    117.  
    The code is for the battlescene. You can see already some obvious things. The scene is 500x400 px.

    The code
    Code (javascript):
    1.     /* Separate element so that it can have a negative Z and be separate from the rest */
    2.     Image {
    3.         source: "images/grass.png"
    4.         anchors.fill: parent;
    5.         z: -500;
    6.     }
    7.  
    [/secret]

    Says there's an image, which we can get at images/grass.png. If you look more carefully, you'll see that the image is the one at the background of the scene.

    The anchors.fill: parent means the image takes the whole of the parent widget, here the parent widget is the scene so it takes all the scene.

    z: -500 tells that the image is at the far end, -500 is very far far away so that means that other stuff will appear on top of it instead of behind it.

    You can also see some Team, FieldPokemon elements that fill the battlescene. You'll notice that in the qml/BattleDataQML folder there are a Team and FieldPokemon files. Indeed, at the beginning of the code you see import "BattleDataQML" 1.0, so you can summon the files in the folder directly. Since the qml files are but other elements, you can put them directly on your scene.

    There are other parts of the code I could explain. Just look at the code, understand what you can, and then read the next part.

    Battle Moves

    The only currently implemented battle move is Leech Seed. So that's the only one I can refer you to atm.

    First look at BattleDataQML/moves.js

    You'll see this line:

    Code (javascript):
    1. effects[BattleData.LeechSeed] = "Moves/LeechSeed.qml";
    It basically tells that for LeechSeed, the corresponding qml file is Moves/LeechSeed.qml. For now we can only associate a battle move with a qml file. Maybe later we can add parameters to the move, like params[BattleData.LeechSeed] = xxx. That way several similar moves could use the same QML file with different parameters for slightly different effects. But we're not there yet.

    Anyway, if you wanted to add an effect for Tackle, you should do:

    Code (javascript):
    1. effects[BattleData.Tackle] = "Moves/YourFileForTackle.qml"
    Now let's look at the code for leechseed:

    [secret]
    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3. import "../utilities.js" as Utilities
    4. import "../spawner.js" as Spawner
    5.  
    6. Move {
    7.     id: main;
    8.  
    9.     /* Available variables:
    10.       - attacker (FieldPokemon)
    11.       - target (FieldPokemon)
    12.       - attack (int)
    13.       */
    14.  
    15.     Timer {
    16.         id: timer2;
    17.         interval: 300;
    18.     }
    19.  
    20.  
    21.     Timer {
    22.         id: timer3;
    23.         interval: 600;
    24.     }
    25.  
    26.     function start() {
    27.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x, "y":target.y+40}, "controlY":80};
    28.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+20}, "controlY":80};
    29.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    30.  
    31.         launchSeed(curve1, false);
    32.  
    33.         timer2.triggered.connect(function(){launchSeed(curve2, false)});
    34.         timer3.triggered.connect(function(){launchSeed(curve3, true)});
    35.  
    36.         timer2.start();
    37.         timer3.start();
    38.     }
    39.  
    40.     function launchSeed(curve, finish) {
    41.         var parent = main.parent;
    42.         var leech = Spawner.spawn(parent.parent, "moving-animated", {
    43.                                       "source": "../../images/leech-seed.gif",
    44.                                       "duration": 750,
    45.                                       "delay": 1000,
    46.                                       "curve": curve,
    47.                                       "z": parent.z
    48.                                   },
    49.                                   function(obj){
    50.                                       finished.connect(function(){obj.destroy()});
    51.                                       if (finish) {
    52.                                           finished();
    53.                                       }
    54.                                   }
    55.                                   );
    56.     }
    57.  
    58.     signal finished();
    59. }
    60.  
    [/secret]

    So basically, you'll see that LeechSeed.qml has a function start() and a signal finished(). That's what all move should have: start() is called when the move starts, and the move calls finished() when it has finished.

    Now let's look more in detail at start():

    Code (javascript):
    1.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x, "y":target.y+40}, "controlY":80};
    2.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+20}, "controlY":80};
    3.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    For those of you that have ever used Photoshop or Illustrator, the notion of curve and control point may be familiar. You know, when with the ink pen you click here, there, and then drag something in the middle to make a curve? It's the same principle: pos1 is here, pos2 is there, controlY is how far vertically you drag the pen.

    The curves will be used by Spawner to move objects along it. Basically what Spawner does, is it loads a QML component with the parameter you give it. In this instance, it'll load Utilities/MovingGif.qml with the parameters source, duration, delay, curve, z.

    If you look at MovingGif.qml, you'll see that it moves the gif along the curve for duration (duration is the time in milliseconds), then it starts animating the gif and waits delay (which here is 1 second), then it finishes. You'll see it's very specific to Leech Seed, but later on you can add more parameters to make it more generic and use it with other moves.

    So if you look at the code of LeechSeed again, you'll see i launch a seed, i launch another 300 milliseconds later and another 600 milliseconds later, using timers.

    Now onto the final piece of code:
    Code (javascript):
    1.                                   function(obj){
    2.                                       finished.connect(function(){obj.destroy()});
    3.                                       if (finish) {
    4.                                           finished();
    5.                                       }
    6.                                   }
    That's the bit of code called when the moving gif finished (Spawner takes care of calling that). The parameter, obj, is the object called by Spawner.

    So the line
    Code (javascript):
    1. finished.connect(function(){obj.destroy()});
    Says that when i call finished(), then the object should be destroyed (here the leech seed). It does two things: It removes the seed from the screen, and since the seed is dynamically allocated by the spawner (don't bother understanding that if it's trouble), it frees some memory too.

    Basically, just remember to destroy objects created by Spawner. You could destroy it right there, but then the first seed would be destroyed while the last seed is still playing, and you want to destroy all 3 seeds at the same time. That's why you connect them to the finished signal, so that they are all destroyed when finished() is called.

    Then there is:

    Code (javascript):
    1.                                       if (finish) {
    2.                                           finished();
    3.                                       }
    Here finish is the parameter of launchSeed (you saw launchSeed called with launchSeed(XXX, false) or launchSeed(XXX, true)). So when the third seed ends, since the third seed has finish to true, finished() will be called and so it notifies of the end of the move!

    Conclusion

    I understand that for non-programmers a lot of this is hard to digest. That's why as long as you make some kind of effort, don't hesitate to PM me on the server for help. You can also post here any progress you make.

    Also since we are all bound to modify some files, not only add Move files, post all the changes in this topic. I'll try to keep updated files here: https://github.com/coyotte508/pokemon-online/tree/master/bin/qml

    For example since last download i've changed LeechSeed.qml and move.js...

    So yea. Ask away. I can even invite some of you to indigo to discuss stuff with me and other devs on the server, when needed. And I hope for some contributions!
     
    Last edited: Jul 8, 2012
  2. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    First!

    Ok, implemented earthquake :-)

    Here's a demo video [11M]

    My code:
    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3.  
    4. Move {
    5.     id: main;
    6.  
    7.     /* Available variables:
    8.       - attacker (FieldPokemon)
    9.       - target (FieldPokemon)
    10.       - attack (int)
    11.       */
    12.  
    13.     SequentialAnimation  {
    14.         id: animation;
    15.         SequentialAnimation  {
    16.             loops: 10;
    17.             NumberAnimation { target: scene; property: "x"; to: +50; duration: 50 }
    18.             NumberAnimation { target: scene; property: "x"; to: -50; duration: 50 }
    19.         }
    20.         NumberAnimation { target: scene; property: "x"; to: 0; duration: 100 }
    21.         ScriptAction { script: (function() {
    22.             battle.scene.unpause();
    23.             finished()
    24.         })(); }
    25.     }
    26.  
    27.     function start() {
    28.         battle.scene.pause();
    29.         animation.running = true;
    30.     }
    31.  
    32.     signal finished();
    33. }
    34.  

    Basically, I just start SequentialAnimation on the start() function. It does all animation in order. I first do another sequential animation with 10 loops. Then I center the scene to 0. Afterwards I call a function to destroy the move object and continue battling.

    Oh and obviously add:
    Code (text):
    1. effects[BattleData.Earthquake] = "Moves/Earthquake.qml";
    to moves.js
     
  3. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    :D

    Also with my recent changes, you don't need battle.scene.unpause(); and battle.scene.pause();. (Moved them to moves.js)
     
  4. Deity

    Deity Designer

    Joined:
    Dec 9, 2010
    Messages:
    195
    Likes Received:
    18
    Did Stealth Rock, no way to record it without taking an hour to upload it to Youtube.

    Added this to moves.js

    Code (javascript):
    1. effects[BattleData.StealthRock] = "Moves/HiddenPebbles.qml";
    And this is Moves/HiddenPebbles.qml (Stealth Rock)

    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3. import "../utilities.js" as Utilities
    4. import "../spawner.js" as Spawner
    5.  
    6. Move {
    7.     id: main;
    8.  
    9.     /* Available variables:
    10.       - attacker (FieldPokemon)
    11.       - target (FieldPokemon)
    12.       - attack (int)
    13.       */
    14.  
    15.     Timer {
    16.         id: timer2;
    17.         interval: 300;
    18.     }
    19.  
    20.  
    21.     Timer {
    22.         id: timer3;
    23.         interval: 600;
    24.     }
    25.  
    26.     function start() {
    27.         battle.scene.pause();
    28.  
    29.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x-10, "y":target.y+40}, "controlY":80};
    30.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+80}, "controlY":80};
    31.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    32.  
    33.         launchSeed(curve1, false);
    34.  
    35.         timer2.triggered.connect(function(){launchSeed(curve2, false)});
    36.         timer3.triggered.connect(function(){launchSeed(curve3, true)});
    37.  
    38.         timer2.start();
    39.         timer3.start();
    40.     }
    41.  
    42.     function launchSeed(curve, finish) {
    43.         var parent = main.parent;
    44.         var leech = Spawner.spawn(parent.parent, "moving-animated", {
    45.                                    "source": "../../images/stealth-rock.png",
    46.                                    "duration": 750,
    47.                                    "delay": 1000,
    48.                                    "curve": curve,
    49.                                     "z": parent.z
    50.                                },
    51.                                function(obj){
    52.                                       if (finish) {
    53.                                            obj.destroy();
    54.                                            battle.scene.unpause();
    55.                                            finished();
    56.                                       } else {
    57.                                           finished.connect(function(){obj.destroy()});
    58.                                       }
    59.                                }
    60.                                );
    61.     }
    62.  
    63.     signal finished();
    64. }
    65.  
    Only difference from Leech Seed is where some of the rocks land and directories.
     
  5. Wavy

    Wavy prince of the sea Server Moderator Server Moderator

    Joined:
    Aug 6, 2010
    Messages:
    394
    Likes Received:
    67
    Attack animations aren't showing for me. Everything else works, but neither Leech Seed, nor Earthquake (which I added) shows any animation. I'm ready to help with this but it's obviously useless if I can't get them to display.

    OS is Windows7
     
  6. Xdevo

    Xdevo Phrasing Super Moderator Tour Director Super Moderator Tour Director

    Joined:
    Jul 18, 2010
    Messages:
    2,524
    Likes Received:
    1,616
    I'm having the same problem with the same OS.
     
  7. Deity

    Deity Designer

    Joined:
    Dec 9, 2010
    Messages:
    195
    Likes Received:
    18
    Hm, I'm using Windows 7 and works fine.

    Anyways, here are a couple more and an update to SR (Forgot to replace the function name)

    moves.js (For all 3 moves)
    Code (javascript):
    1. effects[BattleData.StealthRock] = "Moves/HiddenPebbles.qml";
    2. effects[BattleData.ToxicSpikes] = "Moves/ToxicSpikes.qml";
    3. effects[BattleData.Spikes] = "Moves/Spikes.qml";
    HiddenPebbles.qml
    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3. import "../utilities.js" as Utilities
    4. import "../spawner.js" as Spawner
    5.  
    6. Move {
    7.     id: main;
    8.  
    9.     /* Available variables:
    10.       - attacker (FieldPokemon)
    11.       - target (FieldPokemon)
    12.       - attack (int)
    13.       */
    14.  
    15.     Timer {
    16.         id: timer2;
    17.         interval: 300;
    18.     }
    19.  
    20.  
    21.     Timer {
    22.         id: timer3;
    23.         interval: 600;
    24.     }
    25.  
    26.     function start() {
    27.         battle.scene.pause();
    28.  
    29.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x-10, "y":target.y+40}, "controlY":80};
    30.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+80}, "controlY":80};
    31.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    32.  
    33.         launchStealth(curve1, false);
    34.  
    35.         timer2.triggered.connect(function(){launchStealth(curve2, false)});
    36.         timer3.triggered.connect(function(){launchStealth(curve3, true)});
    37.  
    38.         timer2.start();
    39.         timer3.start();
    40.     }
    41.  
    42.     function launchStealth(curve, finish) {
    43.         var parent = main.parent;
    44.         var stealth = Spawner.spawn(parent.parent, "moving-animated", {
    45.                                    "source": "../../images/stealth-rock.png",
    46.                                    "duration": 750,
    47.                                    "delay": 1000,
    48.                                    "curve": curve,
    49.                                     "z": parent.z
    50.                                },
    51.                                function(obj){
    52.                                       if (finish) {
    53.                                            obj.destroy();
    54.                                            battle.scene.unpause();
    55.                                            finished();
    56.                                       } else {
    57.                                           finished.connect(function(){obj.destroy()});
    58.                                       }
    59.                                }
    60.                                );
    61.     }
    62.  
    63.     signal finished();
    64. }
    65.  
    Spikes.qml
    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3. import "../utilities.js" as Utilities
    4. import "../spawner.js" as Spawner
    5.  
    6. Move {
    7.     id: main;
    8.  
    9.     /* Available variables:
    10.       - attacker (FieldPokemon)
    11.       - target (FieldPokemon)
    12.       - attack (int)
    13.       */
    14.  
    15.     Timer {
    16.         id: timer2;
    17.         interval: 300;
    18.     }
    19.  
    20.  
    21.     Timer {
    22.         id: timer3;
    23.         interval: 600;
    24.     }
    25.  
    26.     function start() {
    27.         battle.scene.pause();
    28.  
    29.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x, "y":target.y+55}, "controlY":80};
    30.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+65}, "controlY":80};
    31.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    32.  
    33.         launchSpikes(curve1, false);
    34.  
    35.         timer2.triggered.connect(function(){launchSpikes(curve2, false)});
    36.         timer3.triggered.connect(function(){launchSpikes(curve3, true)});
    37.  
    38.         timer2.start();
    39.         timer3.start();
    40.     }
    41.  
    42.     function launchSpikes(curve, finish) {
    43.         var parent = main.parent;
    44.         var spike = Spawner.spawn(parent.parent, "moving-animated", {
    45.                                    "source": "../../images/spikes.png",
    46.                                    "duration": 750,
    47.                                    "delay": 1000,
    48.                                    "curve": curve,
    49.                                     "z": parent.z
    50.                                },
    51.                                function(obj){
    52.                                       if (finish) {
    53.                                            obj.destroy();
    54.                                            battle.scene.unpause();
    55.                                            finished();
    56.                                       } else {
    57.                                           finished.connect(function(){obj.destroy()});
    58.                                       }
    59.                                }
    60.                                );
    61.     }
    62.  
    63.     signal finished();
    64. }
    65.  
    ToxicSpikes.qml
    Code (javascript):
    1. import QtQuick 1.0
    2. import "../" 1.0
    3. import "../utilities.js" as Utilities
    4. import "../spawner.js" as Spawner
    5.  
    6. Move {
    7.     id: main;
    8.  
    9.     /* Available variables:
    10.       - attacker (FieldPokemon)
    11.       - target (FieldPokemon)
    12.       - attack (int)
    13.       */
    14.  
    15.     Timer {
    16.         id: timer2;
    17.         interval: 300;
    18.     }
    19.  
    20.  
    21.     Timer {
    22.         id: timer3;
    23.         interval: 600;
    24.     }
    25.  
    26.     function start() {
    27.         battle.scene.pause();
    28.  
    29.         var curve1 = {"pos1":{"x":attacker.x+40, "y":attacker.y+10}, "pos2":{"x":target.x, "y":target.y+55}, "controlY":80};
    30.         var curve2 = {"pos1":{"x":attacker.x+30, "y":attacker.y+5}, "pos2":{"x":target.x+30, "y":target.y+65}, "controlY":80};
    31.         var curve3 = {"pos1":{"x":attacker.x+40, "y":attacker.y+15}, "pos2":{"x":target.x+70, "y":target.y+60}, "controlY":70};
    32.  
    33.         launchToxicSpikes(curve1, false);
    34.  
    35.         timer2.triggered.connect(function(){launchToxicSpikes(curve2, false)});
    36.         timer3.triggered.connect(function(){launchToxicSpikes(curve3, true)});
    37.  
    38.         timer2.start();
    39.         timer3.start();
    40.     }
    41.  
    42.     function launchToxicSpikes(curve, finish) {
    43.         var parent = main.parent;
    44.         var tspike = Spawner.spawn(parent.parent, "moving-animated", {
    45.                                    "source": "../../images/toxic-spikes.png",
    46.                                    "duration": 750,
    47.                                    "delay": 1000,
    48.                                    "curve": curve,
    49.                                     "z": parent.z
    50.                                },
    51.                                function(obj){
    52.                                       if (finish) {
    53.                                            obj.destroy();
    54.                                            battle.scene.unpause();
    55.                                            finished();
    56.                                       } else {
    57.                                           finished.connect(function(){obj.destroy()});
    58.                                       }
    59.                                }
    60.                                );
    61.     }
    62.  
    63.     signal finished();
    64. }
    65.  
    66.  

    Whoops, forgot all the images:

    [​IMG]

    [​IMG]

    [​IMG]



    List of Most Common Moves
    Leech Seed
    Ice Beam
    Thunderbolt
    Surf
    Stone Edge
    Substitute
    Earthquake
    Stealth Rock
    Spikes
    Toxic Spikes
    Rapid Spin
    Protect
    Drain Punch
    Payback
    U-turn
    Bullet Punch
    Pain Split
    Toxic
    Will-O-Wisp
    Thunder Wave
    Wish
    Substitute
    Close Combat
    Outrage
    Dragon Dance
    Shadow Ball
    Swords Dance
    Calm Mind
    Scald
    Surf
    Psychic
    Psyshock
    Focus Blast
    Grass Knot
    Hidden Power
    Brick Break
    Draco Meteor
    Volt Switch

    Feel free to suggest more to add


    And here's a resource for all move animations from B/W (For reference or ripping)
    http://www.youtube.com/watch?v=2hXl2r3_Cts&list=UUOroKrnNjz_SKhhyORshyVQ&index=10&feature=plcp
     
    Last edited: Jan 2, 2012
  8. Nexus

    Nexus Legend Killer

    Joined:
    Oct 12, 2010
    Messages:
    1,287
    Likes Received:
    2
    Draco Meteor and Volt switch are commonly used as well Js .Sure count me in , I will do some later .
     
  9. Arcanine123

    Arcanine123 Occupation isn't guilty.

    Joined:
    Apr 27, 2012
    Messages:
    7
    Likes Received:
    0
    Tried it, it's awesome.
     
  10. dravog

    dravog New Member

    Joined:
    Mar 26, 2012
    Messages:
    6
    Likes Received:
    0
    guys try mach punch with a punch in front
     
  11. dravog

    dravog New Member

    Joined:
    Mar 26, 2012
    Messages:
    6
    Likes Received:
    0
    oh i forgot that if we can put a back ground scene of
    - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - -

    behind the scenes for extrem speed and an add for mach punch
     
  12. rgrishav145

    rgrishav145 Member

    Joined:
    Apr 21, 2012
    Messages:
    37
    Likes Received:
    0
    Awesome earthquake one
     
  13. Croak

    Croak 20/20 hindsight

    Joined:
    Aug 31, 2011
    Messages:
    273
    Likes Received:
    0
    Volt Switch:
    [​IMG][/HIDE]
    lolBide:
    [​IMG][/HIDE]
     
  14. Tyki

    Tyki Change

    Joined:
    Nov 13, 2011
    Messages:
    926
    Likes Received:
    0
    PO Trainer Name:
    Tyki
    Bumping this with a toxic idea.

    [​IMG]
     
  15. Hannah

    Hannah Come a little closer

    Joined:
    Nov 10, 2010
    Messages:
    985
    Likes Received:
    237
    PO Trainer Name:
    Hannah
    For those interested in contributing to the Pokemon Online Battle Animations, the requests are in this thread.

    Locking this up because it's mostly a tutorial and the needed stuff is on the other thread.
     
Thread Status:
Not open for further replies.