Last active
June 16, 2021 14:00
-
-
Save maozgal/128516eee7c9b10d26189b5664b98720 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MainActivity : AppCompatActivity() { | |
private var mostHighDashedLine: View? = null | |
private var dashArray = arrayListOf<View>() | |
private var dashLinesCount = 0; | |
private var timer = Timer() | |
private var height = 100 | |
private var width = 100F | |
private var dashLineHeight = 400 | |
private var dashLineWidth = 100 | |
private var car: View? = null | |
private var startX = 0F | |
private var endX = 0F | |
private var obstaclesArray = arrayListOf<View>() | |
private val movementInterval = 2 | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
gameInit() | |
} | |
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { | |
// Finger touched the screen | |
if (ACTION_DOWN == ev?.action) { | |
// Moving UI elements has to be done by the main thread. | |
runOnUiThread { | |
// Decide whether to animate the car right or left | |
car?.tag = !(car?.tag as Boolean) | |
car?.animate()?.translationX(if (car?.tag as Boolean) startX else endX) | |
?.setDuration(200)?.start() | |
} | |
} | |
return super.dispatchTouchEvent(ev) | |
} | |
private fun runGame() { | |
timer.cancel() | |
timer = Timer() | |
timer.scheduleAtFixedRate(object : TimerTask() { | |
override fun run() { | |
gameLoop() | |
} | |
}, 0L, 3L); | |
} | |
private fun gameLoop() { | |
// Moving UI elements has to be done by the main thread. | |
runOnUiThread { | |
// Run through all the dashed lines and increase their Y-axis parameter by 2 px. | |
for (i in 0..dashLinesCount) { | |
var dashView = dashArray.get(i); | |
dashView.y += movementInterval; | |
// If a dashed line is out of sight (below the bottom of the screen), reset it to be | |
// on top of the highest dashed line. | |
if (dashView.y > height + (dashLineHeight / 2)) { | |
val mostHighDashedLineY: Float = (mostHighDashedLine?.y ?: 0F) | |
dashView.y = mostHighDashedLineY - (2 * dashLineHeight.toFloat()) | |
mostHighDashedLine = dashView | |
} | |
} | |
// Run through all the obstacle and increase their Y-axis parameter by 2 px. | |
for (i in 0 until obstaclesArray.size) { | |
if (i < obstaclesArray.size) { | |
var obstacle = obstaclesArray.get(i); | |
obstacle.y += movementInterval; | |
// If an obstacle is out of sight (below the bottom of the screen), reset it to be | |
// on top of the highest obstacle. | |
if (obstacle.y > height + obstacle.height) { | |
obstacle.y = -(2 * dashLineHeight.toFloat()) | |
} | |
} | |
} | |
} | |
} | |
private fun gameInit() { | |
initValues() | |
} | |
private fun initValues() { | |
val root = findViewById<ConstraintLayout>(R.id.root) | |
car = findViewById<ConstraintLayout>(R.id.car) | |
car?.tag = true | |
root.viewTreeObserver.addOnGlobalLayoutListener(object : | |
ViewTreeObserver.OnGlobalLayoutListener { | |
override fun onGlobalLayout() { | |
root.viewTreeObserver.removeOnGlobalLayoutListener(this) | |
val displayMetrics = DisplayMetrics() | |
windowManager.defaultDisplay.getMetrics(displayMetrics) | |
height = displayMetrics.heightPixels | |
dashLinesCount = height / dashLineHeight | |
width = displayMetrics.widthPixels.toFloat() | |
startX = 60.toFloat() | |
val carWidth: Int = car?.width ?: 0 | |
endX = width - 180.toFloat() - carWidth | |
buildObstacles() | |
buildDashedLine() | |
runGame() | |
} | |
}) | |
} | |
private fun buildObstacles() { | |
// Take the root view (Layout) | |
val root = findViewById<ConstraintLayout>(R.id.root) | |
// Build 5 obstacle | |
for (i in 0..5) { | |
var orientation = if ((i % 2) == 0) ConstraintSet.LEFT else ConstraintSet.RIGHT | |
var obstacle = View(this) | |
obstacle.id = View.generateViewId() | |
obstacle.setBackgroundColor(Color.BLUE) | |
root.addView(obstacle) | |
val constraints = ConstraintSet() | |
constraints.clone(root) | |
constraints.constrainHeight(obstacle.id, 100) | |
constraints.constrainWidth(obstacle.id, 100) | |
val start = i * 400 | |
constraints.connect( | |
obstacle.id, | |
ConstraintSet.BOTTOM, | |
R.id.root, | |
ConstraintSet.BOTTOM, | |
start | |
) | |
constraints.connect( | |
obstacle.id, | |
orientation, | |
R.id.root, | |
orientation, | |
140 | |
) | |
constraints.applyTo(root) | |
obstacle.bringToFront() | |
obstaclesArray.add(obstacle) | |
} | |
} | |
private fun buildDashedLine() { | |
// Take the root view (Layout) | |
val root = findViewById<ConstraintLayout>(R.id.root) | |
// Build the first dash line. | |
val bottomLine = buildDashLineView() | |
root.addView(bottomLine, 0) | |
attachViewToBottomOfParent(root, bottomLine) | |
dashArray.add(bottomLine) | |
// Build the rest of the the dash lines. | |
var currentV = bottomLine | |
for (i in 0 until dashLinesCount) { | |
val v = buildDashLineView() | |
root.addView(v) | |
attachViewToTopOfOtherView(root, v, currentV) | |
// Remember the current dashed line so the constraints could be on top of it | |
currentV = v | |
dashArray.add(currentV) | |
// The current most high dashed line. needed for when resetting dashed line from bottom | |
// to top, this will be the dashed line to make the constraint upon | |
mostHighDashedLine = v | |
} | |
} | |
private fun attachViewToTopOfOtherView(root: ConstraintLayout?, view: View, other: View) { | |
val constraints = ConstraintSet() | |
generateBasicDashConstraints(constraints, root, view) | |
constraints.connect( | |
view.id, | |
ConstraintSet.BOTTOM, | |
other.id, | |
ConstraintSet.TOP, | |
dashLineHeight | |
) | |
constraints.applyTo(root) | |
} | |
private fun attachViewToBottomOfParent(root: ConstraintLayout?, view: View) { | |
val constraints = ConstraintSet() | |
generateBasicDashConstraints(constraints, root, view) | |
constraints.connect( | |
view.id, | |
ConstraintSet.BOTTOM, | |
R.id.root, | |
ConstraintSet.BOTTOM, | |
dashLineHeight | |
) | |
view.setBackgroundColor(Color.WHITE) | |
constraints.applyTo(root) | |
} | |
private fun generateBasicDashConstraints( | |
constraints: ConstraintSet, | |
root: ConstraintLayout?, | |
view: View | |
) { | |
constraints.clone(root) | |
constraints.constrainHeight(view.id, dashLineHeight) | |
constraints.constrainWidth(view.id, dashLineWidth) | |
constraints.connect(view.id, ConstraintSet.LEFT, R.id.root, ConstraintSet.LEFT) | |
constraints.connect(view.id, ConstraintSet.RIGHT, R.id.root, ConstraintSet.RIGHT) | |
} | |
private fun buildDashLineView(): View { | |
val v = View(this) | |
v.id = View.generateViewId() | |
v.setBackgroundColor(Color.WHITE) | |
return v | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment