2012-07-01 23 views
6

Şu anda bir çevrimiçi oyun üzerinde çalışıyorum ve performans nedenleriyle HTML5'in tuvalini kullanmak yerine webgl kullanmaya karar verdim. Ben üç.js framework kullanıyorum ve niyetim hareketli hareketli sprite sahip olmaktır. Spritelar spriteta yerleştirilir ve ben doğru tekniği kullanmak ve zaman geçtikçe Sprite sanatını değiştirmek için UVOffset ve UVScale kullanın. Bu kodun performansını iyileştirmenin bir yolu olup olmadığını merak ediyordum, çünkü şu anda sahada yaklaşık 300 "oyuncu" da yavaşlamaya başlıyor.3.js 'de animasyonlu spriteların performansını iyileştirme

Selamlar

kodumu en önemli parçası aşağıdadır:

var image = THREE.ImageUtils.loadTexture("img/idlew.png"); 

    function addPlayer(){ 
    var mesh = new THREE.Sprite({map:image});//, affectedByDistance: false, useScreenCoordinates: false}); 
    images.push(mesh); 
    mesh.position.set(Math.floor(Math.random() * 500), Math.floor(Math.random() * 500), 10); 
    scene.add(mesh); 
    mesh.uvScale.x = 96/1152; 
    mesh.scale.x = 0.1; 
    mesh.scale.y = 0.1; 
    } 


var imgBackground = new THREE.MeshLambertMaterial({ 
     map:THREE.ImageUtils.loadTexture('img/grass.jpg') 
    }); 


    var background = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000),imgBackground); 


    scene.add(background); 



    scene.add(camera); 
camera.rotation.x = -(Math.PI/2); 
scene.add(new THREE.AmbientLight(0xFFFFFF)); 

addPlayer(); 

    renderer.render(scene, camera); 
    var moveUp = false; 
    tick(); 
    var ticker = 0; 
    var usedOne = 0; 

    function tick(){ 
    ticker++; 
    if(ticker%10==0){ 
     for (var i = 0; i < images.length; i++) { 
     images[i].uvOffset.x = usedOne * 0.0835; 
     }; 
     usedOne++; 
     if(usedOne == 12) usedOne = 0; 
     addPlayer(); 
     addPlayer(); 
     addPlayer(); 
     console.log(images.length); 
    } 
    requestAnimationFrame(tick); 

     renderer.render(scene, camera); 
    } 
+1

Yığın Taşması'na Hoş Geldiniz ve sorunu çözdüğünüze sevindim! Yani, bildiğiniz gibi, aşağıdaki soru bölümündeki yanıtınızı cevaplamak kesinlikle kabul edilebilir ve (kısa bir bekleme süresinden sonra) kabul edilen cevap olarak işaretleyin. Bu, gelecekte aynı konuya giren diğer kişilerin de çözümü daha hızlı bulmasına yardımcı olur. – Toji

cevap

9

Ben bir animasyon doku, canlı örnek gösterilecek kodu örneği yazdım Ofsetleri otomatik olarak işlemek için yazdım.

function TextureAnimator(texture, tilesHoriz, tilesVert, numTiles, tileDispDuration) 
{ 
    // note: texture passed by reference, will be updated by the update function. 

    this.tilesHorizontal = tilesHoriz; 
    this.tilesVertical = tilesVert; 

    // how many images does this spritesheet contain? 
    // usually equals tilesHoriz * tilesVert, but not necessarily, 
    // if there at blank tiles at the bottom of the spritesheet. 
    this.numberOfTiles = numTiles; 
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping; 
    texture.repeat.set(1/this.tilesHorizontal, 1/this.tilesVertical); 

    // how long should each image be displayed? 
    this.tileDisplayDuration = tileDispDuration; 

    // how long has the current image been displayed? 
    this.currentDisplayTime = 0; 

    // which image is currently being displayed? 
    this.currentTile = 0; 

    this.update = function(milliSec) 
    { 
     this.currentDisplayTime += milliSec; 
     while (this.currentDisplayTime > this.tileDisplayDuration) 
     { 
      this.currentDisplayTime -= this.tileDisplayDuration; 
      this.currentTile++; 
      if (this.currentTile == this.numberOfTiles) 
       this.currentTile = 0; 
      var currentColumn = this.currentTile % this.tilesHorizontal; 
      texture.offset.x = currentColumn/this.tilesHorizontal; 
      var currentRow = Math.floor(this.currentTile/this.tilesHorizontal); 
      texture.offset.y = currentRow/this.tilesVertical; 
     } 
    }; 
}  

Sen (örneğin) kullanarak malzemeyi başlatabilir:

var runnerTexture = new THREE.ImageUtils.loadTexture('images/run.png'); 
// a texture with 10 frames arranged horizontally, display each for 75 millisec 
annie = new TextureAnimator(runnerTexture, 10, 1, 10, 75); 
var runnerMaterial = new THREE.MeshBasicMaterial({ map: runnerTexture }); 

ve her önce güncellemek kullanarak kılmasıdır şöyledir: (yukarıdaki bağlantıya çıkarılan) fonksiyonudur

var delta = clock.getDelta(); 
annie.update(1000 * delta); 

Bu yardımcı olur umarız!

+0

Ofsetin otomatik olarak değiştirilmesi için kesinlikle iyi bir yol; Ancak, bunun görüntülemeyi nasıl daha hızlı hale getirdiğini gerçekten anlamıyorum. Şu anda 20 fps'lik bir üst sınırla (sweetspot olarak) ve spritelar her karede (x ve y val) her bir hareketin, her 10 hamlede canlandırmanın (ofsetin değiştirilmesi) değiştiği bir noktadayım. Oluşturma, her çerçeve değişikliğini redone. Şu anda sahip olduğum konu, alanımda çok fazla sprite bulunduğumda çok yavaş ilerliyor ... 100 hareketli hareketli ve UV-ofset'i değiştirirken kamerayı hareket ettirirken son derece yavaşlıyor – Kristof

+0

+1 Bunların 476'sı, hepsinde şeffaflık ve 8 kare animasyon. Bu yöntemi kullanarak hala 30+ fps elde ediyordum. Teşekkürler! – Chad

+0

Merhaba. Aynı fikrin başka bir uygulamasını yazdım ve onu modül olarak paketledim. Ayrıca, uv ofsetini kullanıyorum, ancak tüm hesaplamaları gölgelendiricilere taşıyorum. ne düşünüyorsun? https://github.com/elephanter/AnimatedSprites – Elephant