2011-12-20 2 views
2

마우스 클릭 및 마우스 오버 이벤트가 감지되어야하는 Canvas를 사용하여 html5로 2D 게임을 작성하고 있습니다. 탐지에는 픽셀 완벽해야하며 객체는 직사각형이 아니며 (주택, 이상한 모양의 UI 버튼 ...) 신속하고 신속하게 대응해야합니다. (분명히 무차별 한 힘은 옵션이 아닙니다.)캔버스를 사용한 완벽한 픽셀 2D 마우스 선택

그럼 내가 물어보고 싶은 것은 어떻게 마우스가 어떤 물체인지 알아낼 수 있고 가능한 최적화가 무엇인지에 있습니다.

P.S : 조사를 해보고 QuadTree here을 사용하는 사람을 발견했습니다.

답변

3

저는 픽셀 완벽한 히트를 위해 유령 캔버스의 개념을 설명하는 (날짜가있는) 튜토리얼을 가지고 있습니다. 발각. 튜토리얼은 here입니다. 최신 튜토리얼에 대한 경고를 무시하고 최신 튜토리얼에서는 유령 캔버스 개념을 사용하지 않습니다.

문제는 이미지를 메모리 캔버스에 그리고 나서 getImageData을 사용하여 마우스 클릭의 단일 픽셀을 얻는 것입니다. 그런 다음 그 단일 픽셀이 완전히 투명한지 여부를 확인하십시오.

완전히 투명하지 않은 경우 목표가 있습니다.

완전히 투명하면 다음 개체를 메모리 캔버스에 그리고 반복합니다.

끝 부분에서 메모리 내 캔버스 만 지워야합니다.

getImageData은 느리지 만 픽셀 완전 히트 감지를 원하고 아무 것도 계산하지 않은 경우 유일한 옵션입니다.

다른 방법으로 경로 또는 오프셋이있는 픽셀 배열을 미리 계산할 수 있습니다. 이것은 많은 일이지만 더 빠를 수도 있습니다.예를 들어 투명도가 40x20 인 이미지를 가지고 있다면 투명하거나 그렇지 않은 배열을 계산할 수 있습니다 [40] [20]. 그런 다음 이미지를 (25, 55)로 그리면 마우스 위치에서 해당 위치를 뺀 다음 보았을 때 새 위치가 참인지 테스트 할 수 있습니다. 배열 [posx] [posy].

귀하의 질문에 대한 답변입니다. 제안 사항? 이것이 게임이라면 픽셀 완벽한 탐지를 잊어 버리십시오.

진지하게.

개체를 나타내지 만 픽셀 완벽하지 않은 경로 (일반 자바 스크립트 코드에서는 캔버스가 아님)를 만드십시오. 예를 들어, 집은 이미지에 매우 근접한 삼각형이있는 정사각형 일 수 있습니다 테스트를 치러 올 때 대신에 사용됩니다. 점이 픽셀 완전 감지보다 경로 안에있는 경우 계산하려면 비교적 매우 빠른입니다. 다각형 와인딩 횟수 규칙 탐지에서 포인트를 찾습니다. 그것은 솔직히 최선의 방법입니다.

+0

경계 폴리곤을 계산하기 전에 더 자세히 설명 할 수 있습니까? 튜토리얼 어쩌면? :) – Ethan

+0

튜토리얼을 할 수는 있지만 1-2 일이 걸릴 것입니다. –

+0

훌륭합니다. 고마워. – Ethan

0

HTML5 캔버스는 각 그리기 API 함수를 호출하기 전에 여러 변형을 설정할 수있는 단순한 그리기 플레인입니다. 개체를 만들 수없고 표시 목록이 없습니다. 따라서 이러한 기능을 직접 만들어야하거나 다른 라이브러리를 사용할 수 있습니다. 나는이 관심을 가지고 심지어는이 목적을 위해 라이브러리를 쓴 몇 달 전에

http://www.kineticjs.com/

http://easeljs.com/

. 여기에서 볼 수 있습니다 : http://exsprite.com. 성능 문제가 많았지 만 시간이 부족했기 때문에 최적화 할 수 없었습니다. 그것은 정말로 재미 있었고, 그래서 그것을 완벽하게 만들기 위해 약간의 시간을 기다렸습니다.

+0

이전에 이젤을 사용했는데 성능이 좋지 않다고 생각합니다. – Ethan

2

전통적인 게임 개발의 일반적인 해결책은 클릭 마스크를 만드는 것입니다. 단색으로 별도의 스크린 외부 캔버스에 모든 것을 다시 렌더링 할 수 있습니다 (렌더링은 매우 빨라야합니다). 클릭 한 것을 알아 내고 싶을 때 화면 밖 캔버스의 x/y 좌표에서 색상을 샘플링하기 만하면됩니다. 또한 사용자가 무언가를 클릭 할 경우에만 발생에 보조 캔버스에 렌더링을 최적화 할 수 있습니다

var map = { 
     '#000000' : obj1 
    , '#000001' : obj2 
    , ... 
}; 

:에 가깝다> OBJ 해시 - 당신은 색상을 구축 끝낸다. 다양한 기법을 사용하면 사용자가 클릭 한 캔버스 부분 만 그리도록 추가로 최적화 할 수 있습니다 (예 : 캔버스를 NxN 그리드로 분할 할 수 있습니다 (예 : 20x20 픽셀 사각형의 그리드). 그 사각형에있는 객체 - 그러면 적은 수의 객체 만 다시 그려야 할 것입니다.)

+0

투명 영역이있는 이미지를 단색 객체로 렌더링하려면 어떻게해야합니까? – Ethan

+1

https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html - 단색으로 새 캔버스를 채운 다음 이미지를'destination-in '으로 그릴 때, 당신은 당신은 새로운 캔버스 위에 그릴 수 있습니다. –

0

나는 주석으로 충분하다고 믿는다. 이것은 내가 현재이와 함께 http://untitled.servegame.com

var lastUp = 0; 
function mouseUp(){ 
    mousedown = false; //one of my program globals. 
    var timeNow = new Date().getTime(); 
    if(mouseX == xmouse && mouseY == ymouse && timeNow > lastUp + 100){//if it was a centralized click. (mouseX = click down point, xmouse = mouse's most recent x) and is at least 1/10th of a second after the previous click. 
     lastUp = new Date().getTime(); 
     var elem = document.elementFromPoint(mouseX, mouseY); //get the element under the mouse. 
     var url = extractUrl($(elem).css('background-image')); // function I found here: http://webdevel.blogspot.com/2009/07/jquery-quick-tip-extract-css-background.html 

     imgW = $("#hiddenCanvas").width(); //EVERY art file is 88px wide. thus my canvas element is set to 88px wide. 
     imgH = $(elem).css('height').split('p')[0]; //But they vary in height. (currently up to 200); 

     hiddenCanvas.clearRect(0, 0, imgW, imgH); //so only clear what is necessary. 

     var img = new Image(); 
     img.src = url;       
     img.onload = function(){ 
      //draw this elements image to the canvas at 0,0 
      hiddenCanvas.drawImage(img,0,0); 

      ///This computes where the mouse is clicking the element. 
      var left = $(elem).css('left').split('p')[0]; //get this element's css absolute left. 
      var top = $(elem).css('top').split('p')[0]; 
      offX = left - offsetLeft; //left minus the game rendering element's absolute left. gives us the element's position relative of document 0,0 
      offY = top - offsetTop; 
      offX = mouseX - offX; //apply the difference of the click point's x and y 
      offY = mouseY - offY; 


      var imgPixel = hiddenCanvas.getImageData(offX, offY, 1, 1); //Grab that pixel. Start at it's relative X and it's relative Y and only grab one pixel. 
      var opacity = imgPixel.data[3]; //get the opacity value of this pixel. 

      if(opacity == 0){//if that pixel is fully transparent 
       $(elem).hide(); 
       var temp = document.elementFromPoint(mouseX, mouseY); //set the element right under this one 
       $(elem).show(); 
       elem = temp; 
      } 

      //draw a circle on our hiddenCanvas so when it's not hidden we can see it working! 
      hiddenCanvas.beginPath(); 
      hiddenCanvas.arc(offX, offY, 10, 0, Math.PI*2, true); 
      hiddenCanvas.closePath(); 
      hiddenCanvas.fill(); 


      $(elem).css("top", "+=1"); //apply something to the final element. 

     } 
    } 
} 

에있는, 내 2D 등각 투영 스크롤에 사용자의 의도를 결정하는 방법은 다음과 같습니다

<canvas id="hiddenCanvas" width="88" height="200"></canvas> 

설정 CSS 위치 절대 X = - 숨길 (폭) ;

관련 문제