Fork me on GitHub
Not signed in (Sign In)

Welcome, Guest

Want to take part in these discussions? Sign in if you have an account, or apply for one below

    • CommentAuthorpsilos
    • CommentTimeNov 14th 2008 edited
     
    Hello again,

    I am trying to implement a 3D SnowBall effect,

    I would like to ask for some more advice,
    My restrictions is that there is not any BoundingSphere Class, so I am using BoundingBox for now.

    My idea was to use Brownian Motion for the snow inside the Ball/Box which works fine, and to apply some gravity in the floor of the cube.

    So, I have added 4 Actions ( TurnTowardsPoint ) in the 4 corners of the cube,

    The result is not the best, is it any way, to stop them moving only if they hit the floor of the cube?

    Adding another BoundingBox with Collide = 0, doesn't seem to work either.

    Thanks in advance for any help.

    Here is my code so far:

    public class SnowMotion extends Emitter3D
    {
    public function SnowMotion()
    {
    counter = new Blast( 100 );

    addInitializer( new PV3DObjectClass( Particle, null, 4 ) );
    addInitializer( new ColorInit( 0xFFFFFFFF, 0xFFFFFFFF ) );
    addInitializer( new MassInit( 1 ) );
    addInitializer( new CollisionRadiusInit( 2 ) );
    addInitializer( new ApplyMaterial( ParticleMaterial, 0xFFFFFF, 1, ParticleMaterial.SHAPE_CIRCLE ) );

    addInitializer( new Position( new BoxZone( 100, 100, 100, new Vector3D( 0, 0, 70 ), new Vector3D( 0, 1, 0 ), new Vector3D( 0, 0, 1 ) ) ) );
    addInitializer( new Velocity( new SphereZone( new Vector3D( 0, 0, 70 ), 120, 100 ) ) );

    //addAction( new Accelerate( new Vector3D( 0, 0, -5) ) );
    addAction( new Move() );
    addAction( new Collide( 1 ) );
    addAction( new BoundingBox( -81, 81, -81, 81, -11, 150, 0 ) );

    addAction( new TurnTowardsPoint( new Vector3D( 100, -100, 0), 10 ) );
    addAction( new TurnTowardsPoint( new Vector3D( 100, 100, 0), 10 ) );
    addAction( new TurnTowardsPoint( new Vector3D( -100, 100, 0), 10 ) );
    addAction( new TurnTowardsPoint( new Vector3D( -100, -100, 0), 10 ) );
    }
    }
    • CommentAuthorRichard
    • CommentTimeNov 17th 2008
     
    I would suggest a model based more closely on how a snowglobe actually works - a downward acceleration, a high drag factor, and low collision coefficient. Add in actions to "shake" the globe - i.e. apply large random accelerations to the particles over a short period of time (the drag factor will damp them down quickly as soon as you stop) - and turn these actions on and off when you need them.
    • CommentAuthorpsilos
    • CommentTimeNov 17th 2008 edited
     
    Thank you for your suggestions, I am trying to implement them,

    but how can I add these random Actions and switch them on and off?

    I have tried to use your example like this, but doesn't work:


    public class ShakeGlobe extends ActionBase
    {
    private var _isDown:Boolean;
    private var shake:Accelerate;

    public function ShakeGlobe( stage:DisplayObject )
    {
    _isDown = false;
    stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownListener, false, 0, true );
    stage.addEventListener( KeyboardEvent.KEY_UP, keyUpListener, false, 0, true );
    }

    private function keyDownListener( ev:KeyboardEvent ):void
    {
    if( ev.keyCode == Keyboard.SHIFT )
    {
    _isDown = true;
    }
    }
    private function keyUpListener( ev:KeyboardEvent ):void
    {
    if( ev.keyCode == Keyboard.SHIFT )
    {
    _isDown = false;
    }
    }

    override public function update( emitter:Emitter, particle:Particle, time:Number ):void
    {
    if( particle.mass == 1 )
    {
    if( _isDown )
    {
    shake = new Accelerate ( new Vector3D ( 0, 0, 65) );
    emitter.addAction( shake );
    }
    else
    {
    if(emitter.hasAction( shake ))
    {
    emitter.removeAction( shake );
    }
    }
    }
    }


    It would be great if you can provide an example, thanks a lot
    • CommentAuthorRichard
    • CommentTimeNov 18th 2008
     
    Try something like this (note: I haven't tested this at all) ...

    package
    {
    public class ShakeGlobe extends ActionBase
    {
    private var shake:Accelerate;

    public function ShakeGlobe( stage:DisplayObject )
    {
    shake = new Accelerate ( new Vector3D ( 0, 0, 65) );
    stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownListener, false, 0, true );
    stage.addEventListener( KeyboardEvent.KEY_UP, keyUpListener, false, 0, true );
    }

    private function keyDownListener( ev:KeyboardEvent ):void
    {
    if( ev.keyCode == Keyboard.SHIFT )
    {
    emitter.addAction( shake );
    }
    }
    private function keyUpListener( ev:KeyboardEvent ):void
    {
    if( ev.keyCode == Keyboard.SHIFT )
    {
    emitter.removeAction( shake );
    }
    }
    }
    }
    • CommentAuthorpsilos
    • CommentTimeNov 18th 2008 edited
     
    Really thank you for the answers,

    but how do I get access to the referenced emitter now?
    My guess is that I would need to update the emitter as well, is that right?

    Thanks
    • CommentAuthorRichard
    • CommentTimeNov 18th 2008 edited
     
    Yes, firing from the hip I didn't think of that. You could use the addedToEmitter method to store a reference to the emitter -

    package
    {
    public class ShakeGlobe extends ActionBase
    {
    private var shake:Accelerate;
    private var emitter:Emitter;

    public function ShakeGlobe( stage:DisplayObject )
    {
    shake = new Accelerate ( new Vector3D ( 0, 0, 65) );
    stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownListener, false, 0, true );
    stage.addEventListener( KeyboardEvent.KEY_UP, keyUpListener, false, 0, true );
    }

    private function keyDownListener( ev:KeyboardEvent ):void
    {
    if( emitter && ev.keyCode == Keyboard.SHIFT )
    {
    emitter.addAction( shake );
    }
    }
    private function keyUpListener( ev:KeyboardEvent ):void
    {
    if( emitter && ev.keyCode == Keyboard.SHIFT )
    {
    emitter.removeAction( shake );
    }
    }

    private function addedToEmitter( emitter:Emitter ):void
    {
    this.emitter = emitter;
    }
    private function removedFromEmitter( emitter:Emitter ):void
    {
    this.emitter = null;
    }
    }
    }
    • CommentAuthorpsilos
    • CommentTimeNov 18th 2008
     
    Thanks a lot Richard,
    this is working perfectly now, but unfortunately could not find an Action to apply for realistic shaking the snow.

    The initializer seems quite realistic now like this:


    public class SnowMotion extends Emitter3D
    {
    protected static const BOX_SIZE:Number = 160;
    protected static const OFFSET:Vector3D = new Vector3D(0, 0, 70);

    public function SnowMotion( stage:DisplayObject)
    {
    counter = new Blast( 150 );

    addInitializer( new PV3DObjectClass( Particle, null, 4 ) );
    addInitializer( new ColorInit( 0xFFFFFFFF, 0xFFFFFFFF ) );
    addInitializer( new MassInit( 1 ) );
    addInitializer( new CollisionRadiusInit( 2 ) );
    addInitializer( new ApplyMaterial( ParticleMaterial, 0xFFFFFF, 1, ParticleMaterial.SHAPE_CIRCLE ) );
    addInitializer( new Position( new BoxZone( BOX_SIZE, BOX_SIZE, BOX_SIZE, OFFSET, new Vector3D( 0, 1, 0 ), new Vector3D( 0, 0, 1 ) ) ) );
    addInitializer( new Velocity( new SphereZone( new Vector3D( 0, 0, 70 ), 130, 120 ) ) );

    addAction( new Accelerate( new Vector3D( 0, 0, -5) ) );
    addAction( new Move() );
    addAction( new Collide( 0.5 ) );
    addAction( new BoundingBox( -81, 81, -81, 81, 20, 150, 1 ) );
    addAction( new SpeedLimit( 60 ) );
    addAction( new LinearDrag( 0.15 ) );
    addAction( new ShakeGlobe( stage, this ) );
    }
    }



    So, I was thinking how can I accelerate my particles again to fill this Position and Velocity as Initial, I have already tried different approaches like accelerate, targetVelocity, Jet, etc but no luck.

    Any ideas?

    Thanks