2012-07-01 75 views
6

Hiện tại tôi đang làm việc trên một trò chơi trực tuyến và đã quyết định sử dụng webgl thay vì canvas của HTML5 vì lý do hiệu suất. Tôi đang sử dụng khung công tác ba.js và ý định của tôi là di chuyển các hình động. Các sprites mình được đặt trên spritesheets và tôi sử dụng UVOffset và UVScale để sử dụng nghệ thuật phù hợp và chuyển đổi nghệ thuật của Sprite trong thời gian trôi qua. Tôi đã tự hỏi liệu có một cách để cải thiện hiệu suất của mã này, bởi vì ngay bây giờ nó bắt đầu chậm lại ở khoảng 300 "người chơi" trên sân cùng một lúc.Cải thiện hiệu suất của các hình động trong ba.js

Trân

Sau đây là phần quan trọng nhất của mã của tôi:

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

Chào mừng bạn đến với Stack Overflow và vui mừng vì bạn đã sắp xếp sự cố! Vì vậy, bạn biết đấy, nó hoàn toàn chấp nhận được để trả lời câu hỏi của riêng bạn trong phần câu trả lời dưới đây và (sau một thời gian chờ đợi ngắn) đánh dấu nó như là câu trả lời được chấp nhận. Điều này giúp những người khác có thể gặp phải vấn đề tương tự trong tương lai tìm giải pháp nhanh hơn. – Toji

Trả lời

2

Tôi đã trả lời câu hỏi của riêng mình bằng cách nhận ra các mã có thể được cải thiện đáng kể bằng cách đặt

renderer.render(scene, camera); 

Mã ở đúng nơi để nó chỉ được gọi là khi cần.

9

Tôi đã viết một ví dụ về mã để hiển thị một kết cấu hoạt hình, ví dụ sống tại địa chỉ:

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

với nguồn sẵn có tại địa chỉ:

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

Phần hữu ích là một chức năng Tôi đã viết để tự động xử lý offsets. Chức năng (chiết xuất từ ​​các liên kết ở trên) như sau:

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

Bạn có thể khởi tạo các vật liệu sử dụng (ví dụ):

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

và cập nhật nó trước mỗi render bằng cách sử:

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

Hy vọng điều này sẽ hữu ích!

+0

Chắc chắn là một cách tốt đẹp để xử lý bù đắp thay đổi tự động; tuy nhiên tôi không thực sự thấy làm thế nào điều này có thể làm cho rendering nhanh hơn. Ngay bây giờ tôi đang ở một điểm mà tôi có các ứng dụng với một giới hạn trên 20fps (đó là sweetspot) và sprites di chuyển (x và y val) mỗi khung hình, các hình ảnh động thay đổi (thay đổi bù đắp) mỗi 10 di chuyển. Kết xuất làm lại mọi thay đổi khung. Vấn đề tôi có bây giờ là render quá chậm khi tôi có quá nhiều sprites trên lĩnh vực của tôi ... có 100 sprites di chuyển và thay đổi UV-offset trong khi di chuyển máy ảnh cực kỳ chậm – Kristof

+0

+1 Tôi điền khung nhìn của tôi với sprites (476 trong số đó) tất cả đều có độ trong suốt và 8 khung hình hoạt ảnh. Sử dụng phương pháp này tôi vẫn nhận được hơn 30 khung hình/giây. Cảm ơn! – Chad

+0

hi. Tôi đã viết một triển khai thực hiện cùng một ý tưởng, và đóng gói nó như là mô-đun. Tôi cũng sử dụng bù đắp uv, nhưng di chuyển tất cả các tính toán để đổ bóng. bạn nghĩ sao? https://github.com/elephanter/AnimatedSprites – Elephant