android空间动态背景,[Android] 做了一个星空背景的动态 Drawable

编程入门 行业动态 更新时间:2024-10-26 18:29:15

android空间动态<a href=https://www.elefans.com/category/jswz/34/1771046.html style=背景,[Android] 做了一个星空背景的动态 Drawable"/>

android空间动态背景,[Android] 做了一个星空背景的动态 Drawable

新项目需要做一个星空背景,顺便说下怎么做一个动态 Drawable

先看最终效果图:

我们的目标是一个叫 StarrySky 的 动态Drawable, 用法像这样:

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()

}

复制代码

分析一下效果图,就是在随机位置加了很多点,然后这些点以随机速度往随机方向做匀速直线运动。

那我们所有需要的要素都在这里了:

随机位置

随机速度

随机方向

那我就定义一个类保存这些要素就好,

class Star(

var x: Float,

var y: Float,

var speed: Int, // pixels per second

var direction: Int // degree (0-360)

)

复制代码

因为是星星都动态的,所以要可以计算下一帧的位置,加一个move方法来计算。

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())

}

}

复制代码

然后给 StarrySky 加一个列表来保存这些星星, 为了避免concurrent异常,加上粗暴的同步锁

val stars = HashSet()

private val LOCK = Any()

fun addStar(star: Star) {

synchronized(LOCK) {

stars.add(star)

}

}

fun removeStar(star: Star) {

synchronized(LOCK) {

stars.remove(star)

}

}

fun copyStar(): HashSet {

synchronized(LOCK) {

val set = HashSet()

set.addAll(stars)

return set

}

}

复制代码

画出来:

fun draw(canvas: Canvas) {

canvas.drawColor(backgroundColor)

val currentStars = copyStar()

for (star in currentStars) {

canvas.drawCircle(star.x, star.y, 2f, starPaint)

}

}

复制代码

怎么让他们动起来呢?

方法很多,Timer ValueAnimator 甚至手动delay都可以。我们的目标就是每过 16ms(每秒60帧) 能更新一下我们的位置。然后告诉 drawable,我位置更新了,你可以重新画一遍了。

我这里用了Timer

fun start() {

/// xxx

timer.schedule(object : TimerTask() {

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,新位置计算结束

告诉 drawable 重新绘制:

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())

}

}

复制代码

我们先给他重新命个名,叫Model吧

月亮、太阳、超人等等,这每类模型和星星一样的点在于,他们必然都有坐标,但是移动模式可能不一样。

所以我们可以把速度和方向提出来做抽象得到:

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)

}

}

复制代码

现在整个星空StarrySky看起来像这样了:

class StarrySky: Drawable(), Animatable {

/// xxx

val models = HashSet()

// 开始动画

override fun start() {

// 每 16s 更新

timer.schedule(object : TimerTask() {

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)

}

}

}

复制代码

当然,这里都是伪代码。你实际写代码还要注意更多的细节,比如 Set 的同步问题,物体移动出范围后如何处理的问题。

当这些问题你都处理好了,美丽的星空就从你的手中诞生了。

更多推荐

android空间动态背景,[Android] 做了一个星空背景的动态 Drawable

本文发布于:2024-02-11 20:35:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1683324.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:背景   动态   星空   空间   android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!