Tunnelling Problem w/ Interactivity

16 views
Skip to first unread message

anselm bradford

unread,
Jun 24, 2007, 9:21:57 PM6/24/07
to ape-g...@googlegroups.com
I've got a problem with tunnelling when using mouse events to move
particles around. Consider the attached swf (I'm sending this from
gmail so I hope it comes through on the groups page, if not see source
at bottom of this message).

Dragging the bars vertically it's possible to jump one right past the
other fairly easily. Does anyone know of an approach that might help
this sort of tunnelling behavior?
I tried changing the multisample property all the way up to 1000 and
it only made the movement a bit choppy, but didn't seem to affect the
prevalence of tunnelling.

Alec - I noticed that changing the px and py properties directly do
not change the underlying sprite x,y properties. Shouldn't these
change when px or py are changed?

Thanks,
-Ans


This is the source, notice that I have a different class called
DrawingContainer in place of Sprite (for the sprite property in
AbstractItem) so that I can access the underlying particle through
mouse events:

------------------------------------------------------------
Main.as
------------------------------------------------------------

package
{

import org.cove.ape.*;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;

public class Main extends Sprite
{
private var dragging : RectangleParticle;

public function Main()
{

stage.frameRate = 60;
addEventListener(Event.ENTER_FRAME, run);

APEngine.init(1/4);
APEngine.container = this;
APEngine.addMasslessForce(new Vector(0,0));

var defaultGroup:Group = new Group();
defaultGroup.collideInternal = true;

var rp:RectangleParticle = new RectangleParticle(250,300,300,50,0,false);
defaultGroup.addParticle(rp);

var rp2:RectangleParticle = new RectangleParticle(250,50,300,50,0,false);
defaultGroup.addParticle(rp2);

rp.sprite.addEventListener( MouseEvent.ROLL_OVER , rollOverHandler );
rp.sprite.addEventListener( MouseEvent.ROLL_OUT , rollOutHandler );
rp.sprite.addEventListener( MouseEvent.MOUSE_DOWN , mouseDownHandler );
rp.sprite.addEventListener( MouseEvent.MOUSE_UP , mouseUpHandler );
rp.multisample = 10;

rp2.sprite.addEventListener( MouseEvent.ROLL_OVER , rollOverHandler );
rp2.sprite.addEventListener( MouseEvent.ROLL_OUT , rollOutHandler );
rp2.sprite.addEventListener( MouseEvent.MOUSE_DOWN , mouseDownHandler );
rp2.sprite.addEventListener( MouseEvent.MOUSE_UP , mouseUpHandler );
rp2.multisample = 10;


APEngine.addGroup(defaultGroup);
}


private function run(evt:Event):void
{
APEngine.step();
APEngine.paint();
}

private function mouseMoveHandler( event : MouseEvent ) : void
{
dragging.px = mouseX;
dragging.py = mouseY;

dragging.sprite.x = mouseX;
dragging.sprite.y = mouseY;
}

private function mouseDownHandler( event : MouseEvent ) : void
{
//var p : RectangleParticle = event.target as RectangleParticle;
dragging = DrawingContainer(event.target).owner as RectangleParticle;
stage.addEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
}
private function mouseUpHandler( event : MouseEvent ) : void
{
dragging = null;
stage.removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
}

private function rollOverHandler( event : Event ) : void
{
event.target.alpha = .5;
}

private function rollOutHandler( event : Event ) : void
{
event.target.alpha = 1;
}

}
}


------------------------------------------------------------
DrawingContainer.as
------------------------------------------------------------

package org.cove.ape
{

import flash.display.Sprite;

public class DrawingContainer extends Sprite
{
public var owner : AbstractItem;

public function DrawingContainer( owner : AbstractItem )
{
super();
this.owner = owner;
}
}
}


------------------------------------------------------------
AbstractItem.as - line 174
------------------------------------------------------------
changed from

_sprite = new Sprite();
to
_sprite = new DrawingContainer(this);

Inter_Rectangles.swf

Paul

unread,
Jun 25, 2007, 12:37:41 AM6/25/07
to APE General
Anselm, how about adding an invisible, non-colliding particle set to
the mouse position and then use a spring constraint (a mouse spring?)
to connect to the actual particle being moved? This would let you put
a little stretch into the interaction, and fine tune the stiffness of
the mouse spring to get the right feel.

I'm about to try something like this myself.

Paul

anselm bradford

unread,
Jun 25, 2007, 10:15:00 AM6/25/07
to ape-g...@googlegroups.com
Interesting idea, you are essentially talking about the way PopShapes
(http://lab.andre-michelle.com/physics-engine) moves particles around,
is that correct?

-Ans

Paul

unread,
Jun 25, 2007, 11:08:21 AM6/25/07
to APE General
Oh yeah, that's right! And FisixEngine does this too, having it built-
in, allowing you to set the stiffness of the mouseAttacher connection.

I've usually adjusted the stiffness up close to 'rigid' to get the
feel I want, but still I'd guess that it helps to not have a colliding
particle (the one you grab and attach to the mouse) moved so
authoritatively with the mouse location.

But with the speed that Alec is updating APE, he may have already
added a "mouseGrabber" class. :-)

alec cove

unread,
Jun 25, 2007, 4:10:27 PM6/25/07
to APE General

Hey Anslem,

As Paul mentioned, the way to go is to use a 'mouse spring'. The
problem with setting the position directly is that it takes the
particles out of the physical environment of the engine. I suspect
this is why you see mouse springs a lot in the other engines. Also,
the issue with multisampling is that it takes into account the
previous and current position of a particle, and setting px and py
automatically sets prev and curr to the same value. It's something id
like to revisit at some point -- maybe when I'm doing the built in
mouse events, since it would be nice to be able to just drag something
around without a spring and have it work correctly.

On a slightly different subject, I really think you'd be better off
using a class for your dragable rectangle. You'd end up with cleaner
code and you wouldn't have to alter the engine either. Have a look at
these two classes, the main one and the separate class for the
DragRect.
----------------
package {

import org.cove.ape.*;
import flash.events.Event;
import flash.display.Sprite;

[SWF(width="800", height="600", backgroundColor="#336699")]
public class DragTest extends Sprite {

public function DragTest() {

stage.frameRate = 60;
addEventListener(Event.ENTER_FRAME, run);

APEngine.init(1/4);
APEngine.container = this;

var defaultGroup:Group = new Group(true);;

var drA:DragRect = new DragRect(250,300,300,50);
defaultGroup.addParticle(drA);

var drB:DragRect = new DragRect(250,50,300,50);
defaultGroup.addParticle(drB);

APEngine.addGroup(defaultGroup);
}


private function run(evt:Event):void {
APEngine.step();
APEngine.paint();
}
}
}

----------------
package {

import flash.events.MouseEvent;
import org.cove.ape.RectangleParticle;

public class DragRect extends RectangleParticle {

public function DragRect(x:Number, y:Number, width:Number,
height:Number) {

super(x, y, width, height, 0);
sprite.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
sprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);

sprite.addEventListener(MouseEvent.ROLL_OUT, rollOut);
sprite.addEventListener(MouseEvent.ROLL_OVER, rollOver);
}

private function mouseUp (mevt:MouseEvent):void {
sprite.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
}

private function mouseDown (mevt:MouseEvent):void {
sprite.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
}

private function rollOut (mevt:MouseEvent):void {
mevt.target.alpha = 1;
}

private function rollOver (mevt:MouseEvent):void {
mevt.target.alpha = 0.5;
}

private function mouseMove (mevt:MouseEvent):void {
px = mevt.stageX;
py = mevt.stageY;
}
}
}
---------
DragRect is now responsible for its own events, you dont have to add
them each time. Also, you gain the scope of the events being within
the class, and because of that you don't have to do any stuff with
'owner'.

Thanks,
Alec

anselm bradford

unread,
Jun 26, 2007, 3:29:07 PM6/26/07
to ape-g...@googlegroups.com
Thanks for the advice Paul and Alec,

I would like to have the effect of dragging a particle around
directly, as opposed to having it look like the particle is being
dragged by a rubber band. I imagine I could set the "mouse spring" to
have no elasticity, but would I still run into the problem of
tunnelling do you think since a particle dragging at the speed of the
cursor will be moving faster than one that is being tugged around by
an elastic spring?

Alec, sorry if you've mentioned this before, but when do you hope to
have the mouse events included?

-Ans

alec cove

unread,
Jun 26, 2007, 5:07:12 PM6/26/07
to APE General

If you need to have better collision I think the only way to go is to
use the spring. It should work even if the spring is of a very short
length, but youre right, it will still seem like there's a spring
attached. I would try tweaking both the multisample and the
constraintCollisionCycles settings.

As far as the mouse events, I'm not sure. I'm working on collision
events and forces for the 0.5 release, and after that angular
constraints. Mouse events might show up around 0.7. Until then youll
have to do it by using the objects sprite (as you've been doing).

-Alec

On Jun 26, 3:29 pm, "anselm bradford" <anselmbradf...@gmail.com>
wrote:


> Thanks for the advice Paul and Alec,
>
> I would like to have the effect of dragging a particle around
> directly, as opposed to having it look like the particle is being
> dragged by a rubber band. I imagine I could set the "mouse spring" to
> have no elasticity, but would I still run into the problem of
> tunnelling do you think since a particle dragging at the speed of the
> cursor will be moving faster than one that is being tugged around by
> an elastic spring?
>
> Alec, sorry if you've mentioned this before, but when do you hope to
> have the mouse events included?
>
> -Ans
>

anselm bradford

unread,
Jun 26, 2007, 7:46:21 PM6/26/07
to ape-g...@googlegroups.com
Huh, how do I set the length of a spring constant to be very short? I
created a non-collidable particle for the mouse and attached it to one
of the rectangles, but how do I make it shorter than the default that
appears when stiffness is set to 1?

Thanks,
-Ans

alec cove

unread,
Jun 26, 2007, 7:53:35 PM6/26/07
to APE General
you can set the restLength property. the restLength is initially
calculated as the distance between the two attached particles, but you
can set it lower if you want.

var sc:SpringConstraint = new SpringConstraint(p1,p2,1);
sc.restLength = 0.1;

HTH,
Alec

On Jun 26, 7:46 pm, "anselm bradford" <anselmbradf...@gmail.com>
wrote:


> Huh, how do I set the length of a spring constant to be very short? I
> created a non-collidable particle for the mouse and attached it to one
> of the rectangles, but how do I make it shorter than the default that
> appears when stiffness is set to 1?
>
> Thanks,
> -Ans
>

Reply all
Reply to author
Forward
0 new messages