2016-07-13 1 views
2

나는이 iso 그리드 게임 (더 정확한 : dimetric 투영, 일반적인 다이아몬드 레이아웃으로 색인 됨)을 작업하고 있고 내지도에 타일을 페인트하기 위해 원형 브러시를 구현하려고했습니다. 어떤 이미지 편집 소프트웨어에서나 마찬가지입니다. 나는 Midpoint Circle Algorithm 시작,하지만 결과는 내가 작은 브러시 크기 중간 격자보다 더 좋은 알고리즘 타일 격자의지도 타일 브러쉬에 대한 iso 격자

enter image description here

1 ~ 7 내가 차라리 이런 식으로 뭔가있을 것입니다 원하는 무엇처럼 보이지 않는, 바로주의 :

enter image description here

는 무시 첫 번째 동그라미가 작성되지 않습니다 물론 그것은 간단합니다. iso 그리드에서 모양 생성을위한 적합한 알고리즘이 있습니까? 나는 아마도 원 모양도 원하지 않지만, 쿼드와 십자 모양/x- 모양을 교대로 사용합니다.

static List<IntVector2> GetBrushCircleCoords(int x0, int y0, int radius) 
{ 
    List<IntVector2> coords = new List<IntVector2>(); 
    int x = radius; 
    int y = 0; 
    int err = 0; 

    while (x >= y) 
    { 
     coords.Add(new IntVector2(x0 + x, y0 + y)); 
     coords.Add(new IntVector2(x0 + y, y0 + x)); 
     coords.Add(new IntVector2(x0 - y, y0 + x)); 
     coords.Add(new IntVector2(x0 - x, y0 + y)); 
     coords.Add(new IntVector2(x0 - x, y0 - y)); 
     coords.Add(new IntVector2(x0 - y, y0 - x)); 
     coords.Add(new IntVector2(x0 + y, y0 - x)); 
     coords.Add(new IntVector2(x0 + x, y0 - y)); 

     y += 1; 
     err += 1 + 2 * y; 
     if (2 * (err - x) + 1 > 0) 
     { 
      x -= 1; 
      err += 1 - 2 * x; 
     } 
    } 
    return coords; 
} 
+1

확실하지 않음 작은 원에 대한 코드를 향상시킵니다. 그러나 당신이 말한대로 실제로 어쨌든 (단지) 원을 원하지는 않을 것입니다. 그러나이 [[가상 픽셀에 대한] 게시물] (http://stackoverflow.com/questions/22881312/c-sharp-drawing-text-using-custom -pixels/22881391 # 22881391)이 관심의 대상이 될 수 있습니다. 일반 그리기 (GDI + 또는 기타)를 사용하여 브러시 픽셀을 선택하는 템플릿을 만드는 방법을 설명합니다. 이 방법을 사용하면 짝수 글꼴을 포함한 모든 그래픽 프리미티브를 사용할 수 있습니다 .. – TaW

+0

** 내 대답에 ** [Edit1] **이 추가되었습니다. – Spektre

답변

4

당신은 당신의 등각 투영 그리드의 레이아웃을 지정하지 않은 : 여기

은 위키 백과에서 가져온 첫 번째 이미지 샘플 코드입니다. 다이아몬드를 구현하는 것이 더 쉽기 때문에 나는 다이아몬드를 가정합니다. 그러나 정수에서 arithmetics는 반경의 반쪽 셀 해상도를 구현하기가 정말로 어렵습니다. 풀 셀 분해 반경 디스크 채우기의 경우 내부 원 테스트가있는 간단한 2 중첩 for을 사용하십시오. 그 결과는 다음과 같습니다

raw

그냥 내 등각 편집기의 나무와 타일 목록 오버레이를 무시합니다. 다음은이에 대한 C++ 소스 코드 : 더 나은 찾고 결과를 조정 반올림 어떤 정수로

(x-x0)^2+(y-y0)^2<=r^2 

:

void isometric::brush_circle(int x0,int y0,int z0,int r) 
    { 
    r--; if (r<0) return; 
    int tp=16; // filling tile 
    int x,y,rx,ry,rxx,ryy,rr=(r+1)*(r+1)-(r>>1); 

    if ((z0>=0)&&(z0<gzs)) 
    for (rx=-r,x=x0+rx,rxx=rx*rx;rx<=r;rx++,x++,rxx=rx*rx) 
    for (ry=-r,y=y0+ry,ryy=ry*ry;ry<=r;ry++,y++,ryy=ry*ry) 
     if (rxx+ryy<rr) 
     if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) 
     map[z0][y][x]=tp; 

    _redraw=true; 
    } 

그것은 디스크/원 방정식을 사용합니다.당신이를 구현하려면

smooth

: 결과가이처럼 가장자리 다듬기를 적용한 후

: 코드는 광산의 등각 엔진을 기반으로 절반 셀 반경 해상도를 사용하면 더 많은 옵션을 얻을 수 있습니다 :

  1. 사용 부동 또는 고정 소수점를 arithmetics
  2. (반올림 회피로) 따라 그래서 그냥 방정식을 업데이트하는 대신 radius 의 연산을 호출로 사용 diameter 내가 # 2 정도 이동

사용 :

(x-x0)^2+(y-y0)^2<=(d^2)/4 

가장 가까운 것은 다음과 같습니다. d=2) :

void isometric::brush_circle(int x0,int y0,int z0,int d) 
    { 
    if ((z0<0)||(z0>=gzs)) return; 
    int tp=16; // filling tile 
    int x,y,rx,ry,rxx,ryy,r=(d>>1)+1,rr=((d*d)-(d>>1))>>2; 
    if (d==2) 
     { 
     x=x0; y=y0; if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     x++;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     y++;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     x--;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     } 
    else 
    for (rx=-r,x=x0+rx,rxx=rx*rx;rx<=r;rx++,x++,rxx=rx*rx) 
     for (ry=-r,y=y0+ry,ryy=ry*ry;ry<=r;ry++,y++,ryy=ry*ry) 
     if (rxx+ryy<=rr) 
     if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) 
     map[z0][y][x]=tp; 
    _redraw=true; 
    } 

raw smooth

는 적어도 하나의 특별한 경우의 추가 필요 이상 rr 일정을 약간 조정할 것 같습니다.

[EDIT1] 점심 식사 후 일부는 더 가르쳐 ... 훨씬 더보기 방정식의 정수 관점에서

은 다음과 같습니다

4*((x-x0)^2 + (y-y0)^2) <= (d^2) 
방법

final

void isometric::brush_circle(int x0,int y0,int z0,int d) 
    { 
    if ((z0<0)||(z0>=gzs)) return; 
    int tp=16; // filling tile 
    int x,y,rx,ry,rxx,ryy,r=(d>>1)+1,dd=(d*d)+d; 
    if (d==2) 
     { 
     x=x0; y=y0; if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     x++;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     y++;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     x--;  if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) map[z0][y][x]=tp; 
     } 
    else 
    for (rx=-r,x=x0+rx,rxx=rx*rx;rx<=r;rx++,x++,rxx=rx*rx) 
     for (ry=-r,y=y0+ry,ryy=ry*ry;ry<=r;ry++,y++,ryy=ry*ry) 
     if ((rxx+ryy)<<2<dd) 
     if ((x>=0)&&(x<gxs)&&(y>=0)&&(y<gys)) 
     map[z0][y][x]=tp; 
    _redraw=true; 
    } 
+0

이것은 매우 도움이됩니다. 소화 할 시간이 필요하지만 첫 번째 샘플 코드는 이미 내 시도보다 훨씬 더 멋지게 작동합니다. – Xarbrough

+0

@Xarbrough 도움이 된 것을 기쁘게 생각합니다. – Spektre