绘制游戏中的网状能力图

绘制游戏中的网状能力图

先上个效果图:

这里写图片描述

下面分解绘制的过程:

我们先把这个图分解出一个图,然后逐一的绘制,然后在组合起来,这样我们想要的view就出来了。

步骤一:

我们需要绘制最基础的部分,就是多边形。

这里首先想到的就是path,通过他的lineTo()方法可以绘制出各种形状的图形,只要我们给出有规律的点阵。

绘制多边形要确定多边形的所有的点的坐标,如何确定?

这里写图片描述

这里要用到我们以前学过的三角函数了,sin和cos 我们有两个已知条件一个是角度,一个是斜边(斜边就是我们的半径了),我们通过sin和cos分别求出点的x坐标和y坐标,然后就可以绘制多边形了。

步骤二:

绘制完一个多边形后,通过控制半径的长短来绘制多个,此处就是简单的循环步骤一中的代码即可。

步骤三:

绘制完多个多边形后,我们就要把多边形的点从内到外的连接起来,这里的绘制我们只要知道最外层多变形的点坐标即可。通过绘制线的方法drawLine(),给出首位坐标即可。

步骤四:

然后是绘制实际的数据能力值,该绘制方法和步骤一基本一致,主要要注意该能力值,通过百分比的形式传入。然后通过比例计算出合适的半径,在通过正弦余弦来计算出点,然后在绘制出来即可。

步骤五:

绘制完实际数据后,在最外侧绘制能力值的名称,这里需要注意的是在不同的角度范围内要对绘制的文字简单调整,角度是逆时针增加的。

完成上面的步骤基本上就完成了整个的绘制过程。

线面介绍几个注意的地方:

问题1:

如果你是要绘制填充的样式(如项目中的样式),要注意从外向里面绘制(就是半径逐渐变小),因为填充是从(0,0)点开始的,这样每次半径变小的多边形都在外面大的多边形的上一层。

问题2:

因为我们用到了三角函数,所以里面的角度统一用到了π,否则会有误差产生。

问题3:

最后绘制文字判断角度的时候,注意角度是顺时针增加的,然后判断区间的时候也要用π来判断。

下面是整个源码,注释比较清楚

public class MyView extends View {

    private Paint paint;
    private int radius = 100;
    private float angle;//间隔的角度
    private int n;//几边形
    private int level;//画几层
    private ArrayList<Point> pointsArrayList;
    private int viewWidth;
    private int viewHeight;
    private ArrayList<ArrayList<Point>> lineArrayList;
    private String[] name = {"能力1", "能力2", "能力3", "能力4", "能力5", "能力6", "能力7"};
    private float[] percent = {40, 62, 67, 50, 70, 73, 90};
    private TextPaint textPaint;


    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(1);

        textPaint = new TextPaint();
        textPaint.setColor(Color.RED);
        textPaint.setTextSize(30);
        radius = 200;
        n = 7;
        level = 4;
        angle = (float) ((2 * Math.PI) / n);
        lineArrayList = new ArrayList<>();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewHeight = viewWidth = getMeasuredWidth();
        Log.i("myView", viewWidth + "---" + viewHeight);
        radius = viewHeight / 2 - viewHeight / 6;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //左上角为(0,0)移动到中心点为(0,0)
        canvas.translate(viewWidth / 2, viewHeight / 2);
//        canvas.drawLine(0, viewHeight / 2, 0, -viewHeight / 2, paint);
//        paint.setColor(Color.GREEN);
//        canvas.drawLine(viewHeight / 2, 0, -viewHeight / 2, 0, paint);

        //获得所有的点的集合
        calculate();
        //绘制多边形
        drawPolygon(canvas);
        //绘制线
        drawLine(canvas);
        //绘制各项评分值
        drawGrade(canvas);
        //绘制最外层文字
        drawNameText(canvas);


    }

    private void drawNameText(Canvas canvas) {
        ArrayList<Point> points = lineArrayList.get(0);

        for (int i = 0; i < points.size(); i++) {
            Point point = points.get(i);
            //需要判断角度
            angle = (float) ((2 * Math.PI) / n);
            angle *= i;
            Rect rect = new Rect();

            paint.getTextBounds(name[i], 0, name[i].length(), rect);
            int w = rect.width();
            int h = rect.height();
            Log.i("angle", w + "**" + h + "--" + angle);
            if (angle >= 0 && angle < Math.PI / 2) {
                canvas.drawText(name[i], point.getX() + w, point.getY(), textPaint);
            } else if (angle >= Math.PI / 2 && angle < Math.PI) {
                canvas.drawText(name[i], point.getX() - 2 * w, point.getY() + 2 * h, textPaint);
            } else if (angle >= Math.PI && angle < Math.PI + Math.PI / 2) {
                canvas.drawText(name[i], point.getX() - 3 * w, point.getY() - h, textPaint);
            } else if (angle >= Math.PI + Math.PI / 2 && angle < 2 * Math.PI) {
                canvas.drawText(name[i], point.getX(), point.getY(), textPaint);
            }
        }

    }

    private void drawGrade(Canvas canvas) {
        canvas.save();
        paint.reset();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        paint.setColor(Color.parseColor("#33cc66"));

        Path path = new Path();
        float x;
        float y;
        for (int i = 0; i < percent.length; i++) {
            float value = percent[i] / 100;
            value *= viewHeight / 2 - viewHeight / 6;
            x = (float) (value * Math.cos(angle * i));
            y = (float) (value * Math.sin(angle * i));

            if (i == 0) {
                path.moveTo(x, y);
            } else {
                path.lineTo(x, y);
            }
        }
        path.close();
        canvas.drawPath(path, paint);
        path.reset();
        canvas.restore();

    }

    private void drawLine(Canvas canvas) {
        ArrayList<Point> points1 = lineArrayList.get(0);
        paint.setColor(Color.parseColor("#888888"));
        for (int i = 0; i < points1.size(); i++) {
            Point point = points1.get(i);
            canvas.drawLine(0, 0, point.getX(), point.getY(), paint);

        }


    }

    private void drawPolygon(Canvas canvas) {
        canvas.save();
        paint.setStyle(Paint.Style.FILL_AND_STROKE);//设置为填充且描边
        Path path = new Path();
        for (int j = 0; j < lineArrayList.size(); j++) {
            switch (j) {
                case 0:
                    paint.setColor(Color.parseColor("#dddddd"));
                    break;
                case 1:
                    paint.setColor(Color.parseColor("#cccccc"));
                    break;
                case 2:
                    paint.setColor(Color.parseColor("#aaaaaa"));
                    break;
                case 3:
                    paint.setColor(Color.parseColor("#999999"));
                    break;
            }
            for (int i = 0; i < lineArrayList.get(j).size(); i++) {
                Point point = lineArrayList.get(j).get(i);
                Log.i("myView", point.getX() + "" + point.getY());
                if (i == 0) {
                    path.moveTo(point.getX(), point.getY());
                } else {
                    path.lineTo(point.getX(), point.getY());

                }
            }
            path.close();
            if (path != null) {
                canvas.drawPath(path, paint);
            }
            path.reset();
        }
        canvas.restore();
    }

    private void calculate() {
        for (int j = 0; j < level; j++) {
            float x;
            float y;
            Log.i("radius", radius + "---");
            Point point;
            pointsArrayList = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                x = (float) (radius * Math.cos(angle * i));
                y = (float) (radius * Math.sin(angle * i));
                Log.i("myView", x + "" + y);
                point = new Point(x, y);
                pointsArrayList.add(point);
            }
            radius -= radius / level;
            lineArrayList.add(pointsArrayList);
        }


    }
}
如有问题欢迎指出,共同学习,谢谢
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值