Skip to content

Commit cb7d643

Browse files
add ParticlePhysics
1 parent 1bf48e0 commit cb7d643

File tree

1 file changed

+151
-0
lines changed
  • Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package com.smarttoolfactory.tutorial1_1basics.chapter6_graphics
2+
3+
import android.content.res.Resources
4+
import androidx.compose.foundation.Canvas
5+
import androidx.compose.foundation.border
6+
import androidx.compose.foundation.layout.Arrangement
7+
import androidx.compose.foundation.layout.BoxWithConstraints
8+
import androidx.compose.foundation.layout.Column
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
15+
import androidx.compose.material.Slider
16+
import androidx.compose.material.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.runtime.getValue
19+
import androidx.compose.runtime.mutableFloatStateOf
20+
import androidx.compose.runtime.remember
21+
import androidx.compose.runtime.setValue
22+
import androidx.compose.ui.Alignment
23+
import androidx.compose.ui.Modifier
24+
import androidx.compose.ui.geometry.Offset
25+
import androidx.compose.ui.graphics.Color
26+
import androidx.compose.ui.platform.LocalDensity
27+
import androidx.compose.ui.tooling.preview.Preview
28+
import androidx.compose.ui.unit.Dp
29+
import androidx.compose.ui.unit.dp
30+
import androidx.compose.ui.unit.sp
31+
import java.util.Random
32+
33+
@Preview
34+
@Composable
35+
fun ControlledExplosion() {
36+
Column(
37+
modifier = Modifier.fillMaxSize().padding(16.dp),
38+
horizontalAlignment = Alignment.CenterHorizontally
39+
) {
40+
var progress by remember { mutableFloatStateOf(0f) }
41+
42+
Explosion(progress)
43+
44+
Spacer(Modifier.height(16.dp))
45+
Text(text = "Progress: $progress", fontSize = 18.sp)
46+
Slider(
47+
modifier = Modifier.fillMaxWidth(),
48+
value = progress,
49+
onValueChange = {
50+
progress = it
51+
}
52+
)
53+
Spacer(Modifier.height(16.dp))
54+
}
55+
}
56+
57+
@Composable
58+
fun Explosion(
59+
progress: Float
60+
) {
61+
BoxWithConstraints {
62+
63+
val sizeDp = maxWidth
64+
val density = LocalDensity.current
65+
val sizePx = with(density) {
66+
sizeDp.toPx()
67+
}
68+
val sizePxHalf = sizePx / 2
69+
val particles = remember {
70+
List(150) {
71+
ExplodingParticle(
72+
color = Color(listOf(0xffea4335, 0xff4285f4, 0xfffbbc05, 0xff34a853).random()),
73+
startXPosition = sizePxHalf.toInt(),
74+
startYPosition = sizePxHalf.toInt(),
75+
maxHorizontalDisplacement = sizePxHalf,
76+
maxVerticalDisplacement = sizePxHalf
77+
)
78+
}
79+
}
80+
particles.forEach { it.updateProgress(progress) }
81+
82+
Canvas(
83+
modifier = Modifier
84+
.border(width = 1.dp, color = Color(0x26000000))
85+
.size(sizeDp)
86+
) {
87+
drawLine(
88+
color = Color.Black,
89+
start = Offset(sizePxHalf, 0f),
90+
end = Offset(sizePxHalf, sizePx),
91+
strokeWidth = 2.dp.toPx()
92+
)
93+
drawLine(
94+
color = Color.Black,
95+
start = Offset(0f, sizePxHalf),
96+
end = Offset(sizePx, sizePxHalf),
97+
strokeWidth = 2.dp.toPx()
98+
)
99+
particles.forEach { particle ->
100+
drawCircle(
101+
alpha = particle.alpha,
102+
color = particle.color,
103+
radius = 5.dp.toPx(),
104+
center = Offset(particle.currentXPosition, particle.currentYPosition),
105+
)
106+
}
107+
}
108+
}
109+
}
110+
111+
class ExplodingParticle(
112+
val color: Color,
113+
val startXPosition: Int,
114+
val startYPosition: Int,
115+
val maxHorizontalDisplacement: Float,
116+
val maxVerticalDisplacement: Float
117+
) {
118+
private val velocity = 4 * maxVerticalDisplacement
119+
private val acceleration = -2 * velocity
120+
var currentXPosition = 0f
121+
var currentYPosition = 0f
122+
123+
var alpha = 1f
124+
125+
fun updateProgress(explosionProgress: Float) {
126+
val currentTime = explosionProgress * 1f
127+
128+
val verticalDisplacement =
129+
currentTime * velocity + 0.5 * acceleration * currentTime * currentTime
130+
131+
currentXPosition = startXPosition + maxHorizontalDisplacement * explosionProgress
132+
currentYPosition = (startYPosition - verticalDisplacement).toFloat()
133+
134+
}
135+
}
136+
137+
fun Float.mapInRange(inMin: Float, inMax: Float, outMin: Float, outMax: Float): Float {
138+
return outMin + (((this - inMin) / (inMax - inMin)) * (outMax - outMin))
139+
}
140+
141+
fun Int.dpToPx() = toFloat().dpToPx()
142+
fun Dp.toPx() = value.dpToPx()
143+
144+
fun Float.dpToPx() = this * Resources.getSystem().displayMetrics.density
145+
146+
147+
private val random = Random()
148+
fun Float.randomTillZero() = this * random.nextFloat()
149+
fun randomInRange(min: Float, max: Float) = min + (max - min).randomTillZero()
150+
fun randomBoolean(trueProbabilityPercentage: Int) =
151+
random.nextFloat() < trueProbabilityPercentage / 100f

0 commit comments

Comments
 (0)