Protools splash animation
Last active
September 2, 2020 10:53
-
-
Save dsvoronin/99ab590de7f46a95901f to your computer and use it in GitHub Desktop.
Protools
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
import android.content.Context | |
import android.graphics.Canvas | |
import android.graphics.Color | |
import android.graphics.Paint | |
import android.util.AttributeSet | |
class StarsView(context: Context, attrs: AttributeSet) : TickView(context, attrs) { | |
data class Star(val x: Float, | |
val y: Float, | |
val radius: Float, | |
val paint: Paint, | |
val alpha: Int, | |
val shiftFunc: (alpha: Int, shift: Int) -> Int) | |
val density = 50 | |
val alphaRange = 50..222 | |
val radiusRange = 3.0..10.0 | |
val alphaShift = 90 | |
var paint = Paint().apply { color = Color.WHITE } | |
val stars: List<Star> by lazy { generateStars() } | |
override fun tick(canvas: Canvas) { | |
val currentMillis = System.currentTimeMillis() | |
val time = (currentMillis - (currentMillis / 100000 * 100000)).toDouble() / 10000 * 20 | |
val sinus = Math.sin(time) | |
val s = (alphaShift * sinus).toInt() | |
stars.forEach { star -> | |
canvas.drawCircle( | |
star.x, | |
star.y, | |
star.radius, | |
paint.apply { alpha = star.shiftFunc(star.alpha, s).byteAbs() }) | |
} | |
} | |
private fun Int.byteAbs(): Int { | |
return when { | |
this < 0 -> 0 | |
this > 255 -> 255 | |
else -> this | |
} | |
} | |
private fun generateStars(): List<Star> = | |
(0..density).map { | |
val a = rnd.nextInt(alphaRange.first, alphaRange.last) | |
Star( | |
x = rnd.nextInt(0, measuredWidth).toFloat(), | |
y = rnd.nextInt(0, measuredHeight).toFloat(), | |
radius = rnd.nextDouble(radiusRange.start, radiusRange.endInclusive).toFloat(), | |
alpha = a, | |
paint = Paint(paint).apply { alpha = a }, | |
shiftFunc = when (rnd.nextBoolean()) { | |
true -> { alpha, shift -> alpha + shift } | |
false -> { alpha, shift -> alpha - shift } | |
}) | |
} | |
} |
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
import android.content.Context | |
import android.graphics.Canvas | |
import android.util.AttributeSet | |
import android.view.View | |
import java.util.concurrent.ThreadLocalRandom | |
abstract class TickView(context: Context, attrs: AttributeSet) : View(context, attrs) { | |
protected val rnd = ThreadLocalRandom.current() | |
protected var fps = 12 | |
val tick: Runnable | |
get() = Runnable { | |
invalidate() | |
postDelayed(tick, 1000L / fps) | |
} | |
override fun onAttachedToWindow() { | |
super.onAttachedToWindow() | |
post(tick) | |
} | |
override fun onDetachedFromWindow() { | |
super.onDetachedFromWindow() | |
removeCallbacks(tick) | |
} | |
override fun onDraw(canvas: Canvas) { | |
super.onDraw(canvas) | |
tick(canvas) | |
} | |
abstract fun tick(canvas: Canvas) | |
} |
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
import android.content.Context | |
import android.graphics.* | |
import android.util.AttributeSet | |
import java.util.concurrent.ThreadLocalRandom | |
class TracesView(context: Context, attrs: AttributeSet) : TickView(context, attrs) { | |
val density = 5 | |
val speed = 100 | |
val spawnChance = 0.10 | |
val lengthRange = 170..230 | |
val alphaRange = 200..230 | |
init { | |
fps = 60 | |
} | |
val paint = Paint().apply { | |
color = Color.WHITE | |
isAntiAlias = true | |
shader = LinearGradient(0f, 0f, 0f, 0f, Color.WHITE, Color.DKGRAY, Shader.TileMode.MIRROR) | |
} | |
val traces by lazy { generateTraces() } | |
val spawnZone: Rect by lazy { Rect(measuredWidth, -measuredWidth, 2 * measuredWidth, measuredWidth) } | |
val visibleZone: Rect by lazy { Rect(0, 0, measuredWidth, measuredHeight) } | |
override fun tick(canvas: Canvas) { | |
val deadTraces = traces.filter { it.isDead(visibleZone) } | |
val aliveTraces = traces.filter { !it.isDead(visibleZone) } | |
traces.forEach { | |
if (!it.isDead(visibleZone)) { | |
canvas.drawLine( | |
it.x.toFloat(), | |
it.y.toFloat(), | |
it.tailX.toFloat(), | |
it.tailY.toFloat(), | |
paint.apply { alpha = it.alpha }) | |
it.move(speed) | |
} | |
} | |
if (aliveTraces.size < 2 && deadTraces.size > 0 && rnd.nextFloat() <= spawnChance) { | |
deadTraces.random().respawn(spawnZone, rnd, lengthRange, alphaRange) | |
} | |
} | |
private fun generateTraces(): List<Trace> = (0..density).map { Trace() } | |
private fun <T> List<T>.random(): T = get(rnd.nextInt(size)) | |
data class Trace(var x: Int = 0, var y: Int = 0, var tailX: Int = 0, var tailY: Int = 0, var alpha: Int = 0) { | |
fun respawn(zone: Rect, rnd: ThreadLocalRandom, lengthRange: IntRange, alphaRange: IntRange) { | |
val point = zone.randomPoint(rnd) | |
val length = rnd.nextInt(lengthRange.first, lengthRange.last) | |
alpha = rnd.nextInt(alphaRange.first, alphaRange.last) | |
x = point.x | |
y = point.y | |
tailX = (point.x + length) | |
tailY = (point.y - length) | |
} | |
fun move(speed: Int) { | |
x -= speed | |
y += speed | |
tailX -= speed | |
tailY += speed | |
} | |
fun isDead(visibleZone: Rect): Boolean = tailX < visibleZone.left || tailY > visibleZone.bottom | |
fun Rect.randomPoint(rnd: ThreadLocalRandom): Point = Point( | |
rnd.nextInt(this.left, this.right), | |
rnd.nextInt(this.top, this.bottom)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment