美文网首页
4个小球

4个小球

作者: 有点健忘 | 来源:发表于2018-01-15 15:26 被阅读8次

按照这里来设计的,效果比这里丑点。主要原因还是path画的有点生硬,转弯的时候不平滑。
https://www.jianshu.com/p/138ad32540ce

就是简单模仿下,所以细节未做优化。这个小球的宽高和位置都是按照控件大小算的,所以这个控件需要固定的宽高,不要用wrap即可。

import java.util.ArrayList;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;

public class LaunchAnimaView extends View {

    public LaunchAnimaView(Context context) {
        super(context);
        initSomething();
    }

    public LaunchAnimaView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSomething();
    }

    public LaunchAnimaView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSomething();
    }

    Paint paint = new Paint();
    int[] colors = { Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN };//4种球的颜色
    float[] maxSacles = { 2, 1, 2, 1 };//4种球的最大方法比例
    ArrayList<Paint> paints = new ArrayList<Paint>();//保存4种画笔
    ArrayList<PathMeasure> measures = new ArrayList<PathMeasure>();//保存4跳路径的pathmeasure信息
    ArrayList<Path> paths = new ArrayList<Path>();//保存4跳路径
    ArrayList<float[]> positions = new ArrayList<float[]>();//最后要画的小球的实时位置信息,数组长度为2,分别保存x和y的坐标
    int[] startXPositioon = new int[4];//4个小球的起始位置,这里只有x的坐标,而y都是0
    int radius = 1;//小球的原始半径
    float factorSacle = 0;//小球的实时放大比例
    //画布被平移到正中心也就是0,0的位置,所以上边的坐标都是按照正中心为0,0计算的。
    private void initSomething() {
        for (int i = 0; i < 4; i++) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(colors[i]);
            paint.setStyle(Style.FILL);
            paints.add(paint);
        }
        paint.setColor(Color.BLACK);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(1);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);

        for (int i = 0; i < positions.size(); i++) {
            float[] pos = positions.get(i);
            canvas.drawCircle(pos[0], pos[1], radius * (1 + maxSacles[i] * factorSacle), paints.get(i));
//          canvas.drawPath(paths.get(i), paint);
        }

        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        System.err.println("onLayout========================" + changed);
        makeMeasure();
    }

    private boolean haveMeasure = false;

    private void makeMeasure() {
        if (haveMeasure) {
            return;
        }
        haveMeasure = true;
        int halfWidth = getWidth() / 2;
        int halfHeigth = getHeight() / 2;
        radius = halfWidth / 16;
        startXPositioon[0] = -halfWidth / 2;
        startXPositioon[1] = -halfWidth / 4;
        startXPositioon[2] = halfWidth / 4;
        startXPositioon[3] = halfWidth / 2;
        Path path1 = new Path();
        path1.moveTo(-halfWidth / 2, 0);
        path1.cubicTo(-halfWidth / 2, 0, -halfWidth + radius * 4, -halfHeigth * 2 / 3, -halfWidth / 2 - radius * 2,
                -halfHeigth + radius * 4);
        path1.cubicTo(-halfWidth / 4, -halfHeigth + radius * 3, 0, -halfHeigth * 2 / 3, 0, 0);
        path1.moveTo(0, 0);

        Path path2 = new Path();
        path2.moveTo(-halfWidth / 4, 0);
        path2.cubicTo(-halfWidth / 4, 0, -halfWidth / 4 + radius, -halfHeigth * 2 / 3, halfWidth / 2,
                -halfHeigth * 2 / 3);
        path2.cubicTo(halfWidth / 2 + radius, -halfHeigth * 2 / 3 + radius * 3, halfWidth / 2 - radius, -halfHeigth / 3,
                0, 0);
        path2.moveTo(0, 0);

        Path path3 = new Path();
        path3.moveTo(halfWidth / 4, 0);
        path3.cubicTo(halfWidth / 4, 0, halfWidth / 4 - radius, halfHeigth * 2 / 3, 0, halfHeigth * 2 / 3);
        path3.cubicTo(-radius * 2, halfHeigth * 2 / 3 + radius * 2, -halfWidth + radius * 2, 0, -halfWidth / 2,
                -halfHeigth / 3);
        path3.cubicTo(-halfWidth / 2 + radius, -halfHeigth / 3 + radius, -halfWidth / 4, -halfHeigth / 4, 0, 0);

        Path path4 = new Path();
        path4.moveTo(halfWidth / 2, 0);
        path4.cubicTo(halfWidth / 2, 0, halfWidth + radius * 4, halfHeigth * 2 / 3, halfWidth / 2 - radius * 2,
                halfHeigth + radius * 4);
        path4.cubicTo(halfWidth / 2 - radius * 2, halfHeigth + radius * 4, -radius * 2, halfHeigth * 2 / 3, 0, 0);
        path4.moveTo(0, 0);

        paths.add(path1);
        paths.add(path2);
        paths.add(path3);
        paths.add(path4);
        for (Path path : paths) {
            measures.add(new PathMeasure(path, false));
            positions.add(new float[2]);
        }
        startTransX();
    }
    private void reset() {
        if (animator != null) {
            animator.cancel();
        }
        if (animator2 != null) {
            animator2.cancel();
        }
        for (int i = 0; i < positions.size(); i++) {
            float[] pos = positions.get(i);
            pos[0] = 0;
            pos[1] = 0;
        }
        factorSacle = 0;
        postInvalidate();
    }
    public void startTransX() {
        reset();
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(1000);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = animation.getAnimatedFraction();
                for (int i = 0; i < measures.size(); i++) {
                    float[] pos = positions.get(i);
                    pos[0] = startXPositioon[i] * value;
                }
                postInvalidate();
                if(value>=1) {
                    startMove();
                }
            }
        });
        animator.start();
    }

    private void startMove() {
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(2000);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = animation.getAnimatedFraction();
                for (int i = 0; i < measures.size(); i++) {
                    PathMeasure pathMeasure = measures.get(i);
                    float[] pos = positions.get(i);
                    pathMeasure.getPosTan(value * pathMeasure.getLength(), pos, null);
                }
                if (value < 0.66) {
                    factorSacle = value / 0.66f;
                } else {
                    factorSacle = (1 - value) / (1 - 0.66f);
                }

                postInvalidate();
            }
        });
        animator.start();
    }
}

相关文章

  • day-11-pygame的应用

    小球碰撞,大球碰击小球,小球消失

  • 射线拓展

    小球撞击砖块,小球和砖块都必须有碰撞体,当小球撞击到砖块之后,小球消失,在小球原本位置再生成一个小球,点击鼠标继续...

  • Java 小球碰撞

    小球碰撞的关键是 判断小球是否碰撞过:1.当两小球间距小于小球直径时发生碰撞。2.当小球碰到边缘时发生碰撞。

  • 知识回顾第一期

    一、作品效果1、小球朝着某个方向移动,碰到舞台边缘反弹。2、小猫追着小球跑,当小猫碰到小球后,小球随机变换位置继续...

  • 2018-09-04 Day12-pygame小游戏

    1、小球碰撞 2、接球游戏 3、大球吃小球

  • 实现小球在弹射前的拉伸特效和动态障碍物特效

    当前我们实现小球弹射时,会先用鼠标点击小球,然后移动鼠标,当松开鼠标时,小球会弹射向鼠标松开的位置。我们按住小球的...

  • 基于C语言的小球移动课程设计

    用C语言实现“小球移动”的简单图形游戏。可添加、删除小球,小球的分数和大小随机,球会在游戏区域内反弹,小球可被删除...

  • 小球

    题目描述 许多的小球一个一个的从一棵满二叉树上掉下来组成FBT(Full Binary Tree,满二叉树),每一...

  • 04three.js跳动的小球(一)

    小球

  • 18080518 2D游戏 物理弹球

    0805视频 18 物理弹球场景 小球弹射 物理弹球Demo制作 - 需求分析 小球小球.png 障碍物障碍物.p...

网友评论

      本文标题:4个小球

      本文链接:https://www.haomeiwen.com/subject/mxqdoxtx.html