문제

To start with, I'm not new to actionscript (AS2.0) neither am I an experienced programmer in this language and I barely use any of it's object oriented features (frankly, I've never even written a class). Anyway, This is my code


var instName;
var num=0;
setInterval(createSym,100);
function createSym(){
    instName="sym"+num++;
    this.attachMovie("sym",instName,this.getNextHighestDepth());
    eval(instName)._x=100;
    eval(instName)._y=100;  
    var t1=setInterval(moveSym,8,instName);
    function moveSym(instName){
        eval(instName)._x+=1;
    }
    var t2=setInterval(checkSym,1,instName);
    function checkSym(instName){
        if(eval(instName)._x>=600){
            clearInterval(t1);
            clearInterval(t2);
            eval(instName).removeMovieClip();
        }
    }
}

At first I thought I'm having some kind of scope problem with nested functions but I've accidentally used the same logic in another program and it works perfectly (I would also appreciate some help in understanding how runtime memory is managed in languages like this). But then I realized that this code works if I change this in this.attachMovie to _root or if I change calling technique (without changing this to _root) to


setInterval(mycaller,100);
function caller(){
     createSym();
}

I can't make out how these two ways differ from each other. Thanks for any help with this :)

도움이 되었습니까?

해결책

The scope changes in AS2 with setInterval. Just to make sure, do trace(this) inside the callback and you'll see it's not the _root, as expected, but you can pass a container movieclip as an extra argument to the callback function so you can add the library items into.

Also, the code looks complicated for no reason:

var instName;//keep track of the new instance for each clip
var num=0;//number of symbols
setInterval(createSym,100);//create a symbol every 100 milliseconds
function createSym(){
    instName="sym"+num++;//update instance name
    this.attachMovie("sym",instName,this.getNextHighestDepth());//attach a new clip
    eval(instName)._x=100;//set initial position
    eval(instName)._y=100;  
    var t1=setInterval(moveSym,8,instName);//add another interval to move the symbol
    function moveSym(instName){
        eval(instName)._x+=1;
    }
    var t2=setInterval(checkSym,1,instName);//and another inverval to check if the clip is 'outside' limits, clear intervals and remove clip
    function checkSym(instName){
        if(eval(instName)._x>=600){
            clearInterval(t1);
            clearInterval(t2);
            eval(instName).removeMovieClip();
        }
    }
}

Each person has a coding style, so there isn't a right/wrong at this point, as long as it work. Here's how I rewrote it so it would make sense for me:

var clips:Array = [];
var currentClips:Number = 0;
var totalClips:Number = 100;
setInterval(update,40,this);//interval is at 40 ms ~ 25 fps, also pass a target movie clip to attache library items into

function update(targetClip:MovieClip) {
    if(currentClips < totalClips){//still need clips ?
        var clip:MovieClip = targetClip.attachMovie('sym','sym'+currentClips,targetClip.getNextHighestDepth());//add a clip
        clip._x = 100;//initialize position
        clip._y = Math.random() * 100;
        clips.push(clip);//update array and clips counter
        currentClips++;
    }
    //update existing clips
    for(var i:Number = 0 ; i < currentClips; i++) {
        clips[i]._x+=10;
        if(clips[i]._x > Stage.width) {//if a clips is outsite, remove it, update the array and counter, and another should be created instead
            clips[i].removeClip();
            clips.splice(i,1);
            currentClips--;
        }
    }
}

Notice that clips are removed and added each time they exit the stage, which might take a few resources, that could be saved if we simply reuse the same symbol by repositioning it:

var clips:Array = [];
var currentClips:Number = 0;
var totalClips:Number = 100;
setInterval(update,40,this);//interval is at 40 ms ~ 25 fps, also pass a target movie clip to attache library items into

function update(targetClip:MovieClip) {
    if(currentClips < totalClips){//still need clips ?
        var clip:MovieClip = targetClip.attachMovie('sym','sym'+currentClips,targetClip.getNextHighestDepth());//add a clip
        clip._y = Math.random() * 100;//initialize position
        clips.push(clip);//update array and clips counter
        currentClips++;
    }
    //update existing clips
    for(var i:Number = 0 ; i < currentClips; i++) {
        clips[i]._x+=10;
        if(clips[i]._x > Stage.width) clips[i]._x = 0;//reuse same clips, simply update position
    }
}

Also, I noticed it doesn't look very fun as is, so I've added a variable for velocity (_vx), since MovieClip is a dynamic class and you can add properties to it at runtime. Note that this isn't a good practice. The goal was to get a bit of depth in the way the clips animate:

var clips:Array = [];
var currentClips:Number = 0;
var totalClips:Number = 100;
setInterval(update,40,this);//interval is at 40 ms ~ 25 fps, also pass a target movie clip to attache library items into

function update(targetClip:MovieClip) {
    if(currentClips < totalClips){//still need clips ?
        var clip:MovieClip = targetClip.attachMovie('sym','sym'+currentClips,targetClip.getNextHighestDepth());//add a clip
        clip._y = Math.random() * 100;//initialize position
        clip._vx = 5 + Math.random() * 5;//clips have different velocities - give a bit of depth
        clips.push(clip);//update array and clips counter
        currentClips++;
    }
    //update existing clips
    for(var i:Number = 0 ; i < currentClips; i++) {
        clips[i]._x += clips[i]._vx;
        if(clips[i]._x > Stage.width) clips[i]._x = 0;//reuse same clips, simply update position
    }
}

Speaking of depth, the clips aren't depth sorted, but I diverge... Regarding your problem with _root and scope, the issue with with setInterval because scope changes, but you can use an argument to the callback to get past the issue.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top