# 做了一个星空背景的动态 Drawable – StarrySky

imageView.setImageDrawable(starrySky)
// or
imageView.background = starrySky

starrySky.start()

#### 所以基础结构就是

class StarrySky: Drawable(), Animatable {
/// xxx
override fun draw(canvas: Canvas)
override fun start()
override fun stop()
override fun isRunning()
}

1. 随机位置
2. 随机速度
3. 随机方向

class Star(
var x: Float,
var y: Float,
var speed: Int, // pixels per second
var direction: Int  // degree (0-360)
)

class Star(
var x: Float,
var y: Float,
var speed: Int, // pixels per second
var direction: Int  // degree (0-360)
) {
fun move(delta: Int) {
x += speed * delta / 1000f * cos(direction.toFloat())
y += speed * delta / 1000f * sin(direction.toFloat())
}
}

val stars = HashSet()
private val LOCK = Any()
synchronized(LOCK) {
}
}
fun removeStar(star: Star) {
synchronized(LOCK) {
stars.remove(star)
}
}
fun copyStar(): HashSet {
synchronized(LOCK) {
val set = HashSet()
return set
}
}

fun draw(canvas: Canvas) {
canvas.drawColor(backgroundColor)
val currentStars = copyStar()
for (star in currentStars) {
canvas.drawCircle(star.x, star.y, 2f, starPaint)
}
}

fun start() {
/// xxx
override fun run() {
val currentTime = System.currentTimeMillis()
update((currentTime - lastTime).toInt())
lastTime = currentTime
}
}, 0, 16)
}
fun update(delta: Int) {
// xxx
// 这里要注意处理同步问题, 我就简写
for star in stars:
star.move(delta)
}

ok，新位置计算结束

fun update(delta: Int) {
// 计算新位置后
invalidateSelf()
}

## 做成通用型 Drawable

class Star(
var x: Float,
var y: Float,
var speed: Int, // pixels per second
var direction: Int  // degree (0-360)
) {
fun move(delta: Int) {
x += speed * delta / 1000f * cos(direction.toFloat())
y += speed * delta / 1000f * sin(direction.toFloat())
}
}

abstract class Model(
var position: Point
) {
abstract fun move(delta: Int)
}

abstract class Model(
var position: Point
) {
abstract fun move(delta: Int)
abstract fun draw(canvas: Canvas)
}

class Star(position: Point, val speed: Int, val direction: Int, paint: Paint): Model(position) {
fun move(delta: Int) {
position.x += speed * delta / 1000f * cos(direction.toFloat())
position.y += speed * delta / 1000f * sin(direction.toFloat())
}
fun draw(canvas: Canvas) {
canvas.drawCircle(position.x, position.y, 2f, paint)
}
}

class StarrySky: Drawable(), Animatable {
/// xxx
val models = HashSet()

// 开始动画
override fun start() {
// 每 16s 更新
override fun run() {
val currentTime = System.currentTimeMillis()
update((currentTime - lastTime).toInt())
lastTime = currentTime
// 重绘
invalidateSelf()
}
}, 0, 16)
}
override fun stop()
override fun isRunning()

// 计算新位置
fun update(delta: Int) {
models.forEach {
it.move(delta)
}
}

// 绘制模型
override fun draw(canvas: Canvas) {
models.forEach {
it.draw(canvas)
}
}
}