
이 장면에서 빛이 내려오는 효과를 구현했으니 이제 나뭇잎도 떨어지는 효과를 만들어 볼 것이다.
분석을 해보자면
1. 오른쪽에서 대각선으로 모두 일정한 방향으로 떨어짐
2. 떨어지면서 회전함
이렇게 2가지 종류의 애니메이션이 있다.
var things by remember {
mutableStateOf(
List(10) {
val x = Random.nextInt(screenWidthPx.toInt()).toFloat()
val y = Random.nextInt(screenHeightPx.toInt() / 2).toFloat()
val offset = if (Random.nextInt(2) == 1) {
Offset(x, -y)
} else {
Offset(screenWidthPx + x, y)
}
val imageSize = Random.nextInt(10, 40).dp
Leaf(offset, imageSize, 0f)
}
)
}
빛이 내리는 효과랑 비슷하게 초기값을 랜덤으로 설정해주는데 위쪽과 오른쪽 바깥쪽에서 생성되도록 해주었다.
LaunchedEffect(Unit) {
while (true) {
things = things.map { thing ->
val newX = thing.offset.x - 20f
val newY = thing.offset.y + 20f
val offset = if (newX <= 0 || newY >= screenHeightPx) {
val x = Random.nextInt(screenWidthPx.toInt()).toFloat()
val y = Random.nextInt(screenHeightPx.toInt() / 2).toFloat()
if (Random.nextInt(2) == 1) {
Offset(x, -y)
} else {
Offset(screenWidthPx + x, y)
}
} else {
Offset(newX, newY)
}
val rotate = (thing.rotate + 2) % 360
thing.copy(offset = offset, rotate = rotate)
}
delay(100L)
}
}
20f만큼 왼쪽 아래로 모두가 일정하게 이동하도록 하였다.
화면 밖으로 나가면 다시 초기값을 생성한다.
위 코드를 보면
val rotate = (thing.rotate + 2) % 360
이 있다. 초기 rotate값을 기준으로 2도씩 계속 돌아가도록 설정해주었다.
@Composable
fun WindBlownDiagonalEffect(
resourceId: Int,
) {
val configuration = LocalConfiguration.current
val density = LocalDensity.current
val screenWidthPx = with(density) {
configuration.screenWidthDp * this.density
}
val screenHeightPx = with(density) {
configuration.screenHeightDp * this.density
}
var things by remember {
mutableStateOf(
List(10) {
val x = Random.nextInt(screenWidthPx.toInt()).toFloat()
val y = Random.nextInt(screenHeightPx.toInt() / 2).toFloat()
val offset = if (Random.nextInt(2) == 1) {
Offset(x, -y)
} else {
Offset(screenWidthPx + x, y)
}
val imageSize = Random.nextInt(10, 40).dp
Leaf(offset, imageSize, 0f)
})
}
LaunchedEffect(Unit) {
while (true) {
things = things.map { thing ->
val newX = thing.offset.x - 20f
val newY = thing.offset.y + 20f
val offset = if (newX <= 0 || newY >= screenHeightPx) {
val x = Random.nextInt(screenWidthPx.toInt()).toFloat()
val y = Random.nextInt(screenHeightPx.toInt() / 2).toFloat()
if (Random.nextInt(2) == 1) {
Offset(x, -y)
} else {
Offset(screenWidthPx + x, y)
}
} else {
Offset(newX, newY)
}
val rotate = (thing.rotate + 2) % 360
thing.copy(offset = offset, rotate = rotate)
}
delay(100L)
}
}
val imageVector = ImageBitmap.imageResource(id = resourceId)
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Transparent)
) {
for (thing in things) {
val offsetX = with(density) {
thing.offset.x.toDp()
}
val offsetY = with(density) {
thing.offset.y.toDp()
}
Image(
bitmap = imageVector,
contentDescription = null,
modifier = Modifier
.size(thing.size)
.offset(
x = offsetX,
y = offsetY
)
.rotate(thing.rotate),
colorFilter = ColorFilter.tint(color = Color(0xFFAE8B4E))
)
}
}
}
data class Leaf(
val offset: Offset,
val size: Dp,
val rotate: Float,
)