在XNA上的另一个主题中,Callum Rogers wrote some code创建一个带圆圈轮廓的纹理,但我正在尝试创建一个充满颜色的圆圈。我必须修改此代码以用颜色填充圆圈?
public Texture2D CreateCircle(int radius)
{
int outerRadius = radius*2 + 2; // So circle doesn't go out of bounds
Texture2D texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);
Color[] data = new Color[outerRadius * outerRadius];
// Colour the entire texture transparent first.
for (int i = 0; i < data.Length; i++)
data[i] = Color.Transparent;
// Work out the minimum step necessary using trigonometry + sine approximation.
double angleStep = 1f/radius;
for (double angle = 0; angle < Math.PI*2; angle += angleStep)
{
// Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates
int x = (int)Math.Round(radius + radius * Math.Cos(angle));
int y = (int)Math.Round(radius + radius * Math.Sin(angle));
data[y * outerRadius + x + 1] = Color.White;
}
texture.SetData(data);
return texture;
}
答案 0 :(得分:4)
不要为这样的东西使用纹理(特别是对于单一颜色的东西!) - 也不要尝试逐个像素地进行。你有3D加速的原因。
使用三角形扇形绘制类似于饼图的圆圈。你需要以下顶点。
前两个点将定义圆心和边界之间的直线。第三个顶点将定义第一个多边形。然后,顶点1,3和4将定义第二个多边形等
要获取圆圈边框上的点,请使用示例中的公式。第一个角度为0°,以下为多个(圆圈上的360°/ 点)。要获得一个完整的圆,你需要一个与第二个点(边界上的第一个点)匹配的附加点。
根据圆上顶点的数量,您将获得不同的n-gons。你使用圆形的顶点越多,形状就越好(以某种性能成本):
实际上XNA example for drawing primites显示了如何使用三角扇绘制圆圈(或n-gon)。
答案 1 :(得分:4)
对于任何想要逐像素进行的人来说......我根据给出的信息制定了解决方案。在您的2D纹理方法中,添加以下代码以填充圆圈。我正在制作游戏,希望能够制作不同颜色和大小的圆圈。因此,在CreateCircle(int radius)方法中,在创建轮廓后添加以下代码:
bool finished = false;
int firstSkip = 0;
int lastSkip = 0;
for (int i = 0; i <= data.Length - 1; i++)
{
if (finished == false)
{
//T = transparent W = White;
//Find the First Batch of Colors TTTTWWWTTTT The top of the circle
if ((data[i] == Color.White) && (firstSkip == 0))
{
while (data[i + 1] == Color.White)
{
i++;
}
firstSkip = 1;
i++;
}
//Now Start Filling TTTTTTTTWWTTTTTTTT
//circle in Between TTTTTTW--->WTTTTTT
//transaparent blancks TTTTTWW--->WWTTTTT
// TTTTTTW--->WTTTTTT
// TTTTTTTTWWTTTTTTTT
if (firstSkip == 1)
{
if (data[i] == Color.White && data[i + 1] != Color.White)
{
i++;
while (data[i] != Color.White)
{
//Loop to check if its the last row of pixels
//We need to check this because of the
//int outerRadius = radius * 2 + -->'2'<--;
for (int j = 1; j <= outerRadius; j++)
{
if (data[i + j] != Color.White)
{
lastSkip++;
}
}
//If its the last line of pixels, end drawing
if (lastSkip == outerRadius)
{
break;
finished = true;
}
else
{
data[i] = Color.White;
i++;
lastSkip = 0;
}
}
while (data[i] == Color.White)
{
i++;
}
i--;
}
}
}
}
// Set the data when finished
//-- don't need to paste this part, already given up above
texture.SetData(data);
return texture;
答案 2 :(得分:1)
如果您需要从头开始(尽管我猜测有更简单的方法),请更改执行渲染的方式。而不是迭代角度和绘制像素,迭代像素并确定它们相对于圆的位置。如果它们是<R
,则绘制为填充颜色。如果它们是~= R
,则绘制为边框颜色。
答案 3 :(得分:0)
我知道我有点迟了,但我修改了你的代码以填补中心
public static Texture2D CreateCircle(GraphicsDevice importedGraphicsDevice, int radius)
{
int outerRadius = radius * 2 + 2; // So circle doesn't go out of bounds
Texture2D texture = new Texture2D(importedGraphicsDevice, outerRadius, outerRadius);
Color[] data = new Color[outerRadius * outerRadius];
// Colour the entire texture transparent first.
for (int i = 0; i < data.Length; i++)
data[i] = Color.Transparent;
// Work out the minimum step necessary using trigonometry + sine approximation.
double angleStep = 1f / radius;
for (double angle = 0; angle < Math.PI * 2; angle += angleStep)
{
// Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates
int x = (int)Math.Round(radius + radius * Math.Cos(angle));
int y = (int)Math.Round(radius + radius * Math.Sin(angle));
data[y * outerRadius + x + 1] = Color.White;
}
//width
for (int i = 0; i < outerRadius; i++)
{
int yStart = -1;
int yEnd = -1;
//loop through height to find start and end to fill
for (int j = 0; j < outerRadius; j++)
{
if (yStart == -1)
{
if (j == outerRadius - 1)
{
//last row so there is no row below to compare to
break;
}
//start is indicated by Color followed by Transparent
if (data[i + (j * outerRadius)] == Color.White && data[i + ((j + 1) * outerRadius)] == Color.Transparent)
{
yStart = j + 1;
continue;
}
}
else if (data[i + (j * outerRadius)] == Color.White)
{
yEnd = j;
break;
}
}
//if we found a valid start and end position
if (yStart != -1 && yEnd != -1)
{
//height
for (int j = yStart; j < yEnd; j++)
{
data[i + (j * outerRadius)] = new Color(10, 10, 10, 10);
}
}
}
texture.SetData(data);
return texture;
}