Lets start with taking Mongo as example, you can find the source code for this in example/sample section. We have tried to explain technique to create Animation using Motion Welder in short and simple way by dividing the tutorial into 10 steps below.
Step 1: Creating New Project.

Start with creating a new project and loading images to it.
OR 
Step 2: Creating clips from Mongo Image.
To save space/heap and to avoid repeatation of images(frame parts), artist generally create clipped images, as shown above. Here is how your clip will be shown

Start clipping this image, by creating a rectangular clips around the image parts, here is how you can do it.
- To create a clip, drag your mouse over the image from top-left to right-bottom
- To move a clip, hold it, and drag to new position
- To change dimension of a clip, shift+hold and drag to new dimension
Once you are done with creating clips, move on to start designing your Animation.
Note: You need not to clipped it to this extend if it is really not required, Even better animation can be created without clipping it to this extend or using complete frame in your input image.
Tips:
Developer can optimise resource, by identifying clips which are getting flipped in game, and seperating them out in seperate image, so that flip of only that image need to be kept in memory.
Step 3: Starting with first Animation, first Frame.
Click on Add Animation above panel, to add a animation. Name your animation.
This is what you can see now:

Let me introduce you to all this window
A. Clips Window(Drag Clips)
B. Design Window(Animation Window)
C. Frame Window
D. Info Window
A. Clips Window:
This is where your created clips appears, you can drag those create clips to Design Window, to design your Frame.
B. Design Window:
This is where you design your frame.
Frames can be designed by draging clips from Clips Window or using tools provided on left side panel in design Window.
Various Components of this Window:
1. Axis: Axis determines reference point,which is used to poisiton a animation in your j2me code, Also flipping is done based on this axis. For example flip-horizontal is done along vertical axis.
You can change the position of axis using ALT + DRAG, all the components are arranges wrt this axis.
2. Screen: Screen is used by artist to visualize the mobile screen, and when enabled, only screen area is visible. You can change the default position/dimension of Screen. Screen is generally not used while designing animation such as "Character Animation","Pickable Animation", but it used when you design animation like GameOver, StartUp Animation, which is generally visible over complete screen.
3. Background:
"Q. Now i am happy with the animation which i just created. But will it match with my ingame background, i want to test it?"
Solution for this is BackGround feature. Load your Bg image, and check if your animation matches well with your game background.
Artist can change position of that Bg using SPACE + DRAG over image.
4. Outline: Outline is self explanatory and you might not need explanation for it, but just to brief you, it is used show outlines of your clips, so that clips are easily indentified in a frame.
5. Native Components to design your Frame:
"Q. Boss asked me to create animation of thundering which will be played in background, how do i do that..? Using images might consume more heap for this useless functionality, as thundering images might be big, with simply few long lines..!!"
How about using Native Components, yes artist can save memory by using native components like Arc, Line, Rectangle, rather than actual .png image to design a frame, Peformance/look when using this components might vary on phone, do check it out.
6. Collision/Positioner Markers:
"Q. Well things are good so far, but my Mongo should get banana, when he hit it through his forehead, how do i achieve it, i need cordinates of my Mongo's forehead. :(.. actually a rectangular area around it. Can i do it "
Yes you can achive it by Collision/Positioner Markers. Developer can mark a position in a frame, and can read its value in his j2me games easily.
7. Play:
"Q. Now i am done, let me export my animation, but how about testing it in Motion Welder itself, i don't want to keep it testing in my game ".
Artist can test out you animation using play feature, and see, how well it is getting played, take a help of loop option, to play it in a loop.
8. Gif Exporter:
"Q. It's playing well now, how do i show it to my Boss, can i do it, without sending Motion Welder"
Here Gif Exporter can help you. Artist can export animation created by motion welder to animatated .gif file.
C. Frame Window.
Frame Window simply list all frames in a animation in order in which it will play. You can change the ordering by move a frame UP/DOWN in the list. Artist can enable alpha option, to check how much is a frame in offset with other frames, as shown below
D. Info Window:
Info Window provides information about Axis, Screen, Bg.
"Q. I am aware of all the windows now, how do i start with my frame? "
Yes, Now since we are aware of all the components, and it's time to design first Frame of Mongo Stand. Identify all the clips required by this frame, drag them one by one to our Design Window, arrange them, move them up/down the layer to give a best look.
Use
Native Components like Line, Arc etc to add to design. Look at numerous option like Flip, Lock, Link to design it in better way.
For eg.Lock those clips, if you want to freeze it's position etc, or Link it if you want to link all the clips motion.

Step 4: Creating Animation out of Frames:
"Q. Do i have to create a complete new Frame again, i just have to modify my first frame to get second? "
Now since you have designed your first frame, it's time to add many such frame to form a animation. Genarally artist need not to create second frame from start, as it is easy to create copy of first frame, and make suitable modification to it. Add as many frames as required.
For Mongo, we have designed stance and run.
Step 5: Exporting animation to j2me(.anu)
Now it's time to actually see your things playing on mobile. Goto File->Export Animation binary(.anu) and save your .anu file in your j2me res folder.
Dats it, we are done now, and ready to load it using Motion Welder library (motionwelder.jar). Move to next step to enjoy fun loading animation
Step 6: How to Use Motion Welder library(motionwelder.jar)
Motion Welder library (motionwelder.jar) is a opensource library containing set of few class to load/play which is provided along with installer.
Instead of using motionwelder.jar it is preffered to use source code directly so that it becomes a part of obfuscation, and result in more compressed. Also it is preffered to change source code as required. For example it is better to change source code for Nokia Device as it uses DirectGraphics and flipped image need not to be loaded explicitly on heap
Let me go through Important classes/interface used by Motion Welder
1. MSpriteLoadeder - used to load .anu file and store it's data in MSpriteData
2. MSpriteData - Used to store animation data (after loading anu data is loaded into MSpriteData)
3. MSpriteImageLoader - Interface which defines basic function that shuold be used to load images
4. MPlayer - Abstract Player to play the animation
5. MSimpleAnimationPlayer - Animation Player
6. MSpriteAnimationPlayer - Animation Player
Step 7: Loading Animation in j2me.
"Q. Every thing is set now, i have mongo image, and mongo.anu in my resource folder, now it's time to play it in my game.How do i use this classes".
Lets start with loading mongo.anu in our game, have a look at code.
| |
public static int ANIM_STAND = 0;
public static int ANIM_RUN = 1;
/*
[mongo.anu] loading mongo.anu.
[false] ask loader NOT to load chopped images in memory, but load complete image, as it is.
[myResourceLoader] inform loader that, resource should be loaded using class myResourceLoader
*/
MSpriteData mongoAnimationData = MSpriteLoader.loadSprite(/mongo.anu", false, myResourceLoader);
/* Create new animation player */
MSimpleAnimationPlayer player = new MSimpleAnimationPlayer(mongoAnimationData, 100,100);
/* Set current animation of player */
player.setAnimation(ANIM_STAND);
/* Call this in loop, to update and paint */
player.update();
player.paint(g); |
|
Step 8: Loading Images for animation.
"Q. But, how to load images? my mongo.png is kept in res folder as it is, how do i load it."
Before we can play animation as shown above, we need to write class for myResourceLoader for loading images. Lets write class ResourceLoader which implements MSpriteImageLoader.
Developer have complete freedom, on how he wish to load images, and what all images he need to load.
| |
public class ResourceLoader implements MSpriteImageLoader {
public Image[] loadImage(String spriteName,int imageId,int orientationUsedInStudio) {
if(spriteName.equals("/mongo.anu")){
// 3 for no-orientation, h-flip, v-flip
Image[] image = new Image[3];
// answer this two boolean according to your game requirement.
boolean doesMyGameNeedHFlip = true;
boolean doesMyGameNeedVFlip = false;
// load this image, if call is for first image
if(imageId==0){
image[0] = loadImage("/mongo.png");
// load Horizontal Flip image, if it is required by your game, or you have used it in Studio
if(orientationUsedInStudio==MSprite.ORIENTATION_FLIP_H || orientationUsedInStudio==MSprite.ORIENTATION_FLIP_BOTH_H_V ||doYouNeedHFlippedSpriteInYourgame){
image[1] = loadHFlippedImage("/mongo.png");
}
// load Vertical Flip image, if it is required by your game, or you have used it in Studio
if(orientationUsedInStudio==MSprite.ORIENTATION_FLIP_V || orientationUsedInStudio==MSprite.ORIENTATION_FLIP_BOTH_H_V ||doYouNeedVFlippedSpriteInYourgame){
image[2] = loadVFlippedImage("/mongo.png");
}
}
return image;
}
}
} |
|
Note: If you are developing for Nokia, where flipping can be done at runtime, then no need to load flipped images. Please refer comments in library source code provided Also look at variation in drawImageClip in MPlayer.
Step 9: Reading Collision/Position Marked area.
How do i read the collision area marked on mongo for collision detection.
It is very simmple for read collision rects, code shown below is very self explanatory.
| |
// this will return number of collision rectangle at this frame for given animation
int noOfRectAtThisFrame = player.getNumberOfCollisionRect();
for(int i=0;i<noOfRectAtThisFrame;i++){
// rect is nothing but int[4] with x,y,w,h
short[] rect = player.getCollisionRect(i);
// do required caclulating with it..
} |
|
Note: For Optimisation, same rect[] object is returned without creating new object with data filled with new values.
Step 10: Why MSimpleAnimationPlayer here, why not MSpriteAnimationPlayer.?
"Q. I am confused, here you have played animation with MSimpleAnimationPlayer, but in example you have played it with MSpriteAnimationPlayer, what is MSpriteAnimationPlayer? What is difference between two? and what advantage i get using MSpriteAnimationPlayer."
MSpriteAnimationPlayer and MSimpleAnimationPlayer is just a wrapper to abstract class MPlayer, basic functionality of both the player is same, but only difference is how to feed required parameters (orientation, x-position,y-position) and get notification(end of animation, updating sprite position etc).
In MSimpleAnimationPlayer developer need to feed each parameter to player, and get notification from player, whereas
In MSpriteAnimationPlayer player takes each parameter form MSprite object, and notifies it when even occurs.
Here is example to explain both using Mongo, I have tried to explain it using pseudo code, in which i have asked mongo to stand, and when key is pressed, make a walk steps.
Using MSimpleAnimationPlayer:
| |
public class Mongo{
public static final int ANIM_STAND = 0;
public static final int ANIM_WALK_ONE_STEP = 1;
int mongoX,mongoY;
// Constructor
public Mongo(){
// create a new player object
MSimpleAnimationPlayer player = new MSimpleAnimationPlayer(mongoAnimationData, mongoX, mongoY);
// set player to STAND animation
player.setAnimation(ANIM_STAND);
// set player to NO ORIENTATION
player.setOrientation(MSprite.ORIENTATION_NONE);
// keep playing animation in loop, if end of animation is reached, start player from FRAME 0 gain
player.setFrameOffset(0);
}
// Key Events
public void keyPressed(int keyCode){
if(keyCode == LEFT || keyCode == RIGHT){
// check if mongo is stading
if(player.getAnimation()==ANIM_STAND){
// Set animation to WALK player.setAnimation(ANIM_WALK_ONE_STEP);
// // just play it once, when end of animation is reached call end of animation
player.setFrameOffset(-1);
// set orientation as on direction
if(keyCode==LEFT)
player.setOrientation(MSprite.ORIENTATION_FLIP_H);
else
player.setOrientation(MSprite.ORIENTATION_NONE);
}
}
}
// update funtion
public void update(){
// check if animation is completed
if(player.getAnimation()==ANIM_WALK_ONE_STEP){
if(!player.isPlaying()){
player.setAnimation(ANIM_STAND);
player.setFrameOffset(0);
}
}
player.update();
spriteX = player.getSpriteDrawX();
spriteY = player.getSpriteDrawY();
}
// paint funtion
public void paint(Graphics g){
player.paint(g);
}
}
|
|
Using MSpriteAnimationPlayer:
| |
public class Mongo implements MSprite{
public static final int ANIM_STAND = 0;
public static final int ANIM_WALK_ONE_STEP = 1;
int mongoX,mongoY;
int mongoOrientation = MSprite.ORIENTATION_NONE;
// Constructor
public Mongo(){
MSimpleAnimationPlayer player = new MSimpleAnimationPlayer(mongoAnimationData, this);
player.setAnimation(ANIM_STAND);
player.setOrientation(MSprite.ORIENTATION_NONE);
// keep playing animation in loop, if end of animation is reached, start player from FRAME 0 gain
player.setFrameOffset(0);
}
@overridded function
public int getSpriteDrawX(){
return mongoX;
}
@overridded function
public int getSpriteDrawY(){
return mongoX;
}
@overridded function
public byte getSpriteOrientation(){
return orientation;
}
@overridded function
public void updateSpritePosition(int deltaX,int deltaY){
mongoX += deltaX;
mongoY += deltaY;
}
@overridded function
public void endOfAnimation(){
if(player.getAnimation()==ANIM_WALK_ONE_STEP){
player.setAnimation(ANIM_STAND);
player.setFrameOffset(0);
}
}
// Key Events
public void keyPressed(int keyCode){
if(keyCode == LEFT || keyCode == RIGHT){
// check if mongo is stading
if(player.getAnimation()==ANIM_STAND){
player.setAnimation(ANIM_WALK_ONE_STEP);
// just play it once, when end of animation is reached call end of animation
player.setFrameOffset(-1);
if(keyCode==LEFT)
orientation = MSprite.ORIENTATION_FLIP_H;
else
orientation = MSprite.ORIENTATION_NONE;
}
}
}
// Update function
public void update(){
player.update();
}
// Paint function
public void paint(Graphics g){
player.paint(g);
}
}
|
|
Note: Please refer documentation provided along with installer, to know about functionality of each function.
|