글
Technical Article 2004. 10. 14. 13:59두 강체간의 입사각, 입사속도에 따른 충돌후 반사각,속도 구하기
#ifndef MAX
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#endif
#ifndef MIN
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
#endif
typedef struct _FIA_POINT
{
int x;
int y;
} FIA_POINT;
#define BIG_TILE_SIZE ROTATE_CHR_SIZE
#define SMALL_TILE_SIZE 12
#define DOT_PRODUCT(ux,uy,vx,vy) ((ux)*(vx) + (uy)*(vy))
void CollisionResponse(void *pv, BALLSTATE *pBallState, int nStage, int nMapAngle)
{
PCAMELTRYApp pApp = (PCAMELTRYApp)pv;
//
// 1. 공의 위치(다음번에 이동될)에 타일이 있는지 체크
//
FIA_POINT ptAbsPos;
// #ifndef _DEBUG
// ptAbsPos.x = MIN(MAX((pBallState->posX/ PRECISION + pBallState->vX )/BIG_TILE_SIZE , 0),CX_STAGE);
// ptAbsPos.y = MIN(MAX((pBallState->posY/ PRECISION + pBallState->vY )/BIG_TILE_SIZE , 0),CY_STAGE);
// #else
// ptAbsPos.x = ((pBallState->posX) / PRECISION + 24 + pBallState->vX ) / BIG_TILE_SIZE;
// ptAbsPos.y = ((pBallState->posY) / PRECISION + 24 + pBallState->vY ) / BIG_TILE_SIZE;
ptAbsPos.x = (pBallState->posX + pBallState->vX ) / PRECISION / BIG_TILE_SIZE;
ptAbsPos.y = (pBallState->posY + pBallState->vY ) / PRECISION / BIG_TILE_SIZE;
// #endif
if ( 0 == g_cStageMap[nStage][ptAbsPos.y][ptAbsPos.x] )
return; // 충돌되는 타일 없다!
FIA_POINT ptScroll;
ptScroll.x = pApp->ScrollOffsetX / PRECISION; // 스크롤 값
ptScroll.y = pApp->ScrollOffsetY / PRECISION;
FIA_POINT ptCollPixel; // 충돌픽셀 위치
ptCollPixel.x = 0;
ptCollPixel.y = 0;
// 이미지에서 위치에 다른 값 검색 (?)
FIA_POINT ptScreenImgPos; // 스크린 화면에 좌표에 해당하는거 얻어냄( 절대 좌표에서 스크린좌표-상대좌표 로 변환)
// ptScreenImgPos.x = ptAbsPos.x * BIG_TILE_SIZE - ptScroll.x;
// ptScreenImgPos.y = ptAbsPos.y * BIG_TILE_SIZE - ptScroll.y;
// ptScreenImgPos.x = ptAbsPos.x;
// ptScreenImgPos.y = ptAbsPos.y;
ptScreenImgPos.x = (pBallState->posX + pBallState->vX ) / PRECISION - ptScroll.x;
ptScreenImgPos.y = (pBallState->posY + pBallState->vY ) / PRECISION - ptScroll.y;
NativeColor ncClr;
RGBVAL rgb;
int nCollNorX = 0;
int nCollNorY = 0;
int nCollDist = 0;
bool bFound = FALSE;
nCollNorX = (pBallState->posX/PRECISION - ptAbsPos.x*BIG_TILE_SIZE)+1;
nCollNorY = (pBallState->posY/PRECISION - ptAbsPos.y*BIG_TILE_SIZE)+1;
nCollDist = sqrt(nCollNorX * nCollNorX + nCollNorY * nCollNorY);
bFound = TRUE;
//
// //
// // 2. 타일과 공의 충돌픽셀 체크
// //
// for(int nY = ptScreenImgPos.y ; nY < ptScreenImgPos.y + BIG_TILE_SIZE ; nY++ )
// {
// if ( TRUE == bFound )
// break;
//
// for(int nX = ptScreenImgPos.x ; nX < ptScreenImgPos.x + BIG_TILE_SIZE ; nX++ )
// {
// IBITMAP_GetPixel(pApp->ddbBuffer[ROTATE_BUFFER], nX, nY, &ncClr); // BG_BUFFER맞나?
// rgb = IBITMAP_NativeToRGB(pApp->ddbBuffer[ROTATE_BUFFER], ncClr);
//
// if ( rgb != CLEARCOLOR ) // 해당 위치에 타일 픽셀이 있다.
// {
// nCollNorX = (pBallState->posX/PRECISION - ptScroll.x - nX);
// nCollNorY = (pBallState->posY/PRECISION - ptScroll.y - nY);
// nCollDist = sqrt(nCollNorX * nCollNorX + nCollNorY * nCollNorY);
//
// // 공과 충돌
// if ( nCollDist == 12) // 공 위치에서 r=12 주변 만큼 체크
// {
// ptCollPixel.x = nX + ptScroll.x;
// ptCollPixel.y = nY + ptScroll.y;
// if ( nCollDist == 0 )
// nCollDist = 1;
// bFound = TRUE;
// break;
// }
// }
// }
//
//
// }
if ( FALSE == bFound )
return; // 충돌되는 픽셀이 없다~
//
// 3. 반사각과 충돌후 속도 계산
//
// 충돌노멀벡터 normalize 해주고~
nCollNorX /= nCollDist;
nCollNorY /= nCollDist;
// 접선에 대한 노멀벡터
int tabx = -nCollNorX;
int taby = nCollNorY;
// 반사각및 충돌후 속도 구하는 부분 2(N dot L) - L
int vait = DOT_PRODUCT(pBallState->vX, pBallState->vY, tabx, taby);
int vain = DOT_PRODUCT(pBallState->vX, pBallState->vY, nCollNorX, nCollNorY);
int vbit = DOT_PRODUCT(3, 3, tabx, taby); // 2, 2는 벽의 노멀벡터에 해당하는 값으로 치환해야함
int vbin = DOT_PRODUCT(3, 3, nCollNorX, nCollNorY); // = 벽(타일)의 중점과 충돌픽셀의 벡터 = 노멀벡터에 해당
int vafn = vbin*2 / 2;
int vaft = vait;
int xfa = vafn*nCollNorX + vaft*tabx;
int yfa = vafn*nCollNorY + vaft*taby;
// 이단계에서 각에 대해 변환후 변수 치환
// 속도 적용
// pBallState->vX = (xfa * pApp->g_sin[nMapAngle]) / PRECISION;
// pBallState->vY = (yfa * pApp->g_cos[nMapAngle]) / PRECISION;
// pBallState->vX = xfa;
// pBallState->vY = yfa;
pBallState->vX = (xfa * pApp->g_sin[nMapAngle]) / PRECISION;
pBallState->vY = (yfa * pApp->g_cos[nMapAngle]) / PRECISION;
// 속도에 따른 위치 이동
pBallState->posX += pBallState->vX;
pBallState->posY += pBallState->vY;
}
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#endif
#ifndef MIN
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
#endif
typedef struct _FIA_POINT
{
int x;
int y;
} FIA_POINT;
#define BIG_TILE_SIZE ROTATE_CHR_SIZE
#define SMALL_TILE_SIZE 12
#define DOT_PRODUCT(ux,uy,vx,vy) ((ux)*(vx) + (uy)*(vy))
void CollisionResponse(void *pv, BALLSTATE *pBallState, int nStage, int nMapAngle)
{
PCAMELTRYApp pApp = (PCAMELTRYApp)pv;
//
// 1. 공의 위치(다음번에 이동될)에 타일이 있는지 체크
//
FIA_POINT ptAbsPos;
// #ifndef _DEBUG
// ptAbsPos.x = MIN(MAX((pBallState->posX/ PRECISION + pBallState->vX )/BIG_TILE_SIZE , 0),CX_STAGE);
// ptAbsPos.y = MIN(MAX((pBallState->posY/ PRECISION + pBallState->vY )/BIG_TILE_SIZE , 0),CY_STAGE);
// #else
// ptAbsPos.x = ((pBallState->posX) / PRECISION + 24 + pBallState->vX ) / BIG_TILE_SIZE;
// ptAbsPos.y = ((pBallState->posY) / PRECISION + 24 + pBallState->vY ) / BIG_TILE_SIZE;
ptAbsPos.x = (pBallState->posX + pBallState->vX ) / PRECISION / BIG_TILE_SIZE;
ptAbsPos.y = (pBallState->posY + pBallState->vY ) / PRECISION / BIG_TILE_SIZE;
// #endif
if ( 0 == g_cStageMap[nStage][ptAbsPos.y][ptAbsPos.x] )
return; // 충돌되는 타일 없다!
FIA_POINT ptScroll;
ptScroll.x = pApp->ScrollOffsetX / PRECISION; // 스크롤 값
ptScroll.y = pApp->ScrollOffsetY / PRECISION;
FIA_POINT ptCollPixel; // 충돌픽셀 위치
ptCollPixel.x = 0;
ptCollPixel.y = 0;
// 이미지에서 위치에 다른 값 검색 (?)
FIA_POINT ptScreenImgPos; // 스크린 화면에 좌표에 해당하는거 얻어냄( 절대 좌표에서 스크린좌표-상대좌표 로 변환)
// ptScreenImgPos.x = ptAbsPos.x * BIG_TILE_SIZE - ptScroll.x;
// ptScreenImgPos.y = ptAbsPos.y * BIG_TILE_SIZE - ptScroll.y;
// ptScreenImgPos.x = ptAbsPos.x;
// ptScreenImgPos.y = ptAbsPos.y;
ptScreenImgPos.x = (pBallState->posX + pBallState->vX ) / PRECISION - ptScroll.x;
ptScreenImgPos.y = (pBallState->posY + pBallState->vY ) / PRECISION - ptScroll.y;
NativeColor ncClr;
RGBVAL rgb;
int nCollNorX = 0;
int nCollNorY = 0;
int nCollDist = 0;
bool bFound = FALSE;
nCollNorX = (pBallState->posX/PRECISION - ptAbsPos.x*BIG_TILE_SIZE)+1;
nCollNorY = (pBallState->posY/PRECISION - ptAbsPos.y*BIG_TILE_SIZE)+1;
nCollDist = sqrt(nCollNorX * nCollNorX + nCollNorY * nCollNorY);
bFound = TRUE;
//
// //
// // 2. 타일과 공의 충돌픽셀 체크
// //
// for(int nY = ptScreenImgPos.y ; nY < ptScreenImgPos.y + BIG_TILE_SIZE ; nY++ )
// {
// if ( TRUE == bFound )
// break;
//
// for(int nX = ptScreenImgPos.x ; nX < ptScreenImgPos.x + BIG_TILE_SIZE ; nX++ )
// {
// IBITMAP_GetPixel(pApp->ddbBuffer[ROTATE_BUFFER], nX, nY, &ncClr); // BG_BUFFER맞나?
// rgb = IBITMAP_NativeToRGB(pApp->ddbBuffer[ROTATE_BUFFER], ncClr);
//
// if ( rgb != CLEARCOLOR ) // 해당 위치에 타일 픽셀이 있다.
// {
// nCollNorX = (pBallState->posX/PRECISION - ptScroll.x - nX);
// nCollNorY = (pBallState->posY/PRECISION - ptScroll.y - nY);
// nCollDist = sqrt(nCollNorX * nCollNorX + nCollNorY * nCollNorY);
//
// // 공과 충돌
// if ( nCollDist == 12) // 공 위치에서 r=12 주변 만큼 체크
// {
// ptCollPixel.x = nX + ptScroll.x;
// ptCollPixel.y = nY + ptScroll.y;
// if ( nCollDist == 0 )
// nCollDist = 1;
// bFound = TRUE;
// break;
// }
// }
// }
//
//
// }
if ( FALSE == bFound )
return; // 충돌되는 픽셀이 없다~
//
// 3. 반사각과 충돌후 속도 계산
//
// 충돌노멀벡터 normalize 해주고~
nCollNorX /= nCollDist;
nCollNorY /= nCollDist;
// 접선에 대한 노멀벡터
int tabx = -nCollNorX;
int taby = nCollNorY;
// 반사각및 충돌후 속도 구하는 부분 2(N dot L) - L
int vait = DOT_PRODUCT(pBallState->vX, pBallState->vY, tabx, taby);
int vain = DOT_PRODUCT(pBallState->vX, pBallState->vY, nCollNorX, nCollNorY);
int vbit = DOT_PRODUCT(3, 3, tabx, taby); // 2, 2는 벽의 노멀벡터에 해당하는 값으로 치환해야함
int vbin = DOT_PRODUCT(3, 3, nCollNorX, nCollNorY); // = 벽(타일)의 중점과 충돌픽셀의 벡터 = 노멀벡터에 해당
int vafn = vbin*2 / 2;
int vaft = vait;
int xfa = vafn*nCollNorX + vaft*tabx;
int yfa = vafn*nCollNorY + vaft*taby;
// 이단계에서 각에 대해 변환후 변수 치환
// 속도 적용
// pBallState->vX = (xfa * pApp->g_sin[nMapAngle]) / PRECISION;
// pBallState->vY = (yfa * pApp->g_cos[nMapAngle]) / PRECISION;
// pBallState->vX = xfa;
// pBallState->vY = yfa;
pBallState->vX = (xfa * pApp->g_sin[nMapAngle]) / PRECISION;
pBallState->vY = (yfa * pApp->g_cos[nMapAngle]) / PRECISION;
// 속도에 따른 위치 이동
pBallState->posX += pBallState->vX;
pBallState->posY += pBallState->vY;
}
RECENT COMMENT