美文网首页
Android之鱼塘开发笔记

Android之鱼塘开发笔记

作者: CarlosLynn | 来源:发表于2021-04-02 18:43 被阅读0次

1,需求开发一个按照固定轨迹游泳的鱼池

2,实现思路

ViewGroup + ImageView组合,通过定时刷新,不断对子view位置进行摆放处理

  • 2.1,定时刷新采用Handler定时发送消息
  • 2.2,收到消息后调用ViewGrouprequestLayout()触发回调onLayout(boolean changed, int left, int top, int right, int bottom)函数
  • 2.3,重写ViewGroup的onLayout方法,调用子View的layout()函数不断进行位置放.最终形成鱼宠不断游动效果.

3,鱼宠游动轨迹图

device-2021-04-02-103933.png

4,坐标点的测试

P0,
x:990,y:1065
P0x:990, P0y:1065

P1,
x:540,y:572
P1x:540, P1y:572

P2,
x:90,y:572
P2x:90, P2y:572

P3,
x:990,y:80
P3x:990, P3y:80

P4,
x:990,y:572
P4x:990, P4y:572

P5,
x:990,y:80
P5x:990, P5y:990

P6,
x:90,y:80
P6x:90, P6y:80

P7,
x:990,y:572
P7x:990, P7y:572

P8,
x:540,y:572
P8x:540, P8y:572

P9,
x:90,y:1065
P9x:90, P9y:1065

P10,
x:90,y:572
P10x:90, P10y:572

P11,
x:90,y:1065
P11x:90, P11y:1065

P12,
x:990,y:1065
P12x:990, P12y:1065

5,鱼宠游动状态的定义

/**
 * 鱼儿的游动状态
 */
@IntDef({
        FishStatus.UN_KNOW,
        FishStatus.TURN_LEFT,
        FishStatus.TURN_RIGHT,
        FishStatus.MOVE_LEFT,
        FishStatus.MOVE_RIGHT,
})
@Retention(RetentionPolicy.SOURCE)
@interface FishStatus {
    /**
     * 未知状态
     */
    int UN_KNOW = -1;
    /**
     * 向左转
     */
    int TURN_LEFT = 0;
    /**
     * 向右转
     */
    int TURN_RIGHT = 1;
    /**
     * 向左正常游动
     */
    int MOVE_LEFT = 2;
    /**
     * 向右正常游动
     */
    int MOVE_RIGHT = 3;
}

5,对鱼宠游动过程坐标点进行监听,当游动到了路线轨迹坐标点处进行处理并且修改游动状态

  • 5.1坐标点对应鱼宠游动状态分析

  • P0和P12坐标重合
    P0开始向左游动,P12开始向左转身

  • P1和P8坐标重合
    P1,P8分别停留1秒钟

  • P2和P10坐标重合
    P2开始向右转身,P10向下游

  • P3和P5坐标重合
    P3向下游,P5开始向左转身

  • P4和P7坐标重合
    P4开始向上游动,P7开始向左转身,

  • P9和P11坐标重合
    P9开始向上游动,P11开始向右转身

-P6单独坐标点
P6开始向右转身

  • 5.2相邻两坐标点的轨迹的游动状态分析

  • 1,P0--->P1
    向左上方移动

  • 2,P1--->P2
    向左方移动

  • 3,P2--->P3
    向右上方移动

  • 3,P3--->P4
    向下方移动

  • 4,P4--->P5
    向上方移动

  • 5,P5--->P6
    向左方移动

  • 6,P6--->P7
    向右下方移动

  • 7,P7--->P8
    向左方移动

  • 8,P8--->P9
    向左下方移动

  • 9,P9--->P10
    向上方移动

  • 10,P10--->P11
    向下方移动

  • 10,P11--->P12
    向右方移动

  • 5.3如何判断鱼宠坐标点是否在指定的坐标处.

  • 1,鱼宠坐标和P0坐标相等,也和P12坐标相等,不同时刻的路线坐标值存在相同情况,根据坐标值无法判定是否处于指定的坐标处.

  • 2,鱼宠游动方向向左,游动方向由坐标点驱动,无法用于判断是否处于坐标点处.

  • 3,定义private var progress = 0.0F变量,表示移动路线的进度,每个坐标点对应一个进度值.

    • P0,progress=0
    • P12,progress=1
  • 4,如何建立坐标点和路线进度的映射关系

    这里我们采用,keyvalue键值对形式来保存映射关系,用key来表示进度值progress,用value来表示指定坐标点容器索引posotion,
    (0.0,0),(1.0,12),综合分析无法建立较完善的映射关系,该方式无法用来判定是否处于指定坐标处.

  • 5,根据坐标点距离起点的总长度来判定坐标点

    P0:pLength = 0,P1:pLength = (P1.x-P0.x) * (P1.x-P0.x) + (P1.y-P0.y) * (P1.y-P0.y)开根号.

  • 6,根据坐标点范围以及游动状态组合判断

/**
 * 根据移动的坐标点和轨迹坐标点来修改小鱼的游动状态.
 * @param x
 * @param y
 * @param distance 距离起点的直线距离.
 */
private fun onSwimming(x: Float, y: Float, distance: Float) {
    if (pointList.isEmpty()) return

    if (distance == 0F || progress == 0F) {
        //P0,点处开始向左上游动.
        changeSwimming(FishStatus.TURN_LEFT)
        changeSwimming(FishStatus.MOVE_TOP_LEFT)
    }

    if (isInPointRect(pointList[1], x, y)) {
        //P1,P8处停留
        changeSwimming(FishStatus.REST)
    } else {
        when (lastFishStatus) {
            FishStatus.MOVE_TOP_LEFT -> {
                if (fishStatus == FishStatus.REST) {
                    changeSwimming(FishStatus.MOVE_LEFT)
                }
            }

            FishStatus.MOVE_LEFT -> {
                if (fishStatus == FishStatus.REST) {
                    changeSwimming(FishStatus.MOVE_BOTTOM_LEFT)
                }
            }

            else -> {
                when {
                    //P2,P10
                    //P2点处向右转身,开始向右游动.
                    isInPointRect(pointList[2], x, y) -> {
                        //判定该点位于此P2
                        if (fishStatus == FishStatus.MOVE_LEFT) {
                            if (fishStatus != FishStatus.MOVE_TOP_RIGHT) {
                                changeSwimming(FishStatus.TURN_RIGHT)
                                changeSwimming(FishStatus.MOVE_TOP_RIGHT)
                            }
                        }
                        //P10->p11,下游
                        if (fishStatus == FishStatus.MOVE_TOP_ON_LEFT) {
                            changeSwimming(FishStatus.MOVE_BOTTOM_ON_LEFT)
                        }
                    }

                    //P3,P5,
                    isInPointRect(pointList[3], x, y) -> {
                        //P3,下游
                        if (fishStatus == FishStatus.MOVE_TOP_RIGHT) {
                            changeSwimming(FishStatus.MOVE_BOTTOM_ON_RIGHT)
                        }
                        //P5点处向左转身,开始向左游动.
                        if (fishStatus == FishStatus.MOVE_TOP_ON_RIGHT) {
                            changeSwimming(FishStatus.TURN_LEFT)
                            changeSwimming(FishStatus.MOVE_LEFT)
                        }
                    }

                    //P4,P7,
                    isInPointRect(pointList[4], x, y) -> {
                        //P4,上游
                        if (fishStatus == FishStatus.MOVE_BOTTOM_ON_RIGHT) {
                            changeSwimming(FishStatus.MOVE_TOP_ON_RIGHT)
                        }
                        //P7点处向左转身,开始向左游动.
                        if (fishStatus == FishStatus.MOVE_BOTTOM_RIGHT) {
                            changeSwimming(FishStatus.TURN_LEFT)
                            changeSwimming(FishStatus.MOVE_LEFT)
                        }
                    }

                    //P6,
                    isInPointRect(pointList[6], x, y) -> {
                        //P6点处向右转身,开始向右游动.
                        if (fishStatus == FishStatus.MOVE_LEFT) {
                            changeSwimming(FishStatus.TURN_RIGHT)
                            changeSwimming(FishStatus.MOVE_BOTTOM_RIGHT)
                        }
                    }

                    //P9,P11,
                    isInPointRect(pointList[9], x, y) -> {
                        //P9,垂直向上游
                        if (fishStatus == FishStatus.MOVE_BOTTOM_LEFT) {
                            changeSwimming(FishStatus.MOVE_TOP_ON_LEFT)
                        }
                        //P11,向右转身,向右移动
                        if (fishStatus == FishStatus.MOVE_BOTTOM_ON_LEFT) {
                            changeSwimming(FishStatus.TURN_RIGHT)
                            changeSwimming(FishStatus.MOVE_RIGHT)
                        }
                    }
                }
            }
        }
    }
}
  • 5.4鱼宠还正在向左游动就向边转身了的视觉异常处理

  • 6采用SurfaceView方案来增加动画的流畅性.

  • 7动画运行相关参考资料

https://github.com/blipinsk/ViewPropertyObjectAnimator

一款强大的属性动画操作集合
https://github.com/paulyung541/ActionAnimatorSet

小船游动效果
https://github.com/WANZIzZ/RowingView

方块移动,飞机移动
https://github.com/Jetpack-Missionary/MotionChallenge

赛车动画
https://github.com/VKOOY/AnimationRacingCarForKotlin

SurfaceView实现墨迹天气的风车效果
https://blog.csdn.net/xyz_lmn/article/details/20483709

SurfaceView实现下雨与下雪动画效果(Kotlin语法)
https://www.jb51.net/article/123687.htm

SurfaceView实现鱼儿游动动画
https://www.jb51.net/article/138961.htm

SurfaceView实现红包雨平移动画
http://www.zyiz.net/tech/detail-62558.html

Android自定义View实现抖音飘动红心效果
https://www.jb51.net/article/187575.htm

Android十个小案例动画,自定义View动画实现,ValueAnimator
https://blog.csdn.net/u012835548/article/details/53887607

Android属性动画 - 平移动画
https://blog.csdn.net/u010349644/article/details/101151809

https://github.com/heqiangflytosky/AndroidAnimationDemo

相关文章

网友评论

      本文标题:Android之鱼塘开发笔记

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