2012-07-01 24 views
6

में एनिमेटेड स्प्राइट्स के प्रदर्शन में सुधार करना अभी मैं एक ऑनलाइन गेम पर काम कर रहा हूं और प्रदर्शन कारणों से HTML5 के कैनवास की बजाय वेबग्ल का उपयोग करने का निर्णय लिया है। मैं तीन.जेएस ढांचे का उपयोग कर रहा हूं और मेरा इरादा एनिमेटेड स्प्राइट्स ले जाना है। Sprites खुद spritesheets पर रखा जाता है और मैं सही कला का उपयोग करने के लिए यूवी ऑफसेट और यूवीस्केल का उपयोग करता हूं और समय बीतने के दौरान स्प्राइट की कला को स्विच करता हूं। मैं सोच रहा था कि इस कोड के प्रदर्शन में सुधार करने का कोई तरीका है, क्योंकि अभी यह एक ही समय में मैदान पर लगभग 300 "खिलाड़ियों" पर धीमा होना शुरू कर देता है।तीन.जेएस

सादर

के बाद मेरे कोड का सबसे महत्वपूर्ण हिस्सा है:

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

स्टैक ओवरफ़्लो में आपका स्वागत है, और खुशी है कि आपने समस्या को हल किया है! तो आप जानते हैं, नीचे दिए गए उत्तर अनुभाग में अपने प्रश्न का उत्तर देने के लिए पूरी तरह से स्वीकार्य है और (एक संक्षिप्त प्रतीक्षा अवधि के बाद) इसे स्वीकार किए गए उत्तर के रूप में चिह्नित करें। यह उन अन्य लोगों की सहायता करता है जो भविष्य में एक ही मुद्दे में भाग ले सकते हैं, समाधान को तेजी से ढूंढें। – Toji

उत्तर

2

मैं कोड को साकार द्वारा अपने ही सवाल का जवाब बहुत

renderer.render(scene, camera); 

रखकर सुधार किया जा सकता सही जगह पर कोड ताकि की आवश्यकता होने पर इसे केवल कहा जा सके। पर उपलब्ध स्रोत के साथ

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

:

9

मैं कोड का एक उदाहरण एक एनिमेटेड बनावट, पर लाइव उदाहरण प्रदर्शित करने के लिए लिखा है

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

उपयोगी भाग एक समारोह है मैंने ऑफसेट को स्वचालित रूप से संभालने के लिए लिखा था।

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

(उदाहरण के लिए) का उपयोग कर सामग्री को प्रारंभ कर सकते हैं::

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

और प्रत्येक से पहले इसे अद्यतन का उपयोग कर रेंडर: समारोह (ऊपर के लिंक से निकाले) इस प्रकार है

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

आशा है कि इससे मदद मिलती है!

+0

ऑफसेट को स्वचालित रूप से बदलने के लिए निश्चित रूप से एक अच्छा तरीका; हालांकि मैं वास्तव में नहीं देखता कि यह कैसे तेजी से प्रतिपादन कर सकता है। अभी मैं एक बिंदु पर हूं जहां मेरे पास 20fps (जो मिठाईस्पॉट है) की ऊपरी सीमा के साथ एप्लिकेशन है और हर फ्रेम में एनीमेशन बदल रहा है (ऑफसेट बदल रहा है) प्रत्येक फ्रेम में स्प्राइट्स (एक्स और वाई वैल) चल रहा है। प्रतिपादन प्रत्येक फ्रेम परिवर्तन को फिर से शुरू करता है। मेरे पास अब मुद्दा यह है कि मेरे क्षेत्र में बहुत अधिक sprites होने पर प्रतिपादन बहुत धीमा हो जाता है ... कैमरे को ले जाने के दौरान 100 sprites चलती है और यूवी ऑफसेट बदलती है – Kristof

+0

+1 मैंने अपने व्यूपोर्ट को sprites के साथ भर दिया (उनमें से 476) सभी पारदर्शिता और एनीमेशन के 8 फ्रेम के साथ। इस विधि का उपयोग करके मुझे अभी भी 30+ एफपीएस मिल रहा था। धन्यवाद! – Chad

+0

हाय। मैंने एक ही विचार के एक और कार्यान्वयन को लिखा, और इसे मॉड्यूल के रूप में पैक किया। मैं यूवी ऑफसेट का भी उपयोग कर रहा हूं, लेकिन सभी गणनाओं को शेडर्स में ले जाएं। तुम क्या सोचते हो? https://github.com/elephanter/AnimatedSprites – Elephant