7

この質問は、ActionScript 3.0 および Flash CS6 に関連しています。

オブジェクトを特定の数秒間少し振るようにしています。これを「ムービークリップ」にして、次のコードを作成しました。

import flash.events.TimerEvent;

var Machine_mc:Array = new Array();

var fl_machineshaking:Timer = new Timer(1000, 10);
fl_machineshaking.addEventListener (TimerEvent.TIMER, fl_shakemachine);
fl_machineshaking.start ();


function fl_shakemachine (event:TimerEvent):void {


 for (var i = 0; i < 20; i++) {

  Machine.x += Math.random() * 6 - 4;
  Machine.y += Math.random() * 6 - 4;
 }

}

ムービーをテストすると、次のようなエラーが複数表示されます。

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at Historieoppgave_fla::MainTimeline/fl_shakemachine()
    at flash.utils::Timer/_timerDispatch()
    at flash.utils::Timer/tick()

また、オブジェクトは揺れませんが、ティックごとに少しずつ左に着実に移動します。

要するに、オブジェクトがステージ/シーンになくなった後にスクリプトを停止する方法と、スクリプトの何が問題なのかわからないので、オブジェクトを振る方法を知りたいのですが、助けてください、ありがとう^_^

4

4 に答える 4

4

AStupidNube は、元の位置について素晴らしい点を指摘しました。したがって、前後の動きであるはずの揺れにそれを追加するため、必要なものが得られる場合と得られない場合があるランダムな値に依存しないでください。シェイクは時間の経過とともに減衰効果もあるため、次のようにしてみてください。

作業コードへのリンク

http://wonderfl.net/c/eB1E - Event.ENTER_FRAME ベース

http://wonderfl.net/c/hJJl - タイマーベース

http://wonderfl.net/c/chYC - Event.ENTER_FRAME に基づいてランダム性を追加

**1 ~ 20 個のシェイク アイテム タイマー ベースのコード - ENTER_FRAME コードについては上記のリンクを参照してください••</p>

package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.utils.Timer;

public class testing extends Sprite {

    private var shakeButton:Sprite;
    private var graphic:Sprite;
    private var shakerPos:Array;
    private var shakers:Array;
    private var numShakers:int = 20;
    private var dir:int = 1;
    private var displacement:Number = 10;
    private var shakeTimer:Timer;

    public function testing() {
        this.shakers = new Array();
        this.shakerPos = new Array();
        this.addEventListener(Event.ADDED_TO_STAGE, this.init);
    }
    private function init(e:Event):void {
        this.stage.frameRate = 30;
        this.shakeTimer = new Timer(33, 20);
        this.shakeTimer.addEventListener(TimerEvent.TIMER, this.shake);
        this.graphics.beginFill(0x333333);
        this.graphics.drawRect(0,0,this.stage.stageWidth, this.stage.stageHeight);
        this.graphics.endFill();

        this.createShakers();

        this.shakeButton = this.createSpriteButton("Shake ");
        this.addChild(this.shakeButton);
        this.shakeButton.x = 10;
        this.shakeButton.y = 10;
        this.shakeButton.addEventListener(MouseEvent.CLICK, this.shakeCallback);
    }
    private function createSpriteButton(btnName:String):Sprite {
        var sBtn:Sprite = new Sprite();
        sBtn.name = btnName;
        sBtn.graphics.beginFill(0xFFFFFF);
        sBtn.graphics.drawRoundRect(0,0,80,20,5);
        var sBtnTF:TextField = new TextField();
        sBtn.addChild(sBtnTF);
        sBtnTF.text = btnName;
        sBtnTF.x = 5;
        sBtnTF.y = 3;
        sBtnTF.selectable = false;
        sBtn.alpha = .5;
        sBtn.addEventListener(MouseEvent.MOUSE_OVER, function(e:Event):void { sBtn.alpha = 1 });
        sBtn.addEventListener(MouseEvent.MOUSE_OUT, function(e:Event):void { sBtn.alpha = .5 });
        return sBtn;
    }
    private function createShakers():void {
        var graphic:Sprite;

        for(var i:int = 0;i < this.numShakers;i++) {
            graphic = new Sprite();
            this.addChild(graphic);
            graphic.graphics.beginFill(0xFFFFFF);
            graphic.graphics.drawRect(0,0,10,10);
            graphic.graphics.endFill();
            // add a 30 pixel margin for the graphic
            graphic.x = (this.stage.stageWidth-60)*Math.random()+30;
            graphic.y = (this.stage.stageWidth-60)*Math.random()+30;
            this.shakers[i] = graphic;
            this.shakerPos[i] = new Point(graphic.x, graphic.y);
        }
    }
    private function shakeCallback(e:Event):void {
        this.shakeTimer.reset();
        this.shakeTimer.start();
    }
    private function shake(e:TimerEvent):void {
        this.dir *= -1;
        var dampening:Number = (20 - e.target.currentCount)/20;
        for(var i:int = 0;i < this.numShakers;i++) {
            this.shakers[i].x = this.shakerPos[i].x + Math.random()*10*dir*dampening;
            this.shakers[i].y = this.shakerPos[i].y + Math.random()*10*dir*dampening;
        }
    }
}

}

これは線形減衰です。値を 2 乗または 3 乗することで、適切と思われるように調整できます。

于 2012-12-03T14:37:54.573 に答える
3

これは、選択した回答の分岐バージョンですが、頻度も設定できるという点で、もう少し柔軟です。また、フレームではなく時間に基づいているため、期間と間隔を設定するときに、フレームではなく時間 (ミリ秒) で考えることができます。

使用法は、選択した回答に似ています。

シェイク (clipToShake、durationInMilliseconds、frequencyInMilliseconds、maxShakeRange);

これは、ENTER_FRAME ではなく TimerEvent を使用するという意味の例にすぎません。また、時間、shakeAmount、および開始位置を追跡するために、シェイクしている MovieClip に動的変数を追加する必要もありません。

    public function shake(shakeClip:MovieClip, duration:Number = 3000, frequency:Number = 30, distance:Number = 30):void
    {
        var shakes:int = duration / frequency;
        var shakeTimer:Timer = new Timer(frequency, shakes);
        var startX:Number = shakeClip.x;
        var startY:Number = shakeClip.y;

        var shakeUpdate:Function = function(e:TimerEvent):void
            {
                shakeClip.x = startX + ( -distance / 2 + Math.random() * distance);
                shakeClip.y = startY + ( -distance / 2 + Math.random() * distance); 
            }

        var shakeComplete:Function = function(e:TimerEvent):void
            {
                shakeClip.x = startX;
                shakeClip.y = startY;
                e.target.removeEventListener(TimerEvent.TIMER, shakeUpdate);
                e.target.removeEventListener(TimerEvent.TIMER_COMPLETE, shakeComplete);
            }

        shakeTimer.addEventListener(TimerEvent.TIMER, shakeUpdate);
        shakeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, shakeComplete);

        shakeTimer.start();
    }
于 2012-12-05T00:26:05.497 に答える
3

元の開始位置を覚えておいて、その時点からシェイク効果を計算する必要があります。これは、MovieClips のシェイク効果です。3 つの変数 (startPosition、shakeTime、maxShakeAmount) を動的に追加します。クラスを使用する場合は、それらをクリップに追加します。

import flash.display.MovieClip;
import flash.geom.Point;

function shake(mc:MovieClip, frames:int = 10, maxShakeAmount:int = 30) : void 
{
    if (!mc._shakeTime || mc._shakeTime <= 0)
    {
        mc.startPosition = new Point(mc.x, mc.y);
        mc._shakeTime = frames;
        mc._maxShakeAmount = maxShakeAmount;
        mc.addEventListener(Event.ENTER_FRAME, handleShakeEnterFrame);
    }
    else
    {
        mc.startPosition = new Point(mc.x, mc.y);
        mc._shakeTime += frames;
        mc._maxShakeAmount = maxShakeAmount;
    }
}

function handleShakeEnterFrame(event:Event):void
{
    var mc:MovieClip = MovieClip(event.currentTarget);
    var shakeAmount:Number = Math.min(mc._maxShakeAmount, mc._shakeTime);
    mc.x = mc.startPosition.x + (-shakeAmount / 2 + Math.random() * shakeAmount);
    mc.y = mc.startPosition.y + (-shakeAmount / 2 + Math.random() * shakeAmount);

    mc._shakeTime--;

    if (mc._shakeTime <= 0)
    {
        mc._shakeTime = 0;
        mc.removeEventListener(Event.ENTER_FRAME, handleShakeEnterFrame);
    }
}

次のように使用できます。

// shake for 100 frames, with max distance of 15px
this.shake(myMc, 100, 15);

ところで: Flash では、「パブリッシュ設定」で「デバッグを許可」を有効にして、より詳細なエラーを表示する必要があります。これにより、コードが壊れている行番号も返されます。


更新:
時間と最大距離が分離されたコードになりました。

于 2012-12-03T14:29:49.097 に答える
0

-4 <= Math.random() * 6 - 4< 2

このオフセットを Machine.x に 20 回追加すると、右よりも左に移動する可能性が高くなります。

次のようなものを探しているようです。

for each (var currentMachine:MovieClip in Machine_mc)
{
     currentMachine.x += Math.random() * 6 - 3;
     currentMachine.y += Math.random() * 6 - 3;
}
于 2012-12-03T14:27:43.637 に答える