0
votes

I have tried a lot to find a solution for moving a dynamic body smoothly on the screen. Mouse Joint doesn't work for me, it has that rubber band effect that isn't useful for smooth movements. I have also tried to apply linear velocity to make the ball move, but couldn't do it so. What are the options to get a simple touch movement on bodies? For example, similar to Glow Hockey?

The answer need not to be specific to AndEngine. Cocos2d would work for me as well.

I've registered Touch listener, and try to move the body on 'Move' Action using:

public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final ITouchArea pTouchArea, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
         switch(pSceneTouchEvent.getAction()){
         case TouchEvent.ACTION_DOWN:

             break;
            case TouchEvent.ACTION_MOVE:
                strikerBody.setLinearVelocity((pSceneTouchEvent.getX()-strikerBody.getPosition().x * PIXEL_TO_METER_RATIO_DEFAULT),(pSceneTouchEvent.getY()-strikerBody.getPosition().y * PIXEL_TO_METER_RATIO_DEFAULT));

                break;
            case TouchEvent.ACTION_UP:

                 break;
            default:
                break;
        }}

The body does move and in the right direction, but if finger movement is a little faster it runs away from the finger, as magnitude of the velocity increases.

3
i would ask you to add some code, esp. about your linear velocity tries :-)Christian R.
Anyone, any solution?Haider

3 Answers

2
votes

Without using mouse joint movement of physics body not become as easy. If you change some value in mouse joint definition then you definitely get your desire effect.

Default behaviour of mouse joint is so elastic. You have to change it as per your requirement. One value set, I provide to you that work for me. That you check for your side.

mouseJointDef.bodyA = this.mGroundBody;
mouseJointDef.bodyB = body;
mouseJointDef.dampingRatio = 4f;
mouseJointDef.frequencyHz = 30;
mouseJointDef.maxForce = (1000.0f * body.getMass());
mouseJointDef.collideConnected = true;
1
votes

Thanks everyone for the suggestions. I finally got it to work using Linear velocity. It is pretty smooth now. When a user tries to move a body across the screen using touch, the finger sometimes touches the body and occasionally it gets away from it. So, linear velocity is to be assigned in two cases:

  1. When the finger is touching the body while it moves (onAreaTouched)
  2. When the finger is not touching the body and it is still moving (onSceneTouchEvent)

    Using the following lines in both the events it made the movement smooth:

    case TouchEvent.ACTION_MOVE: body.setLinearVelocity((pSceneTouchEvent.getX()-body.getPosition().x * PIXEL_TO_METER_RATIO_DEFAULT),(pSceneTouchEvent.getY()-body.getPosition().y * PIXEL_TO_METER_RATIO_DEFAULT));

0
votes

as far as i can see it, setPosition won't help (because the body would lose it's velocity and that would impact the collision)?

measure the time between two touch events and calculate the velocity depending on that, since velocity is way/time, while your velo is just way (with constant time) -that would explain the low speed during a fast finger movement, wouldn't it?

try something like this:

public class YourTouchListener {
  long lastTouch = 0;
  public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, 
    final ITouchArea pTouchArea, final float pTouchAreaLocalX, 
    final float pTouchAreaLocalY) {

      switch(pSceneTouchEvent.getAction()){
      case TouchEvent.ACTION_DOWN:
        this.lastTouch = System.currentTimeMillis();
        break;
      case TouchEvent.ACTION_MOVE:
        long time = System.getCurrentTimeMillis() - lastTouch;
        if (time > 0)
          strikerBody.setLinearVelocity(
            1000* (pSceneTouchEvent.getX() - strikerBody.getPosition().x * 
              PIXEL_TO_METER_RATIO_DEFAULT)/time,               
            1000 * (pSceneTouchEvent.getY()-strikerBody.getPosition().y * 
              PIXEL_TO_METER_RATIO_DEFAULT)/time);
        break;
      case TouchEvent.ACTION_UP:
        this.lastTouch = 0;
        break;
      default:
        break;
    }
  }
}

i can't promise, that this works correct on the first attempt (bc i'don't know what timeUnit is correct, but i assume seconds, so (1000 * way) / (seconds*1000) should be right) or if it will work at all, never tried it.

perhaps, you'll have to use setPosition(x,y) in case TouchEvent.ACTION_DOWN bc the body will not move without a TouchEvent.ACTION_MOVE and you have no time measured (division by zero)