How to update its components from a requestAnimationFrame on Next.js

Viewed 89

Hello, For reasons of readability I do not add the entirety of my code, so don't panic if you don't see a piece of code called somewhere here.

Problem Summary: I'm drawing in a canvas and displaying the player's ping and fps by updating the ServerInfos component from a requestAnimationFrame, and this results in blocking my move because it's reloading my current component where my canvas

Any help or advice is also welcome! :)

Screen for you to understand the component we are talking about and what it is used for: click for see my screen

ServerInfos component code:

export default function ServerInfos({props}) {

const {left, top, ping, fps} = props

const changeColorByMs = () => {
    if (ping < 80) {
        return '#00FF00'
    } else if (ping < 200) {
        return 'rgb(250, 184, 86)'
    } else {
        return 'rgb(253, 97, 97)'
    }
}

const changeColorByFps = () => {
    if (fps > 50) {
        return '#00FF00'
    } else if (fps > 30) {
        return 'rgb(250, 184, 86)'
    } else {
        return 'rgb(253, 97, 97)'
    }
}

return (
    <>
    <div style = {{
        position : 'absolute',
        left: `${left}px`,
        fontFamily : 'Roboto',
        fontWeight : 'bold',
        fontSize : '20px',
        height : "auto",
        top: `${top}px`,
        margin: "0p",
        paddingLeft: "8px",
        paddingRight: "8px",
        backgroundColor: 'rgba(54, 54, 54, 0.384)',
        pointerEvents: 'none',
        }}>

        <li style = {{ listStyleType : 'none', color : changeColorByMs()}}>{ping} ms</li>
        <li style = {{ listStyleType : 'none', color :changeColorByFps()}}>{fps} fps</li>

    </div>
    </>
)
  }

I am currently in the Canvas component so currently here I am using a useState, which will be used later to update the 'ServerInfos' component

const Canvas = () => {
const [statsData, setStatsData] = useState(null)

This is actualized in an animation function in which is running a 'requestAnimationFrame'

function update() {
     movePlayer() //player movement function

     setStatsData({ // the hook object that I am updating for my component
       left : canvasRef.current.offsetLeft,
       top : canvasRef.current.offsetTop,
       ping : ping,
       fps : fpsFunc() 
})
 requestAnimationFrame(update)
}
  

And here I return my block in which I update my component 'ServerInfos'

   return ( 
    <div ref={ref} tabIndex={-1} onKeyDown={handleKeyDown} onKeyUp={handleKeyUp} className={styles.canvas}>

    <canvas ref={canvasRef}/>

    {statsData ? <ServerInfos props = {{
        left : statsData.left,
        top : statsData.top,
        ping : statsData.ping,
        fps : statsData.fps,
    }}/> : null }

    <div ref={tchatRef} className={styles.personalTchat}>
    <div ref={chatRef} className={styles.messages}>
    </div>
    <ul className={styles.chat}></ul>
        <div className="input-group p-2">
            <input ref={messageRef} id="message"
                   className="form-control form-control-lg"
                   type="text"
                   placeholder="Envoyer un message" autoComplete='off'/>
            <div className="input-group-append">
                <button ref={sendRef} className = {styles.escape}>
                    Envoyer
                </button>
            </div>
        </div>
    </div>
    </div>
)

Indeed so far everything works correctly, the concern being that I use a function to move, and when I add this code below

     setStatsData({ //the object hook I am updating for my component

        left : canvasRef.current.offsetLeft,
        top : canvasRef.current.offsetTop,
        ping : ping,
       fps : fpsFunc() 
     })

In my animation function, then my current component reloads at the speed of the requestAnimationFrame, which has the side effect I think of crippling my players' movement, thus preventing any possible movement action, none of my keys do is discoverable and detected in the movePlayer() function

    function movePLayer() {
    if (keys.z.pressed && lastKey.toLowerCase() === 'z') { 
        emitArray.z(socket)
        ctxRef.current.translate(0, +speed)
    } else if (keys.q.pressed && lastKey.toLowerCase() === 'q') {
        ctxRef.current.translate(+speed, 0)
        emitArray.q(socket)
    } else if (keys.s.pressed && lastKey.toLowerCase() === 's') {
        emitArray.s(socket)
        ctxRef.current.translate(0, -speed)     
    } else if (keys.d.pressed && lastKey.toLowerCase() === 'd') {
        emitArray.d(socket)
        ctxRef.current.translate(-speed, 0)
    } 
   }

on the other hand, the handle functions below detect my movements well:

    const handleKeyUp = (e) => {
    switch (e.key.toLowerCase()) {
      case 'z':
        keys.z.pressed = false
        break
      case 'q':
        keys.q.pressed = false
        break
      case 's':
        keys.s.pressed = false
        break
      case 'd':
        keys.d.pressed = false
        break
    }

    if(!e.shiftKey) {
      emitArray = emitMoveSlow
      speed = 3
    }
  }

const handleKeyDown =  e => { // we detect the keys on the keyboard
    switch (e.key.toLowerCase()) {
      case 'z':
        keys.z.pressed = true
        lastKey = 'z'
        break
      case 'q':
        keys.q.pressed = true
        lastKey = 'q'
        break
  
      case 's':
        keys.s.pressed = true
        lastKey = 's'
        break
  
      case 'd':
        keys.d.pressed = true
        lastKey = 'd'
        break
    }
    if(e.shiftKey) {
      emitArray = emitMoveRun
      speed = 5
    }
  }

Game link so you can see the playerMove issue: http://141.94.31.123:8000/

0 Answers
Related