Xar*_*ugh 3 c# algorithm isometric
我正在研究这种iso网格游戏(更精确:二维投影,以典型的钻石布局编制索引),并希望实现圆形画笔在地图上绘制瓷砖,就像在任何图像编辑软件中一样.我从中点圆算法开始,但立即注意到,结果看起来不像我想要的1到7之间的小画笔大小.
我宁愿有这样的事情:
忽略,第一个圆圈没有填充,当然这很容易.在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;
}
Run Code Online (Sandbox Code Playgroud)
您没有指定等轴网格的布局.我假设钻石,因为它更容易在那里实施.但是在整数算术中很难实现半径的半单元分辨率.对于全细胞分辨率半径盘填充使用简单的2嵌套fors与内圈测试.结果如下:
只需忽略我的Isometric编辑器的树和图块列表覆盖.这里的C++源代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
它使用圆盘/圆方程:
(x-x0)^2+(y-y0)^2<=r^2
Run Code Online (Sandbox Code Playgroud)
使用一些整数舍入调整以获得更好的结果.该代码基于我的这个等距引擎:
应用边缘平滑后,结果如下:
如果要实现半单元半径分辨率,可以获得更多选项,例如:
diameter和调用操作数,而不是radius
所以你只要相应地更新方程式(凑整回避)我去#2所以使用:
(x-x0)^2+(y-y0)^2<=(d^2)/4
Run Code Online (Sandbox Code Playgroud)
我得到的最接近的是(特殊情况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;
}
Run Code Online (Sandbox Code Playgroud)
看起来它需要添加至少一个特殊情况和/或调整rr常量.
[编辑1]午餐后再教一些......
从整数的角度来看,更好的方程是:
4*( (x-x0)^2 + (y-y0)^2 ) <= (d^2)
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)