Apply friction - I'm not sure if I'm thinking about this correctly

edited February 2015 in Questions about Code

I've made a trivial sketch of a ball that moves from left to right, and goes through some mud.

Here's an image :

At this point it's started on the left, hit the mud, and as ground to a halt.

The confusion that I'm having is probably based on a misunderstanding of the concepts.


What I'm expecting to happen :

The ball travels along the grass freely, without losing or gaining speed. When the ball hits the 'mud' friction is triggered that slows the balls movement down, though doesn't stop it completely. When the ball is on the other side of the mud it continues moving as usual.

What is happening:

The ball travels freely on the grass. When the ball hits the mud friction is triggered, which can slow the ball down to a complete halt. When the ball exits the mud it's travelling at the same speed that it was when it was in the mud. So when it goes back into the mud a second time it's guaranteed to stop dead.


I've been doing this as I'm trying to follow through Nature Of Code at the moment, and this is related to chapter 2.

So, I'm not too sure what I should do here, or what points I'm missing. Perhaps the logic of this implementation is wrong, I'm thinking that as the friction is only implemented when the ball is in the mud, it won't continue to affect the motion once it's left.

I've tried to change things about but have made a pigs ear each time.

Here's the code, sorry it's a bit long, it's fairly straight forward though. I don't think the last two classes will be of interest, I've included them so that the code runs though if anyone wants to test that way.


edit 1

I've thought about making wind blow from left if the object is moving right and right if it's moving left to force it along, I'm not sure if that's a good way to think or not.

I'm trying to follow the guidelines of the book in that

velocity += acceleration
location += velocity
acceleration *= 0

I think that for this specific example it could be done more simply - but then I wouldn't be using friction and stuff.


Thanks! :)

float height = 300;
float grass = height - 100;

void setup() {
  size(1000, 300);
  b = new ball(random(0, 230), grass);
  m = new mud( 400, grass);
  green = new bottom();
}

ball b;
mud m;
bottom green;

void draw() {
  background(0);
  green.display();
  m.display();

  // wind
  PVector wind = new PVector(0.001, 0);

  b.applyForce(wind);

  // if the ball is in the mud the friction should be activated
  float c = 0.0091;
  float normal = 1;
  float frictionMag = c*normal;
  PVector friction = b.velocity.get();
  friction.normalize();
  friction.mult(-1);
  friction.mult(frictionMag);

  if (b.inmud(m)) {
    b.applyForce(friction);
  }


  b.inmud(m);

  b.display();
  b.edge();
  b.update();
}


class ball {

  PVector location = new PVector();
  PVector velocity = new PVector(0, 0);
  PVector acceleration = new PVector(2.1, 0);
  float mass;



  ball(float x, float y ) {
    location.x = x;
    location.y = y;
    mass = 1;
  }

  void display() {
    fill(255);
    ellipse(location.x, height-100, 30, 30);
  }

  // revle
  void applyForce(PVector force) {
    PVector f = PVector.div(force, mass);
    acceleration.add(f);
  }

  void update() {
    velocity.add(acceleration);
    location.add(velocity);
    acceleration.mult(0);
  }

  void edge() {
    if (location.x > width) {
      location.x = width;
      velocity.x *= -1;
    }
    if (location.x < 0) {
      location.x = 0;
      velocity.x *= -1;
    }
  }

  boolean inmud(mud m) {
    rect(m.position.x + 40, 90, 50, 50);
    rect(m.position.x + 230 - 40 - 50, 90, 50, 50);
    float edge = m.position.x + 230;
    if ((location.x > m.position.x) && (location.x <edge)) {
      text("in the mud", width/2 - 22, 20);

      return true;
    }
    return false;
  }
}

class mud {
  PVector position = new PVector();
  float len = 230;
  float size = position.x + len;

  mud(float x, float y) {
    position.x = x;
    position.y = y;
  }

  void display() {

    fill(#BF771F);
    strokeWeight(4);
    rect(position.x, position.y, len, 35);
  }
}

class bottom {

  PVector b = new PVector();
  bottom() {
    b.x = 0;
    b.y = height-100;
  }

  void display() {
    fill(#49EA4A);
    rect(b.x, b.y, width, height);
  }
}

Comments

  • Just a random note: you should really use standard naming conventions: classes start with an upper-case letter, functions and variables start with a lower-case letter.

    But I'm confused: what you described as happening is exactly what I would expect to happen. Why shouldn't the ball stop when it goes into the mud for long enough?

  • edited February 2015

    cheers Kevin

    Just a random note: you should really use standard naming conventions

    OK cool, I'll google Java naming conventions and try sticking to that

    what you described as happening is exactly what I would expect to happen. Why shouldn't the ball stop when it goes into the mud for long enough?

    Well yeah, that would make sense. I mean, If I rolled a ball and it went through mud without enough initial force then it would come to a stand still.

    Perhaps my phrasing was out, and that what I wanted to do was create something that slowed the ball down to a certain limit, but the ball would then resume it's regular pace once out of the 'mud'

    The problem here is more than likely me, the example that I've given isn't really a real world scenario, or I can't think of a situation that this could physically be possible.

    Perhaps I'm making an error here.

    I thought that I could do it by simply having a speed variable that was effected when the ball was in the mud, but I was trying to stick to this friction > acceleration > velocity > location sort of thing.

    cheers

  • edited February 2015

    Just have a constant as GRASS_SPEED. Then reassign velocity back to it once it's outta the "mud":

    velocity.set(GRASS_SPEED, GRASS_SPEED);

  • @GoToLoop ah yeah, that would work !

    Basically I'm trying to establish whether I've 'done' the exercise that's given...

    Here's the exercise :

    I've changed the code a bit, so that I now have two patches -

    The blue one speeds it up and the brown one slows it down... so it's perpetual now.

    I have done things a bit funky as there are two methods within the ball class for detecting whether it's in either 'mud' or 'quick'... I've heard of (not used) inheritance, I think perhaps this is an application for it?

    In that the mud and quick would be types of 'patch' (or whatever) and that I could then have a detection for patch... I haven't got to that yet though, so perhaps for now I can move on with the book.

    Thanks :)

Sign In or Register to comment.