2012-07-01 16 views
6

In questo momento sto lavorando a un gioco online e ho deciso di utilizzare Webgl anziché la tela HTML5 per motivi di prestazioni. Sto usando il framework three.js e la mia intenzione è di spostare gli sprite animati. Gli sprite stessi sono posizionati su spritesheet e io uso UVOffset e UVScale per usare l'arte giusta e cambiare l'arte dello Sprite durante il tempo che passa. Mi chiedevo se c'è un modo per migliorare le prestazioni di questo codice, perché in questo momento inizia a rallentare a circa 300 "giocatori" sul campo allo stesso tempo.Miglioramento delle prestazioni degli sprite animati in three.js

saluti

Di seguito è la parte più importante del mio codice:

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

Benvenuto in Stack Overflow e felice di aver risolto il problema! Quindi, sai, è perfettamente accettabile rispondere alla tua stessa domanda nella sezione risposte qui sotto e (dopo un breve periodo di attesa) contrassegnarla come risposta accettata. Questo aiuta altre persone che potrebbero incontrare lo stesso problema in futuro a trovare la soluzione più velocemente. – Toji

risposta

2

ho risposto alla mia domanda proprio realizzando il codice potrebbe essere notevolmente migliorata posizionando il

renderer.render(scene, camera); 

Codice nel posto giusto quindi è stato chiamato solo quando necessario.

9

ho scritto un esempio di codice per visualizzare una texture animata, ad esempio dal vivo al:

http://stemkoski.github.com/Three.js/Texture-Animation.html

con sorgente disponibile presso:

http://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Texture-Animation.html

La parte utile è una funzione Ho scritto per gestire gli offset automaticamente. La funzione (estratto dal link qui sopra) è il seguente:

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; 
     } 
    }; 
}  

È possibile inizializzare il materiale utilizzando (per esempio):

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 }); 

e aggiornarlo prima di ogni renda utilizzando:

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

Spero che questo aiuti!

+0

Decisamente un buon modo per gestire automaticamente l'offset cambiando; tuttavia non vedo come questo potrebbe rendere più veloce il rendering. In questo momento sono a un punto in cui ho l'applicazione con un limite superiore di 20 fps (che è lo sweetspot) e gli sprite che si muovono (x e y val) ogni fotogramma, l'animazione che cambia (la variazione dell'offset) ogni 10 mosse. Il rendering ha rifatto ogni cambio di frame. Il problema che ho ora è che il rendering diventa troppo lento quando ho troppi sprite sul mio campo ... avere 100 sprite che si muovono e cambiare l'offset UV mentre si muove la fotocamera diventa estremamente lenta – Kristof

+0

+1 Ho riempito il mio viewport con sprite (476 di loro) tutti con trasparenza e 8 fotogrammi di animazione. Usando questo metodo stavo ancora ottenendo 30+ fps. Grazie! – Chad

+0

ciao. Ho scritto un'altra implementazione della stessa idea e la ho confezionata come modulo. Uso anche l'offset uv, ma trasferisco tutti i calcoli agli shader. cosa ne pensi? https://github.com/elephanter/AnimatedSprites – Elephant