javascriptnanpong

Ping Pong in Java Script


I'm trying to figure out why Positions are returned NaN in browser. this game being rendered in loop and updated as soon as monitor ready to, that's defined in update() function an runs infinite. reset() function is a part of updating so it will randomly generate headings, also there is a while which corresponds to filtering little and boring movements.

Positions are consist of

  1. A direction which is an Array having x,y times..
  2. A Velocity which is constant during the whole game..
  3. Differ value constitute of time delta indicates how much milliseconds passed from last rendered frame to the new one

I appreciate your help.

//br.js

 

     const ausgebur_Velocity = .002
        class Ball {
            constructor(ballElement) {
                this.ballElement = ballElement
                this.reset()
            }
        
            get x() {
                return parseFloat(getComputedStyle(this.ballElement).getPropertyValue("--x"))
            }
        
            set x(value) {
                this.ballElement.style.setProperty("--x", value)
            }
        
            get y() {
                return parseFloat(getComputedStyle(this.ballElement).getPropertyValue("--y"))
            }
        
            set y(value) {
                this.ballElement.style.setProperty("--y", value)
            }
        
            reset() {
                this.x = 50;
                this.y = 50;
                this.direction = { x: 50, y: 25 }
        
                while (Math.abs(this.direction.x) <= .2 || Math.abs(this.direction.x >= .9)) {
                    const heading = randomNumberBet(0, 2 * Math.PI)
                    this.direction = { x: Math.cos(heading), y: Math.sin(heading) }
        
                }
                this.velocity = ausgebur_Velocity
            }
        
            update(differ) {
                this.x += this.direction.x * this.velocity * differ;
                this.y += this.direction.y * this.velocity * differ;
                console.log(this.x)
                console.log(this.y)
        
            }
        
        }
        
        function randomNumberBet(min, max) {
            return Math.random() * (max - min) + min
        }
        
        
        // Main Script Below
        const ball = new Ball(document.getElementById('ball'))
        
        let lastTime
        function update(time) {
            if (lastTime != null) {
                const differ = time - lastTime
        
                ball.update()
            }
            lastTime = time
        
            window.requestAnimationFrame(update)
        }
        
        window.requestAnimationFrame(update)
        
         
    //style.css
    
        *,
        *::after,
        *::before {
        box-sizing: border-box;
    }
    
    :root {
        --hue: 200;
        --saturation: 50%;
        --foreground: hsl(var(--hue), var(--saturation), 75%);
        --background: hsl(var(--hue), var(--saturation), 25%);
    }
    
    body {
        overflow: hidden;
        margin: 0;
        background-color: var(--background)
    }
    
    .control {
        --position: 50;
    
        position: absolute;
        background-color: var(--foreground);
        top: calc(var(--position)*1vh);
        transform: translateY(-50%);
        width: 1vh;
        height: 10vh;
    }
    
    #player_control {
        left: 1vw;
    }
    
    #pc_control {
        right: 1vw;
    }
    
    #ball {
        --x: 50;
        --y: 50;
    
        position: absolute;
        background-color: var(--foreground);
        left: calc(var(--x)*1vh);
        top: calc(var(--y)*1vh);
        transform: translate(-50%, -50%);
        width: 3vh;
        height: 3vh;
        border-radius: 50%;
    
    }
    
    .score {
        display: flex;
        justify-content: center;
        font-weight: bold;
        font-size: 7vh;
        color: var(--foreground);
    }
    
    .score>* {
        flex-grow: 1;
        flex-basis: 0%;
        padding: 0 2vh;
        margin: 1vh 0;
        opacity: .5;
    }
    
    .score>:first-child {
        text-align: right;
        border-right: .5vh solid var(--foreground);
    }

//ping.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="/style.css">
        <script src="/br.js" type="module"></script>
        <title>PING</title>
    </head>
    
    <body>
        <div class="score">
            <div class="player_score">0</div>
            <div class="pc_score">0</div>
        </div>
    
        <div id="ball"></div>
        <div class="control" id="player_control"></div>
        <div class="control" id="pc_control"></div>
    </body>
    
    </html>

Solution

  • It seems the the problem is that get the coordonates from --x and --y css properties, which are not defined here.

    Using top and left works slightly better but I think you'ill have to improve your algorithms.

    const ausgebur_Velocity = .002
    class Ball {
      constructor(ballElement) {
        this.ballElement = ballElement
        this.reset()
      }
    
      get x() {
        return parseFloat(getComputedStyle(this.ballElement).getPropertyValue("left"))
      }
    
      set x(value) {
        this.ballElement.style.setProperty("left", "" + value + "px")
      }
    
      get y() {
        return parseFloat(getComputedStyle(this.ballElement).getPropertyValue("top"))
      }
    
      set y(value) {
        this.ballElement.style.setProperty("top", "" + value + "px")
      }
    
      reset() {
        this.x = 50;
        this.y = 50;
        this.direction = {
          x: 50,
          y: 25
        }
    
        while (Math.abs(this.direction.x) <= .2 || Math.abs(this.direction.x >= .9)) {
          const heading = randomNumberBet(0, 2 * Math.PI)
          this.direction = {
            x: Math.cos(heading),
            y: Math.sin(heading)
          }
    
        }
        this.velocity = ausgebur_Velocity
      }
    
      update(differ) {
        this.x += this.direction.x * this.velocity * differ;
        this.y += this.direction.y * this.velocity * differ;
        console.log("x", this.x)
        console.log("y", this.y)
    
      }
    
    }
    
    function randomNumberBet(min, max) {
      return Math.random() * (max - min) + min
    }
    
    
    // Main Script Below
    const ball = new Ball(document.getElementById('ball'))
    
    let lastTime
    
    function update(time) {
      if (lastTime != null) {
        const differ = time - lastTime
        ball.update(differ)
      }
      lastTime = time
    
      window.requestAnimationFrame(update)
    }
    
    window.requestAnimationFrame(update)
    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }
    
     :root {
      --hue: 200;
      --saturation: 50%;
      --foreground: hsl(var(--hue), var(--saturation), 75%);
      --background: hsl(var(--hue), var(--saturation), 25%);
    }
    
    body {
      overflow: hidden;
      margin: 0;
      background-color: var(--background)
    }
    
    .control {
      --position: 50;
      position: absolute;
      background-color: var(--foreground);
      top: calc(var(--position)*1vh);
      transform: translateY(-50%);
      width: 1vh;
      height: 10vh;
    }
    
    #player_control {
      left: 1vw;
    }
    
    #pc_control {
      right: 1vw;
    }
    
    #ball {
      --x: 50;
      --y: 50;
      position: absolute;
      background-color: var(--foreground);
      left: calc(var(--x)*1vh);
      top: calc(var(--y)*1vh);
      transform: translate(-50%, -50%);
      width: 3vh;
      height: 3vh;
      border-radius: 50%;
    }
    
    .score {
      display: flex;
      justify-content: center;
      font-weight: bold;
      font-size: 7vh;
      color: var(--foreground);
    }
    
    .score>* {
      flex-grow: 1;
      flex-basis: 0%;
      padding: 0 2vh;
      margin: 1vh 0;
      opacity: .5;
    }
    
    .score>:first-child {
      text-align: right;
      border-right: .5vh solid var(--foreground);
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="/style.css">
      <script src="/br.js" type="module"></script>
      <title>PING</title>
    </head>
    
    <body>
      <div class="score">
        <div class="player_score">0</div>
        <div class="pc_score">0</div>
      </div>
    
      <div id="ball"></div>
      <div class="control" id="player_control"></div>
      <div class="control" id="pc_control"></div>
    </body>
    
    </html>