1

You're in a javascript loop:

The loop spits out random numbers increasing or decreasing by 1. It starts at 10 and begins to loop:

10, 9, 8, 7, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 6

I want to log the peak numbers. So in the list above that would be 10, 9, 7

So I assume I would need to log the last 3 numbers as the script loops. 2 numbers ago(a), 1 number ago(b), current number(c) and check if c<b && a<b then log b if that turned out to be true.

I'm unsure of how to actually store those 3 numbers without them being overwritten. So say I did let current = [current number]; because it's a loop that would always be the current number, but how would I store the previous 2 numbers without having them constant be overwritten while remaining in the loop?

UPDATE:

I'm trying to grab the y value for when the ball bounces highest. So if it bounces 3 times I would have 3 y values (when the ball reached its peak 3 times).

The numbers are being logged in the console.

*** Run the code in full page view

'use strict';

// Todo
// - Make the ball spin
// - Make the ball squish
// - Add speed lines
// - Clear only the ball not the whole canvas


(function () {

  const canvas = document.getElementsByClassName('canvas')[0],
        c = canvas.getContext('2d');


  // -----------------------------------
  // Resize the canvas to be full screen
  // -----------------------------------

  window.addEventListener('resize', resizeCanvas, false);

  function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    // ---------
    // Variables
    // ---------

    var circleRadius = 40,
        circleHeight = circleRadius * 2,
        x = (canvas.width/2) - circleRadius, // inital x position of the ball
        y = (canvas.height/2) - circleRadius, // inital y position of the ball
        fallHeight = y,
        vx = 0, // velocity
        vy = 0, // velocity
        groundHeight = circleHeight,
        bouncePoints = [],
        gravity = 0.8,
        dampening = 0.5,
        pullStrength = 0.04,
        segments = 4,
        bezieCircleFormula = (4/3)*Math.tan(Math.PI/(2*segments)), // http://stackoverflow.com/a/27863181/2040509
        pointOffset = {
          positive: bezieCircleFormula*circleRadius,
          negative: circleRadius-(bezieCircleFormula*circleRadius)
        },
        // Each side has 3 points, bezier 1, circle point, bezier 2
        // These are listed below in clockwise order.
        // So top has: left bezier, circle point, right bezier
        // Right has: top bezier, circle point, bottom bezier
        circlePoints = {
          top: [
            [x+pointOffset.negative, y],
            [x+circleRadius, y],
            [x+pointOffset.positive+circleRadius, y]
          ],
          right: [
            [x+circleHeight, y+pointOffset.negative],
            [x+circleHeight, y+circleRadius],
            [x+circleHeight, y+pointOffset.positive+circleRadius]
          ],
          bottom: [
            [x+pointOffset.positive+circleRadius, y+circleHeight],
            [x+circleRadius, y+circleHeight],
            [x+pointOffset.negative, y+circleHeight]
          ],
          left: [
            [x, y+pointOffset.positive+circleRadius],
            [x, y+circleRadius],
            [x, y+pointOffset.negative]
          ]
        };



    // --------------------
    // Ball squish function
    // --------------------
    // For `side` you can pass `top`, `right`, `bottom`, `left`
    // For `amount` use an interger

    function squish (side, squishAmount) {
      for (let i = 0; i < circlePoints[side].length; i++) {
        if (side === 'top') {
          circlePoints[side][i][1] += squishAmount;
        } else if (side === 'right') {
          circlePoints[side][i][0] -= squishAmount;
        } else if (side === 'bottom') {
          circlePoints[side][i][1] -= squishAmount;
        } else if (side === 'left') {
          circlePoints[side][i][0] += squishAmount;
        }
      }
    }



    // ------------------
    // Animation Function
    // ------------------

    function render () {

      // Clear the canvas
      c.clearRect(0, 0, canvas.width, canvas.height);



      // -----------------
      // Draw the elements
      // -----------------

      // Ground
      c.beginPath();
      c.fillStyle = '#9cccc8';
      c.fillRect(0, canvas.height - groundHeight, canvas.width, groundHeight);
      c.closePath();

      // Shadow
      let distanceFromGround = parseFloat(((y - canvas.height/2) + circleHeight) / (canvas.height/2 - groundHeight/2)).toFixed(4),
          shadowWidth = circleRadius * (1-distanceFromGround+1),
          shadowHeight = circleRadius/6 * (1-distanceFromGround+1),
          shadowX = (x + circleRadius) - shadowWidth/2,
          shadowY = canvas.height - groundHeight/2,
          shadowOpacity = 0.15 * distanceFromGround; // The first value here represents the opacity that will be used when the ball is touching the ground

      c.beginPath();
      c.fillStyle = 'rgba(0,0,0, ' + shadowOpacity + ')';
      c.moveTo(shadowX, shadowY);
      c.bezierCurveTo(shadowX, shadowY - shadowHeight, shadowX + shadowWidth, shadowY - shadowHeight, shadowX + shadowWidth, shadowY);
      c.bezierCurveTo(shadowX + shadowWidth, shadowY + shadowHeight, shadowX, shadowY + shadowHeight, shadowX, shadowY);
      c.fill();
      c.closePath();

      // Bezier circle
      c.beginPath();
      c.fillStyle = '#cf2264';
      c.moveTo(circlePoints.left[1][0], circlePoints.left[1][1]);
      c.bezierCurveTo(circlePoints.left[2][0], circlePoints.left[2][1], circlePoints.top[0][0], circlePoints.top[0][1], circlePoints.top[1][0], circlePoints.top[1][1]);
      c.bezierCurveTo(circlePoints.top[2][0], circlePoints.top[2][1], circlePoints.right[0][0], circlePoints.right[0][1], circlePoints.right[1][0], circlePoints.right[1][1]);
      c.bezierCurveTo(circlePoints.right[2][0], circlePoints.right[2][1], circlePoints.bottom[0][0], circlePoints.bottom[0][1], circlePoints.bottom[1][0], circlePoints.bottom[1][1]);
      c.bezierCurveTo(circlePoints.bottom[2][0], circlePoints.bottom[2][1], circlePoints.left[0][0], circlePoints.left[0][1], circlePoints.left[1][0], circlePoints.left[1][1]);
      c.stroke();
      c.closePath();



      // -------------------------------
      // Recalculate circle co-ordinates
      // -------------------------------

      circlePoints = {
        top: [
          [x+pointOffset.negative, y],
          [x+circleRadius, y],
          [x+pointOffset.positive+circleRadius, y]
        ],
        right: [
          [x+circleHeight, y+pointOffset.negative],
          [x+circleHeight, y+circleRadius],
          [x+circleHeight, y+pointOffset.positive+circleRadius]
        ],
        bottom: [
          [x+pointOffset.positive+circleRadius, y+circleHeight],
          [x+circleRadius, y+circleHeight],
          [x+pointOffset.negative, y+circleHeight]
        ],
        left: [
          [x, y+pointOffset.positive+circleRadius],
          [x, y+circleRadius],
          [x, y+pointOffset.negative]
        ]
      };



      // -----------------
      // Animation Gravity
      // -----------------


      // Increment gravity
      vy += gravity;

      // Increment velocity
      y += vy;
      x += vx;



      // ----------
      // Boundaries
      // ----------

      // Bottom boundary
      if (y + circleHeight > canvas.height - groundHeight/2) {
        y = canvas.height - groundHeight/2 - circleHeight;
        vy *= -1;

        // Dampening
        vy *= dampening;
        vx *= dampening;

        // If the Y velocity is less than the value below, stop the ball
        if (vy > -2.4) {
          dampening = 0;
        }

        fallHeight = fallHeight*dampening;
      }

      // Right boundary
      if (x + circleHeight > canvas.width) {
        x = canvas.width - circleHeight;
        vx *= -1;

        // Dampening
        vy *= dampening;
        vx *= dampening;
      }

      // Left boundary
      if (x + circleHeight < 0 + circleHeight) {
        x = 0;
        vx *= -1;

        // Dampening
        vy *= dampening;
        vx *= dampening;
      }

      // Top boundary
      if (y < 0) {
        y = 0;
        vy *= -1;

        // Dampening
        vy *= dampening;
        vx *= dampening;
      }


      console.log(y);

      requestAnimationFrame(render);
    }



    // -----------
    // Click event
    // -----------

    canvas.addEventListener('mousedown', function (e) {
      let dx = e.pageX - x,
          dy = e.pageY - y;

      if (dampening === 0) {
        dampening = 0.5;
      }

      vx += dx * pullStrength;
      vy += dy * pullStrength;

    });

    render();

  }
  resizeCanvas();

})();
body{
  margin: 0;
}

canvas {
  background: #ddf6f5;
  display: block;
}
<canvas class="canvas"></canvas>
MarioD
  • 1,703
  • 1
  • 14
  • 24
  • 2
    So push them into an array. – epascarello Mar 30 '16 at 23:23
  • Sorry I'm not sure I understand, could you elaborate - what am i pushing into an array? – MarioD Mar 30 '16 at 23:25
  • I think I understand, push all of the numbers in the loop into an array. Then just compare the last 3 numbers in the array as the loop runs. Thank you. – MarioD Mar 30 '16 at 23:28
  • 1
    The peak check would be "if prev is less and next is less" than you found a peak so push that number in the array of peaks. – epascarello Mar 30 '16 at 23:32
  • You only need to remember the last number and whether the sense is increasing or decreasing. If the sense is increasing and the current number is less than the last number, change the sense to decreasing,log the last number and make the current number the last. If the current number is more than the last, the sense is increasing. If the number is the same, keep the sense whatever it is. – RobG Mar 30 '16 at 23:37

4 Answers4

2
for(var a=0,b=1,c=2; c < input.length;) 
{ 
  if(input[b] > input[a] && input[b] > input[c])
  {
    console.log(input[b]);
  }  
  a++;b++;c++;
}
Eric Hartford
  • 16,464
  • 4
  • 33
  • 50
2

As I explained, push them into the array.

var nums = [10, 9, 8, 7, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 6];
var peaks = [];
nums.forEach(function(val, index, arr){ 
    var isPrevLess = index==0 || arr[index-1]<val,  //is the last number less
        isNextLess = index==arr.length-1 || arr[index+1]<val;  //is the next number less
    if (isPrevLess && isNextLess) {  //if both are less it is a peak
        peaks.push(val);
    } 
});
console.log(peaks);
epascarello
  • 204,599
  • 20
  • 195
  • 236
1

If I understand correctly, array arr of length l has a peak at position i if any of these is fulfilled:

  • 0 = i < l-1 and arr[i] > arr[i+1]
  • 0 < i < l-1 and arr[i-1] < arr[i] > l-1
  • 0 < i = l-1 and arr[i] > arr[i-1]
  • 0 = i = l-1

Then, you can use

var peaks = arr.filter(function(n, i, a) {
  return (i===0 || n > a[i-1]) && (i===a.length-1 || n > arr[i+1]);
});
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

You really should post a function that does what you say, then your attempt at a solution. Since that's missing…

function foo(startNum, count) {
  var prev = -Infinity;
  var sense = 'up';
  var curr = startNum;
  
  for (var i=0; i<count; i++) {

    // Randomly add or subtract one from current
    curr += Math.random() < 0.5? -1 : 1;
    
    // If it's a peak, do something. If it's not a peak, do something else
    if (sense == 'up' && curr < prev) {  // Hit peak
      document.write('<br>peak: ' + prev + ' going ' + sense);
    } else {
      document.write('<br>Not peak: ' + prev + ' going ' + sense);
    }

    // Prepare for next loop
    sense = prev > curr? 'down' : prev < curr? 'up' : sense;
    prev = curr;
  }
}

foo(10,20);
RobG
  • 142,382
  • 31
  • 172
  • 209