简体   繁体   中英

Smooth movement in processing?

I want this code to effectively increase the smoothness of the transition between directions (it only works with one key at a time) so that I can use multiple keys. The problem is that whenever I change direction the "Player" stops and then continues in the new direction. I want the "Player" to smoothly transition between directions without having to fully release the active key before pressing the new one.

Main code:

Ball ball;
Player player1;
Player player2;

void setup() {

  size(1368,768);
  frameRate(60);
  noStroke();

  ball = new Ball(width/2, height/2, 30);
  player1 = new Player(0, height/2, 30, 150);
  player2 = new Player(width-30, height/2, 30, 150);

  ball.speedX = -10;
  ball.speedY = random(-5,5);

}

void draw() {

  background(0);

  ball.display();
  ball.move();
  player1.run();
  player2.run();

  //Collision
  if (ball.top() < 0) {
    ball.speedY = -ball.speedY;
  }

  if (ball.bottom() > height) {
    ball.speedY = -ball.speedY;
  }

  if (ball.left() < 0) {
    ball.speedX = 0;
    ball.speedY = 0;
  }

  if (ball.right() > width) {
    ball.speedX = 0;
    ball.speedY = 0;
  }

}

void keyPressed() {

  player1.pressed((key == 'w' || key == 'W'), (key == 's' || key == 'S'));
  player2.pressed((keyCode == UP), (keyCode == DOWN));

}

void keyReleased() {

  player1.released((key == 'w' || key == 'W'), (key == 's' || key == 'S'));
  player2.released((keyCode == UP), (keyCode == DOWN));

}

Player class code:

class Player {

  float x, y;
  int dy = 0;
  float w, h;
  float speedY = 5;
  color c;

  //Constructor
  Player(float tempX, float tempY, float tempW, float tempH){

    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    speedY = 0;
    c = (255);

  }

  void run() {

    display();
    move();

  }

  void display() {

    fill(c);
    rect(x, y-h/2, w, h);

  }

  void move() {

    y += dy * speedY;

  }

  void pressed(boolean up, boolean down) {

    if (up) {dy = -1;}
    if (down) {dy = 1;}

  }

  void released(boolean up, boolean down) {

    if (up) {dy = 0;}
    if (down) {dy = 0;}

  }


}

Thanks in advance!

Add 2 attributes move_up and move_down to the class Player and set the attributes in pressed respectively released :

class Player {

    // [...]
    boolean move_up = false, move_down = false;

    void pressed(boolean up, boolean down) {
        if (up)   {move_up   = true;}
        if (down) {move_down = true;}
    }

    void released(boolean up, boolean down) {
        if (up)   {move_up   = false;}
        if (down) {move_down = false;}
    }
}

Change speedY dependent on the attributes in move . Continuously reduce the speed if neither move_up not move_down is set ( speedY = speedY * 0.95; ). That causes that the player smoothly slows down if no key is pressed. If move_up or move_down is pressed the slightly change the speed dependent on the desired direction. Restrict the speed to a certain interval ( speedY = max(-5.0, min(5.0, speedY)); ):

class Player {
    // [...]

    void move() {
        if (!move_up && !move_down) {speedY *= 0.95;}
        if (move_up)                {speedY -= 0.1;}
        if (move_down)              {speedY += 0.1;}
        speedY = max(-5.0, min(5.0, speedY));
        y += speedY;
    }

    // [...]
}

Class Player :

class Player {

    float x, y;
    float w, h;
    float speedY = 0.0;
    color c;
    boolean move_up = false, move_down = false;

    //Constructor
    Player(float tempX, float tempY, float tempW, float tempH){

        x = tempX;
        y = tempY;
        w = tempW;
        h = tempH;
        c = (255);
    }

    void run() {
        display();
        move();
    }

    void display() {

        fill(c);
        rect(x, y-h/2, w, h);
        println(y);
    }

    void move() {
        if (!move_up && !move_down) {speedY *= 0.95;}
        if (move_up)                {speedY -= 0.1;}
        if (move_down)              {speedY += 0.1;}
        speedY = max(-5.0, min(5.0, speedY));
        y += speedY;
    }

    void pressed(boolean up, boolean down) {
        if (up)   {move_up   = true;}
        if (down) {move_down = true;}
    }

    void released(boolean up, boolean down) {
        if (up)   {move_up   = false;}
        if (down) {move_down = false;}
    }
}

If you want smooth transitions, you're going to have to give up "adding a fixed integer distance" in the key handlers, and instead track which keys are down or not, and then accelerating/decelerating your player every time draw() runs. As simple illustration:

Box box;
boolean[] active = new boolean[256];

void setup() {
  size(500,500);
  box = new Box(width/2, height/2);
}

void draw() {
  pushStyle();
  background(0);
  box.update(active);  // First, make the box update its velocity,
  box.draw();          // then, tell the box to draw itself.
  popStyle();
}

void keyPressed() { active[keyCode] = true; }
void keyReleased() { active[keyCode] = false; }

With a simple box class:

class Box {
  final float MAX_SPEED = 1, ACCELERATION = 0.1, DECELERATION = 0.5;
  float x, y;
  float dx=0, dy=0;

  Box(float _x, float _y) { x=_x; y=_y; }

  void draw() {
    // We first update our position, based on current speed,
    x += dx;
    y += dy;
    // and then we draw ourselves.
    noStroke();
    fill(255);
    rect(x,y,30,30);
  }

  void update(boolean[] keys) {
    if (keys[38]) { dy -= ACCELERATION ; } 
    else if (keys[40]) { dy += ACCELERATION ; }
    else { dy *= DECELERATION; }

    if (keys[37]) { dx -= ACCELERATION ; } 
    else if (keys[39]) { dx += ACCELERATION ; }
    else { dx *= DECELERATION; }

    dx = constrain(dx, -MAX_SPEED, MAX_SPEED);
    dy = constrain(dy, -MAX_SPEED, MAX_SPEED);
  }
}

The important part here is the update code, which updates the box's x and y velocity such that if a directional key is currently pressed, we increase the speeed ( dx / dy ) in that direction. Importantly, if no keys are pressed we also dampen the speed to that it returns to 0.

Finally, to make sure we don't end up with infinite speed, we cap the maximum allowed velocity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM