2016-10-27 4 views
0

Easel.js의 SpriteSheetBuilder를 사용하여 즉시 스프라이트 시트를 만들었습니다. 내가 가지고있는 문제는 브라우저가 잠기기 전에 캔버스에 약 5 ~ 6 개의 스프라이트 인스턴스 만 그릴 수 있다는 것입니다. 그것은 상당한 CPU 및 메모리 문제를 일으키는 것입니다. 왜 이런 일이 일어나고 있는지 정확히 지적하는 데 문제가 있습니다. 내 구현이어야합니다. 내 스프라이트 시트는 약 100 프레임으로 구성되어 있지만 사용중인 이미지는 각각 8kbs입니다.Easel.js 브라우저가 잠기는 원인이되는 SpriteSheetBuilder()

내가 만들고있는 것은 콩가 라인 애니메이션입니다. 나는 스프라이트 빌더로 댄서 스프라이트에 합성 될면을 얻기 위해 서버를 호출 할 것이다. 이 문제에 대한 통찰력은 대단합니다! 여기 내 코드가있다.

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <title>EaselJS Example: SpriteSheetBuilder</title> 
    <script src="easeljs-0.8.2.min.js"></script> 
    <style> 
     #dancers img { 
      display: none; 
     } 

     canvas { 
      background: red; 
      width: 100%; 
     } 

     button { 
      width: 50px; 
      height: 50px; 
     } 
    </style> 

</head> 

<body> 

<div id="dancers"> 
    <img id="stage" src="stage.jpg"> 
    <img id="curtains" src="curtains.png"> 
    <img id="conga_1" src="conga_1.png"> 
    <img id="conga_2" src="conga_2.png"> 
    <img id="conga_3" src="conga_3.png"> 
    <img id="conga_4" src="conga_4.png"> 
    <img id="conga_5" src="conga_5.png"> 
    <img id="conga_6" src="conga_6.png"> 
    <img id="conga_7" src="conga_7.png"> 
    <img id="conga_8" src="conga_8.png"> 
    <img id="conga_9" src="conga_9.png"> 
    <img id="conga_10" src="conga_10.png"> 
    <img id="conga_11" src="conga_11.png"> 
    <img id="conga_12" src="conga_12.png"> 
    <img id="conga_13" src="conga_13.png"> 
    <img id="conga_14" src="conga_14.png"> 
    <img id="conga_15" src="conga_15.png"> 
    <img id="conga_16" src="conga_16.png"> 
    <img id="conga_17" src="conga_17.png"> 
    <img id="conga_18" src="conga_18.png"> 
    <img id="conga_19" src="conga_19.png"> 
    <img id="conga_20" src="conga_20.png"> 
    <img id="conga_21" src="conga_21.png"> 
    <img id="conga_22" src="conga_22.png"> 
    <img id="conga_23" src="conga_23.png"> 
    <img id="conga_24" src="conga_24.png"> 
    <img id="conga_25" src="conga_25.png"> 
    <img id="conga_26" src="conga_26.png"> 
    <img id="conga_27" src="conga_27.png"> 
    <img id="conga_28" src="conga_28.png"> 
    <img id="conga_29" src="conga_29.png"> 
    <img id="conga_30" src="conga_30.png"> 
    <img id="conga_31" src="conga_31.png"> 
    <img id="conga_32" src="conga_32.png"> 
    <img id="conga_33" src="conga_33.png"> 
    <img id="conga_34" src="conga_34.png"> 
    <img id="conga_35" src="conga_35.png"> 
    <img id="conga_36" src="conga_36.png"> 
    <img id="conga_37" src="conga_37.png"> 
    <img id="conga_38" src="conga_38.png"> 
    <img id="conga_39" src="conga_39.png"> 
    <img id="conga_40" src="conga_40.png"> 
    <img id="conga_41" src="conga_41.png"> 
    <img id="conga_42" src="conga_42.png"> 
    <img id="conga_43" src="conga_43.png"> 
    <img id="conga_44" src="conga_44.png"> 
    <img id="conga_45" src="conga_45.png"> 
    <img id="conga_46" src="conga_46.png"> 
    <img id="conga_47" src="conga_47.png"> 
    <img id="conga_48" src="conga_48.png"> 
    <img id="conga_49" src="conga_49.png"> 
    <img id="conga_50" src="conga_50.png"> 
    <img id="conga_51" src="conga_51.png"> 
    <img id="conga_52" src="conga_52.png"> 
    <img id="conga_53" src="conga_53.png"> 
    <img id="conga_54" src="conga_54.png"> 
    <img id="conga_55" src="conga_55.png"> 
    <img id="conga_56" src="conga_56.png"> 
    <img id="conga_57" src="conga_57.png"> 
    <img id="conga_58" src="conga_58.png"> 
    <img id="conga_59" src="conga_59.png"> 
    <img id="conga_60" src="conga_60.png"> 
    <img id="conga_61" src="conga_61.png"> 
    <img id="conga_62" src="conga_62.png"> 
    <img id="conga_63" src="conga_63.png"> 
    <img id="conga_64" src="conga_64.png"> 
    <img id="conga_65" src="conga_65.png"> 
    <img id="conga_66" src="conga_66.png"> 
    <img id="conga_67" src="conga_67.png"> 
    <img id="conga_68" src="conga_68.png"> 
    <img id="conga_69" src="conga_69.png"> 
    <img id="conga_70" src="conga_70.png"> 
    <img id="conga_71" src="conga_71.png"> 
    <img id="conga_72" src="conga_72.png"> 
    <img id="conga_73" src="conga_73.png"> 
    <img id="conga_74" src="conga_74.png"> 
    <img id="conga_75" src="conga_75.png"> 
    <img id="conga_76" src="conga_76.png"> 
    <img id="conga_77" src="conga_77.png"> 
    <img id="conga_78" src="conga_78.png"> 
    <img id="conga_79" src="conga_79.png"> 
    <img id="conga_80" src="conga_80.png"> 
    <img id="conga_81" src="conga_81.png"> 
    <img id="conga_82" src="conga_82.png"> 
    <img id="conga_83" src="conga_83.png"> 
    <img id="conga_84" src="conga_84.png"> 
    <img id="conga_85" src="conga_85.png"> 
    <img id="conga_86" src="conga_86.png"> 
    <img id="conga_87" src="conga_87.png"> 
    <img id="conga_88" src="conga_88.png"> 
    <img id="conga_89" src="conga_89.png"> 
    <img id="conga_90" src="conga_90.png"> 
    <img id="conga_91" src="conga_91.png"> 
    <img id="conga_92" src="conga_92.png"> 
    <img id="conga_93" src="conga_93.png"> 
    <img id="conga_94" src="conga_94.png"> 
    <img id="conga_95" src="conga_95.png"> 
    <img id="conga_96" src="conga_96.png"> 
    <img id="conga_97" src="conga_97.png"> 
    <img id="conga_98" src="conga_98.png"> 
    <img id="conga_99" src="conga_99.png"> 
    <img id="conga_100" src="conga_100.png"> 
    <img id="conga_101" src="conga_101.png"> 
    <img id="conga_102" src="conga_102.png"> 
    <img id="conga_103" src="conga_103.png"> 
    <img id="conga_104" src="conga_104.png"> 
    <img id="conga_105" src="conga_105.png"> 
    <img id="conga_106" src="conga_106.png"> 
    <img id="conga_107" src="conga_107.png"> 
    <img id="conga_108" src="conga_108.png"> 
</div> 

<div> 
    <canvas id="testCanvas" width="1920" height="1080"></canvas> 
</div> 


<button id="add_dancer" onclick="addDancer();">add dancer</button> 


<script src="jjcoords.js"></script> 
<script id="editable"> 
    var canvas = document.getElementById("testCanvas"); 
    var stage = new createjs.Stage(canvas); 
    var containers = []; 
    var congaDancers = []; 
    var counter = 0; 

    function init() { 

     var stageImg = new createjs.Bitmap(document.getElementById('stage').src); 
     stage.addChild(stageImg); 

     buildSprite(); 

     var curtains = new createjs.Bitmap(document.getElementById('curtains').src); 
     stage.addChild(curtains); 

     createjs.Ticker.addEventListener("tick", tick); 

    } 


    function buildSprite() { 

     var container = createFrame('ryan3.png', document.getElementById(coords[counter].id).src, coords[counter].x, coords[counter].y, coords[counter].scale, coords[counter].rotation); 
     containers.push(container); 


    } 

    function createFrame(consumerImg, dancerFrame, x, y, scale, rot) { 

     var bitmap; 
     var container = new createjs.Container(); 
     var consumerFace = new Image(); 
     consumerFace.src = consumerImg; 
     consumerFace.onload = function() { 


      var dancer = new createjs.Bitmap(dancerFrame); 
      dancer.scaleX = 1.5; 
      dancer.scaleY = 1.5; 
      dancer.regX = dancer.image.width/2 | 0; 
      dancer.regY = dancer.image.height/2 | 0; 
      dancer.x = 100; 
      dancer.y = 100; 

      bitmap = new createjs.Bitmap(consumerFace.src); 

      bitmap.regX = bitmap.image.width/2 | 0; 
      bitmap.regY = bitmap.image.height/2 | 0; 
      bitmap.scaleX = scale; 
      bitmap.scaleY = scale; 
      bitmap.x = x; 
      bitmap.y = y; 
      bitmap.rotation = rot; 
//   bitmap.alpha = .5; 

      container.name = 'ryan' + counter; 
      container.addChild(dancer, bitmap); 
      container.x = 700; 
      container.y = 250; 
      counter++; 
      if (counter < coords.length) { 
       buildSprite(); 

      } else { 
       spriteBuilder(); 
      } 


     }; 

     return container; 

    } 


    function spriteBuilder() { 

     var square = new createjs.Container(); 

//  stage.addChild(containers[107]); 
//  containers[107].y = 500; 
     // create the sprite sheet builder: 
     var builder = new createjs.SpriteSheetBuilder(); 

     var frames = []; 
     for (var j = 0; j < containers.length; j++) { 

      index = builder.addFrame(containers[j], null, 1, function (target, data) { 

      }, j); 
      // save off the index of each frame in order to use when defining the animation: 

      frames.push(index); 
     } 

     // create an animation named square that comprises all of the frames we just added: 
     // we're also telling it to loop the animation and setting a frequency so it updates every 8 ticks: 

     builder.addAnimation("square", frames, true, 1); 


     // run the build operation, and grab the resulting sprite sheet: 
     // we could also do this asynchronously with buildAsync(...) 
     var spriteSheet = builder.build(); 

     var square2 = new createjs.Sprite(spriteSheet, "square"); 
     square2.scaleX = .6; 
     square2.scaleY = .6; 
     square2.x = 250; 
     square2.y = 620; 
     stage.addChild(square2); 

     // add in the generated spritesheet image for demo purposes: 
//   stage.addChild(new createjs.Bitmap(spriteSheet._images[0])).set({x: 75, y: 150}); 
     // we want to do some work before we update the canvas, 
     // otherwise we could use Ticker.addEventListener("tick", stage); 
     congaDancers.push(square2); 
     console.log(congaDancers); 

    } 

    var xpos = 200; 
    function addDancer() { 
     counter = 0; 
     containers = []; 
     buildSprite(); 

     xpos = xpos + 200; 
     congaDancers[congaDancers.length - 1].x = xpos; 

    } 


    function tick() { 

     stage.update(event); 
    } 


    init(); 


</script> 
</body> 
</html> 
+0

이미지를 압축해서 제공 할 수 있습니까? 로컬 테스트를 함께 던지고 명백한 문제가 있는지 확인할 수 있습니다. – Lanny

+0

예! 이것이 전부입니다. https://www.dropbox.com/s/zdpjtla10i96rbi/spriteBuilder.zip?dl=0 –

답변

0

이것은 실제로 매우 간단합니다. 각 댄서에 대해 100 개 이상의 이미지를 캐싱하여 메모리에 이미지/캔버스를 생성합니다. 이것은 댄서 1 인당 75,000,000 픽셀입니다.

스프라이트 시트는 복잡한 콘텐츠를 캐시하는 좋은 방법입니다. 그러나이 많은 텍스처를 드로잉하고 스와핑하면 어떤 이점도 제공하는 대신 해로운 영향을 미칠 수 있습니다.

이렇게하는 더 좋은 방법이 많이 있습니다.

  1. 당신이 정말 다음, SpriteSheets를 사용 하나를 확인하고 맨 위에 사용자 정의 얼굴을 추가하려면

    . 댄서 바디와 페이스 스프라이트/비트 맵을 가진 컨테이너를 생성하십시오. 이 중 많은 부분을 원하는만큼 만들 수 있으며 각각에 대해 새로운 거대한 이미지 세트를 생성 할 수 없습니다.

  2. SpriteSheetBuilder를 사용하여 새로운 SpriteSheet를 작성하는 대신, 이미 작성중인 모든 이미지를 사용하는 정의를 생성하십시오. SpriteSheet는 여러 개의 이미지를 지원하므로 각 프레임이 새로운 이미지를 가리킬 수 있어야합니다. 그런 다음 이전과 동일한 접근 방식을 취하십시오.

  3. 이 작품의 출처는 어디입니까? 본문 부분 이미지를 사용하여 애니메이션을 만들 경우, 비트 맵을 저장하는 대신에 EaselJS에서이를 수행하십시오. 재사용되는 작은 신체 부위의 무리는 더 많은 performant 일 것이다.

  4. 벡터로 시작한 경우 Adobe Animate를 사용하여 벡터를 내보내는 것이 좋습니다. 이렇게하면 대신 사용할 수있는 확장 가능한 벡터 컨텐츠가 생성됩니다. 허락하신다면 캔버스에있는 수많은 벡터가 이상적이지는 않지만 현재의 방식대로 메모리에 과세하지 않을 것입니다.

더 나은 환경을 만들기 위해 이미지를 미리로드하는 것도 고려해 볼 수 있습니다. 희망이 도움이됩니다!

+0

이 의견은 엄청난 도움이됩니다! 정말 감사! 이 시점에서 필자는 스프라이트 시트 접근 방식과 결혼했지만 올바른 방향으로 나를 가리켜 주셔서 감사합니다. 나는 작품을 만들 사람을 고용했다. 내 소스 파일은 Illustrator 및 After Effects에 있습니다. 다음 번에는 Adobe Animate가 갈 길 같습니다. –