2016-07-30 69 views
1

我做了Node.js的遊戲,我的我的客戶端數據更新/繪製邏輯實現這樣的:鎖定遊戲數據時更新和渲染

var rendering = false; 
    var waiting_for_data = true; 
    var data_update = false; 

    socket.on('update', function(data){ 

     if(rendering)console.log("rendering"); 

     data_update = true; 
     game_data = data; 
     data_update = false; 

     if(waiting_for_data){ 
     waiting_for_data = false; 
     render(); 
     } 


    }); 

    window.requestAnimFrame = (function(){ 
      return window.requestAnimationFrame  || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        window.oRequestAnimationFrame  || 
        window.msRequestAnimationFrame  || 
        function(/* function */ callback, /* DOMElement */ element){ 
        window.setTimeout(callback, 1000/60); 
        }; 
    })(); 


    function render(){ 


     while(data_update){ 
     console.log("waiting" + data_update); 
     } 

     if(game_data == null)console.log(game_data); 

     rendering = true; 
     //mapa.draw(context, game_data.player_position); 
     renderer.draw(game_data); 
     rendering = false; 

     window.requestAnimFrame(render); 
    } 

    } 

而且我可以看到屏幕的任意位置閃爍我的元素每隔幾秒鐘。當我console.log數據和對象的位置,他們看起來不錯。我應該使用某種鎖還是別的什麼?我的渲染變量var和data_update var是否安全更新數據。還有一件事,服務器每秒發出60次「更新」。

+0

是否打算在每個套接字更新上啓動一個新的渲染器。由於'requestAnimFrame',一次啓動的渲染函數將繼續,在下一次套接字更新時,您再次調用渲染並啓動另一個渲染。現在你有兩個正在運行的,並且你將添加另一個更新。另外,while(data_update)'將會阻塞整個頁面,如果渲染被調用'data_upodate = true'並且將其設置爲true,那麼''game_data '不是必需的。 Javascript是單線程的,不需要鎖定,因爲您永遠不會遇到併發訪問衝突。 – Blindman67

+0

是的,這是我的意圖,當我在io'update'回調中呈現時,每件事情都呈現良好,但是我每隔幾秒鐘就會有一些小的滯後,一個客戶端套接字連接並且屏幕上的對象很少。所以我決定嘗試使用requestAnimFram,因爲我認爲這對渲染性能很好。我知道這個問題是由別的東西引起的,但我仍然不知道爲什麼像game_data這樣的奇怪行爲每當我使用requestAnimFrame時每隔幾秒就會變爲null,而現在我只是好奇而已 – peterSweter

回答

0

你的代碼看起來像你試圖成爲線程安全的。沒有必要。

JavaScript是單線程的。它一次只運行一條指令。它一次只運行一個功能。該功能不能被中斷,除非當前功能完成,否則其他事件將不會被改變。由於它僅僅是順序執行的事實,Javascript是線程安全的最終目標。執行代碼時不能中斷。像socket.on和requestAnimationFrame等所有事件都必須等待當前執行完成才能運行。

// var rendering = false; // not needed 
    var waiting_for_data = true; 
    // var data_update = false; // not needed 

    socket.on('update', function (data) { 
     // this will never run if render is running 
     //data_update = true; // nothing will see this 
     game_data = data; // ONLY this will ever happen between the line above and below 
     // data_update = false; // nothing will see this 

     if (waiting_for_data) { 
      waiting_for_data = false; 
      render(); 
     } 

    }); 


    function render() { 
     // if data_updata is true 
     // then the while loop will have no way to exit and nothing 
     // can change data_update while this loop is running except some code in the loop 
     // JavaScript is single threaded and can only do one thing at a time. 
     //while (data_update) { 
     // console.log("waiting" + data_update); 
     //} 

     // again single thread. Only code in this function can run NOTHING else 
     // can do anything until this function has exited all the way out 
     //rendering = true; 
     renderer.draw(game_data); 
     //rendering = false; 

     requestAnimationFrame(render); 
    }