<file_sep>package com.example.movingcarapp

import android.graphics.PointF
import kotlin.math.acos
import kotlin.math.sqrt

class Triangle(
    private val a: PointF,
    private val b: PointF,
    private val c: PointF
) {
    private fun getAB(): Double {
        val dx = a.x - b.x
        val dy = (a.y - b.y).toDouble()
        return sqrt(dx * dx + dy * dy)
    }

    private fun getBC(): Double {
        val dx = b.x - c.x
        val dy = (b.y - c.y).toDouble()
        return sqrt(dx * dx + dy * dy)
    }

    private fun getAC(): Double {
        val dx = a.x - c.x
        val dy = (a.y - c.y).toDouble()
        return sqrt(dx * dx + dy * dy)
    }

    fun getAngle(): Float {
        return angle(getAC(), getBC(), getAB()).toFloat()
    }

    private fun angle(oppositeLeg: Double, adjacentLeg1: Double, adjacentLeg2: Double): Double {
        return Math.toDegrees(
            acos(
                (adjacentLeg1 * adjacentLeg1 + adjacentLeg2 * adjacentLeg2 - oppositeLeg * oppositeLeg)
                        / 2 / adjacentLeg2 / adjacentLeg1
            )
        )
    }

}
<file_sep>include ':app'
rootProject.name='MovingCarApp'
<file_sep>package com.example.movingcarapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        showFragment()
    }

    private fun showFragment() {
        var fragment = getFragment()
        if (fragment == null) {
            fragment = RoadFragment.newInstance()
            supportFragmentManager.beginTransaction()
                .add(R.id.activity_main_fragment_container, fragment)
                .commit()
        }
    }

    private fun getFragment(): Fragment? {
        return supportFragmentManager.findFragmentById(R.id.activity_main_fragment_container)
    }

}
<file_sep>package com.example.movingcarapp

import android.graphics.PointF
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_road.*
import android.view.MotionEvent
import android.view.animation.*


class RoadFragment : Fragment() {

    companion object {
        fun newInstance() = RoadFragment()
    }

    private lateinit var car: ImageView

    private val rotateDuration = 500L
    private val translateDuration = 1500L

    var previousAngle = 0f

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_road, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        findViews()
        initListeners()
    }

    private fun findViews() {
        car = fragment_road_car
    }

    private fun initListeners() {
        view?.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                disableView(view)
                startMotion(event.x, event.y)
                true
            } else {
                false
            }
        }
    }

    private fun disableView(view: View?) {
        if (view == null) return
        view.isEnabled = false
        view.postDelayed({
            view.isEnabled = true
        }, translateDuration + rotateDuration)
    }

    private fun startMotion(x: Float, y: Float) {
        val toDegrees = getToDegrees(x, y)
        car.animate()
            .rotationBy(toDegrees)
            .setDuration(rotateDuration)
            .withEndAction {
                car.animate().x(x).y(y)
                    .setInterpolator(AccelerateDecelerateInterpolator())
                    .setDuration(translateDuration)
                    .start()
            }
            .start()
    }


    private fun getToDegrees(x: Float, y: Float): Float {
        val startPoint = PointF(car.x, car.y)
        val endPoint = PointF(x, y)
        val thirdPointY = getThirdPointY(y)
        val thirdPoint = PointF(car.x, thirdPointY)
        val triangle = Triangle(thirdPoint, startPoint, endPoint)
        val angle = getAngle(x, triangle)
        previousAngle = getPreviousAngle(x, triangle)
        return angle
    }

    private fun getThirdPointY(y: Float): Float {
        return if (car.y > y) {
            y
        } else {
            car.y + (car.y - y)
        }
    }

    private fun getAngle(x: Float, triangle: Triangle): Float {
        val angle = when {
            car.x > x -> triangle.getAngle().unaryMinus()
            else -> triangle.getAngle()
        }
        return angle - previousAngle
    }

    private fun getPreviousAngle(x: Float, triangle: Triangle): Float {
        return if (car.x > x) {
            triangle.getAngle().unaryMinus()
        } else {
            triangle.getAngle()
        }
    }

}