Posted by & filed under Tips.

enchant.js has just hit version 0.4.4. Despite its trademark ease of use and versatility, there’s this mysterious tl.enchant.js thing to figure out. We now introduce you to an ambitious young man struggling with how to use it…

Newbie: Frack!

Old-Timer: What’s the problem?

Newbie: Oh, forget it. Just writing a shooting game. You know, I sure wish I could do more with the way the bad guys move…

   enenmy.addEventListener("enterframe", function(){
       this.y ++;
   });

Old-Timer: Ah-ha. You have them dropping from the sky, but you want to them to zig-zag around and rotate. Right?

Newbie: A shooting game is a lot more exciting if you have to keep changing your aim, don’t you think?

Old-Timer: Yeah. Well, I tried writing it so it would zig-zag, but this makes it a bit tricky to change the movement partway through.

   enenmy.addEventListener("enterframe", function(){
       if(Math.floor(enemy.age / 30) % 2 == 0){
           this.x += 0.5;
           this.y += 0.2
       }else{
           this.x -= 0.5;
           this.y += 0.2
       }
   });

Newbie: Wait, can’t you do that in tl.enchant.js?

Old-Timer: What’s that? You mean you aren’t using WebGL?

Newbie: Not GL, TL. It’s a plugin that lets you to control movement along with time.

Old-Timer: Never heard of it.

Newbie: It used to be called animation.enchant.js. Anyway, tl.enchant.js makes it ridiculously easy to control sprite movement. Check it out:

   enemy.tl.moveBy(30, 10, 30).moveBy(-30, 10, 30).loop();

Old-Timer: Wait, what does this do?

Newbie: First, you move to 30,10 over 30 frames. Then, you move to -30,10 over 30 frames. You then repeat. That’s all you need to create a zig-zag movement.

Old-Timer: That’s how you write it, huh? Dang, that’s easy. Kinda like Flash’s Tweener. How many methods can you connect?

Newbie: Pretty much as many as you want.

Old-Timer: So if you write like this…

   enemy.tl.moveBy(30, 10, 30).moveBy(-30, 10, 30).moveBy
(30, 10, 30).moveBy(-15, 10, 30).moveBy(0, 100, 180);

Newbie: It should zig-zag, and then move straight forward.

Old-Timer: Okay, what if I want it delete it from onscreen after making it move forward?

Newbie: For that you’d use a function from removeFromScene();.

enemy.tl.moveBy(30, 10, 30).moveBy(-30, 10, 30).moveBy(30, 10, 30).moveBy(-15, 10, 30).moveBy(0, 100, 180).removeFromScene();

Old-Timer: Just how easy can this get?! Okay, but what about deleting “enemy” from the screen after an attack?

Newbie: All motions added to the timeline are added via enterframe EventListener, so it won’t be executed after being deleted from the screen.

Old-Timer: Uh, where is that written?

Newbie: You can check an explanation in these slides from the enchant.js meetup. [in Japanese]

Old-Timer: Awesome. Wait, you can use easing too?

Newbie: That’s right. You can use easing just like in Tweener.

Old-Timer: No kidding. Alright, let’s try this on your shooting game. It’s already starting to feel more authentic. Okay, but what if I want to make it move while rotating it?

Newbie: Just use and() to process it simultaneously!

   enemy.tl.moveBy(30, 10, 30).and().rotateBy(360, 30);

Old-Timer: But wouldn’t it get a little long if you wanted to connect more than three?

Newbie: Ah, here’s how to solve that!

   enemy.tl.tween({ x: 30, y: 30, rotation: 360, time:30 });

Old-Timer: Ah, so this object creates twins. If you move this object somewhere, you can create the same movement.

Newbie: Even if you just “delay” and “then,” you can create a pretty good timer. enchant.js is pretty slick at stuff like telling things to happen after one second…

   Game.rootScene.tl.delay(30).then(function(){
       // Processing after one second
   });

Old-Timer: I see, so “then” executes the function. It applies to rootScene, but perhaps you can use it for something besides Sprite?

Newbie: Yep, you can use it for anything that succeeds Node.

Old-Timer: I see. Okay, so what if you want to animate an explosion and then delete it at the end?

Newbie: If you use “cue,” you can apply whatever processing you want after a set period of time.

this.tl.cue({
  0:function(){this.frame++;},
  5:function(){this.frame++;},
 10:function(){this.frame++;},
 15:function(){this.frame++;},
 20:function(){game.rootScene.removeChild(this);}

Old-Timer: No kidding? That’s awesome. So you can change the START text on the title screen and stuff?

Newbie: You’d have to rewrite nineleap.enchant.js. Kinda like this.

this.startScene.element.tl.rotateTo(45,1).scaleTo(5,1).scaleTo
(1,30).and().rotateTo(0,30);

Old-Timer: Sweet! How’d you do that?

Newbie: Just add the line we just talked about to line 17 of nineleap.enchant.js, and rewrite the enchant.nineleap.SplashScene class to what you see below.

enchant.nineleap.SplashScene = enchant.Class.create
(enchant.Scene, {
    image: {
        get: function() {
            return this._image;
        },
        set: function(image) {
            this._image = image;

            while (this.firstChild) {
                this.removeChild(this.firstChild);
            }
            var sprite = new Sprite(image.width, image.height);
            sprite.image = image;
            sprite.x = (this.width - image.width) / 2;
            sprite.y = (this.height - image.height) / 2;
            this.addChild(sprite);
            this.element = sprite; // Add this line
        }
    }
});

Old-Timer: Wow. So, to edit an image directly, you substitute sprite for element!

Newbie: There’s a lot more you can use it for, but why don’t we let you digest this first?

Old-Timer: Thanks! This is awesome. I’m gonna have to use this more.