2010-04-30 3 views
8

HTML5 캔버스에서 두 Sprite 간의 충돌을 확인하고 싶습니다. 토론을 위해 두 스프라이트가 모두 IMG 객체이고 충돌은 알파 채널이 0이 아니라는 것을 의미한다고 가정 해 봅시다. 이제이 두 스프라이트 둘 다 객체의 중심을 중심으로 회전 할 수 있지만이 경우 다른 변형은 없습니다. 더 쉽게. +HTML5 캔버스에서 픽셀 완전 충돌 감지

  • 모두
  • 그림 밖으로 모두의 오프셋 (offset)과 같은 코드가 (테스트해야 지역의 대략적인 추정을위한 변환 행렬을 계산 :

    이제 확실한 해결책 나는이 될 함께했다 회전에 대해 계산 된 추가 공간) 교차하는 사각형의 모든 픽셀에 대해

  • 좌표를 변환하고 알파 채널에 대해 계산 된 위치 (가장 가까운 반올림으로 반올림 됨)에서 이미지를 테스트합니다. 첫 번째 히트시 중단됩니다.

내가보기에 문제는 다음과 같습니다. a) JavaScript에 매트릭스 클래스가 없습니다. JavaScript에서이 작업을 수행해야한다는 것을 의미합니다.이 프레임 워크는 매우 느릴 수 있으며, 모든 프레임에서 충돌을 테스트해야합니다. 비싼. 게다가 드로잉 (또는 캔버스가 나를 위해 무엇을하는지, 매트릭스를 설정)에 이미해야 할 일을 복제해야합니다.

내가 여기에 무엇을 놓치고 있는지 그리고 충돌 감지를위한 더 쉬운 해결책이 있는지 궁금합니다.

+0

내가 답변을 찾을 수없는, 나도이 질문을하고 :( – super

답변

6

나는 자바 스크립트 코더가 아니지만, C++에서와 마찬가지로 자바 스크립트에서도 똑같은 최적화 트릭이 작동한다고 상상할 수있다.

모든 픽셀 대신 스프라이트의 모서리를 회전하면됩니다. 효과적으로 당신은 소프트웨어 텍스처 맵핑과 같은 것을 할 것입니다. 다양한 그래디언트 정보를 사용하여 주어진 픽셀의 x, y 위치를 계산할 수 있습니다. 자세한 정보는 소프트웨어 텍스처 매핑을 참조하십시오.

스프라이트를 "히트"및 "히트하지 않은"영역으로 분해 한 경우 주어진 쿼드 트리 분해가 모두 "히트되지 않음", "모두 히트"또는 "가능한 히트"인지를 효과적으로 확인할 수 있습니다 "(즉 히트와 히트하지 않은 픽셀이 포함되어 있습니다. 첫 번째 2 개는 통과하기가 쉽지 않습니다. 마지막 경우 다음 분해 레벨로 이동하여 테스트를 반복하십시오. 이렇게하면 필요한 픽셀 만 확인하면됩니다. "비 히트 '와'히트 '의 큰 부위는 검사와 같은 복잡한 설정을 할 필요가 없습니다.

을 어쨌든 생각의 단지 몇 이잖아.

7

를 내가 뭔가를 복제 할 필요가 I 이미

잘 그리기에해야 할, 새로운 렌더링 컨텍스트를 만들 수, 플롯 하나는, 그것에 흰색 배경 마스크를 회전 lighter에 합성 조작을 설정하고이 지정된 오프셋 (offset) 상단에있는 다른 회전 마스크를 플롯.

왼쪽에 흰색이 아닌 픽셀이 있으면 히트가 있습니다. 당신은 여전히 ​​getImageData해야하고 그것을 찾으려면 픽셀을 체로 치십시오. 결과 이미지를 아래쪽으로 스케일링하여 (앤티 앨리어싱을 사용하여 일부 픽셀을 흰색이 아닌 상태로 유지하는 방식으로) 작업 부하를 조금 줄일 수는 있지만 여전히 느릴 것입니다.

나는이 프레임을 매우 비싸게 만드는 모든 프레임마다 충돌을 테스트해야합니다.

그래, 현실적으로 당신은 미리 계산 된 콜리 전 테이블을 사용하려고합니다. Sprite a, Sprite b, 상대 회전, relative-x-normalized-to-rotation 및 relative-y-normalized-to-rotation의 모든 조합에 대해 히트/비트 없음을 저장할 수 있습니다. . 얼마나 많은 스프라이트를 가지고 있고 얼마나 많은 로테이션이나 이동 단계에 따라 다소 커질 수 있습니다.

각 스프라이트의 사전 회전 된 마스크를 자바 스크립트 배열 (숫자로, 32 비트/픽셀로 쉽게 &&- 가능 데이터를 제공하거나 Sring의 문자로 제공)에 저장하는 것이 좋습니다. 비트) 및 && 교차하는 스프라이트 마스크의 각 행을 함께 표시합니다.

또는 픽셀을 포기하고 예를 들어보기 시작하십시오. 경로.

2

동일한 문제, 대체 솔루션. 먼저 getImageData 데이터를 사용하여 스프라이트를 둘러싼 다각형을 찾습니다. 단일 솔리드 객체를 가진 투명한 배경을 가진 이미지로 구현이 작동하기 때문에 여기에서주의하십시오. 우주선처럼. 다음 단계는 다각형의 정점 수를 줄이기 위해 Ramer Douglas Peucker Algorithm입니다. 마침내 각 스프라이트에 대해 다른 폴리곤과의 충돌을 점검하고 회전을 확인하는 쉽고 저렴한 극소수의 폴리곤을 얻습니다.

http://jsfiddle.net/rnrlabs/9dxSg/

var canvas = document.getElementById("canvas"); 
var context = canvas.getContext("2d"); 
var img = document.getElementById("img"); 

context.drawImage(img, 0,0); 
var dat = context.getImageData(0,0,img.width, img.height); 
// see jsfiddle 
var startPixel = findStartPixel(dat, 0); 
var path = followPath(startPixel, dat, 0); 
// 4 is RDP epsilon 
map1 = properRDP(path.map, 4, path.startpixel.x, path.startpixel.y); 

// draw 

context.beginPath(); 
context.moveTo(path.startpixel.x, path.startpixel.x); 
for(var i = 0; i < map.length; i++) { 
    var p = map[i]; 
    context.lineTo(p.x, p.y); 
} 
context.strokeStyle = 'red'; 
context.closePath(); 
context.stroke();