Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c4edb49

Browse files
update particle samples
1 parent 695d281 commit c4edb49

File tree

2 files changed

+68
-43
lines changed

2 files changed

+68
-43
lines changed

‎Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/ParticleAnimations.kt

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.material.Button
2121
import androidx.compose.material.Slider
2222
import androidx.compose.material.Text
2323
import androidx.compose.runtime.Composable
24-
import androidx.compose.runtime.DisposableEffect
2524
import androidx.compose.runtime.LaunchedEffect
2625
import androidx.compose.runtime.Stable
2726
import androidx.compose.runtime.getValue
@@ -46,7 +45,7 @@ import androidx.compose.ui.res.painterResource
4645
import androidx.compose.ui.tooling.preview.Preview
4746
import androidx.compose.ui.unit.dp
4847
import androidx.compose.ui.unit.sp
49-
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.mapInRange
48+
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.scale
5049
import com.smarttoolfactory.tutorial1_1basics.chapter6_graphics.toPx
5150
import com.smarttoolfactory.tutorial1_1basics.ui.Pink400
5251
import kotlinx.coroutines.CancellationException
@@ -58,11 +57,11 @@ fun SingleParticleTrajectorySample() {
5857

5958
var progress by remember { mutableFloatStateOf(0f) }
6059

61-
var visibilityThresholdLow by remember {
60+
var trajectoryProgressStart by remember {
6261
mutableFloatStateOf(0f)
6362
}
6463

65-
var visibilityThresholdHigh by remember {
64+
var trajectoryProgressEnd by remember {
6665
mutableFloatStateOf(1f)
6766
}
6867

@@ -80,7 +79,7 @@ fun SingleParticleTrajectorySample() {
8079

8180
val particleState = rememberParticleState()
8281

83-
LaunchedEffect(visibilityThresholdLow, visibilityThresholdHigh) {
82+
LaunchedEffect(trajectoryProgressStart, trajectoryProgressEnd) {
8483
particleState.particleList.clear()
8584
particleState.addParticle(
8685
Particle(
@@ -91,18 +90,17 @@ fun SingleParticleTrajectorySample() {
9190
),
9291
initialSize = Size(5.dp.toPx(), 5.dp.toPx()),
9392
endSize = Size(sizePx, sizePx),
94-
finalCenter = Offset(
93+
displacement = Offset(
9594
sizePxHalf,
9695
sizePxHalf
9796
),
98-
trajectoryProgressRange = visibilityThresholdLow..visibilityThresholdHigh,
97+
trajectoryProgressRange = trajectoryProgressStart..trajectoryProgressEnd,
9998
row = 0,
10099
column = 0
101100
)
102101
)
103102
}
104103

105-
106104
Column(
107105
modifier = Modifier.fillMaxSize()
108106
.verticalScroll(rememberScrollState())
@@ -158,22 +156,22 @@ fun SingleParticleTrajectorySample() {
158156
}
159157
)
160158

161-
Text("visibilityThresholdLow: $visibilityThresholdLow")
159+
Text("trajectoryProgressStart: $trajectoryProgressStart")
162160
Slider(
163161
modifier = Modifier.fillMaxWidth(),
164-
value = visibilityThresholdLow,
162+
value = trajectoryProgressStart,
165163
onValueChange = {
166-
visibilityThresholdLow = it.coerceAtMost(visibilityThresholdHigh)
164+
trajectoryProgressStart = it.coerceAtMost(trajectoryProgressEnd)
167165
},
168166
valueRange = 0f..1f
169167
)
170168

171-
Text("visibilityThresholdHigh: $visibilityThresholdHigh")
169+
Text("trajectoryProgressEnd: $trajectoryProgressEnd")
172170
Slider(
173171
modifier = Modifier.fillMaxWidth(),
174-
value = visibilityThresholdHigh,
172+
value = trajectoryProgressEnd,
175173
onValueChange = {
176-
visibilityThresholdHigh = it.coerceAtLeast(visibilityThresholdLow)
174+
trajectoryProgressEnd = it.coerceAtLeast(trajectoryProgressStart)
177175
},
178176
valueRange = 0f..1f
179177
)
@@ -188,7 +186,7 @@ fun ParticleAnimationSample() {
188186
modifier = Modifier
189187
.fillMaxSize()
190188
.verticalScroll(rememberScrollState())
191-
.padding(16.dp),
189+
.padding(horizontal =16.dp, vertical =32.dp),
192190
verticalArrangement = Arrangement.spacedBy(8.dp)
193191
) {
194192

@@ -201,11 +199,15 @@ fun ParticleAnimationSample() {
201199

202200
val context = LocalContext.current
203201

202+
var progress by remember {
203+
mutableFloatStateOf(0f)
204+
}
204205
Image(
205206
painter = painterResource(R.drawable.avatar_2_raster),
206207
modifier = Modifier
207208
.border(2.dp, Color.Red)
208209
.explode(
210+
progress = progress,
209211
particleState = particleState,
210212
onStart = {
211213
Toast.makeText(context, "Animation started...", Toast.LENGTH_SHORT).show()
@@ -218,6 +220,12 @@ fun ParticleAnimationSample() {
218220
contentDescription = null
219221
)
220222

223+
Slider(
224+
value = progress,
225+
onValueChange = {
226+
progress = it
227+
}
228+
)
221229
Button(
222230
modifier = Modifier.fillMaxWidth(),
223231
onClick = {
@@ -231,12 +239,12 @@ fun ParticleAnimationSample() {
231239

232240
data class Particle(
233241
val initialCenter: Offset,
234-
val finalCenter: Offset,
242+
val displacement: Offset,
235243
val initialSize: Size,
236244
val endSize: Size,
237245
val color: Color,
238246
val trajectoryProgressRange: ClosedRange<Float> = 0f..1f,
239-
val velocity: Float = 4 * finalCenter.y,
247+
val velocity: Float = 4 * displacement.y,
240248
val acceleration: Float = -2 * velocity,
241249
val column: Int,
242250
val row: Int
@@ -254,6 +262,7 @@ data class Particle(
254262
}
255263

256264
fun Modifier.explode(
265+
progress: Float,
257266
particleState: ParticleState,
258267
onStart: () -> Unit = {},
259268
onEnd: () -> Unit = {}
@@ -305,11 +314,13 @@ fun Modifier.explode(
305314

306315
if (animationStatus != AnimationStatus.Idle) {
307316

308-
val progress = particleState.progress
317+
// val progress = particleState.progress
309318

310319
particleState.particleList.forEach { particle ->
311320

312-
// particleState.updateParticle(progress, particle)
321+
if (progress > 0 && progress <= 1f) {
322+
particleState.updateParticle(progress, particle)
323+
}
313324

314325
val color = particle.color
315326
val radius = particle.currentSize.width / 2f
@@ -341,7 +352,7 @@ fun rememberParticleState(): ParticleState {
341352
@Stable
342353
class ParticleState internal constructor() {
343354

344-
var particleSize by mutableStateOf(50.dp)
355+
var particleSize by mutableStateOf(200.dp)
345356

346357
val animatable = Animatable(0f)
347358
val particleList = mutableStateListOf<Particle>()
@@ -396,17 +407,23 @@ class ParticleState internal constructor() {
396407
if (color != Color.Unspecified) {
397408

398409
val initialCenter = Offset(pixelCenterX.toFloat(), pixelCenterY.toFloat())
410+
val horizontalDisplacement = width / 2f
411+
val verticalDisplacement = height / 2f
412+
413+
val velocity = 4 * verticalDisplacement
414+
val acceleration = -2 * velocity
415+
399416
particleList.add(
400417
Particle(
401418
initialCenter = initialCenter,
402-
finalCenter = initialCenter.plus(Offset(width /2f, -height /2f)),
419+
displacement = Offset(horizontalDisplacement, verticalDisplacement),
403420
initialSize = Size(particleSize.toFloat(), particleSize.toFloat()),
404421
endSize = Size.Zero,
405422
color = color,
406423
column = column,
407424
row = row,
408-
velocity = 0f,
409-
acceleration = 0f
425+
velocity = velocity,
426+
acceleration = acceleration
410427
)
411428
)
412429

@@ -416,7 +433,7 @@ class ParticleState internal constructor() {
416433
}
417434
}
418435

419-
// println("PARTICLE count: ${particleList.size}")
436+
println("PARTICLE count: ${particleList.size}")
420437

421438
}
422439

@@ -432,22 +449,27 @@ class ParticleState internal constructor() {
432449
// Each 0.1f change in trajectoryProgress 0.5f total range
433450
// corresponds to 0.2f change of current time
434451

435-
val visibilityThresholdLow = trajectoryProgressRange.start
436-
val visibilityThresholdHigh = trajectoryProgressRange.endInclusive
452+
val trajectoryProgressStart = trajectoryProgressRange.start
453+
val trajectoryProgressEnd = trajectoryProgressRange.endInclusive
437454

438455
val startXPosition = initialCenter.x
439456
val startYPosition = initialCenter.x
440457

441-
val maxHorizontalDisplacement = finalCenter.x
458+
val maxHorizontalDisplacement = displacement.x
442459

443460
trajectoryProgress =
444-
if (explosionProgress < visibilityThresholdLow) {
461+
if (explosionProgress < trajectoryProgressStart) {
445462
0f
446-
} else if (explosionProgress > visibilityThresholdHigh) {
463+
} else if (explosionProgress > trajectoryProgressEnd) {
447464
1f
448465
} else {
449-
explosionProgress
450-
.mapInRange(visibilityThresholdLow, visibilityThresholdHigh, 0f, 1f)
466+
scale(
467+
a1 = trajectoryProgressStart,
468+
b1 = trajectoryProgressEnd,
469+
x1 = explosionProgress,
470+
a2 = 0f,
471+
b2 = 1f
472+
)
451473
}
452474

453475
currentTime = trajectoryProgress
@@ -457,12 +479,16 @@ class ParticleState internal constructor() {
457479
// alpha = if (trajectoryProgress < .7f) 1f else
458480
// scale(.7f, 1f, trajectoryProgress, 1f, 0f)
459481

482+
val horizontalDisplacement = maxHorizontalDisplacement * trajectoryProgress
483+
460484
val verticalDisplacement =
461-
currentTime * velocity + 0.5 * acceleration * currentTime * currentTime
485+
velocity * currentTime + 0.5f * acceleration * currentTime * currentTime
486+
487+
println("horizontalDisplacement: $horizontalDisplacement, verticalDisplacement: $verticalDisplacement")
462488

463489
currentPosition = Offset(
464-
x = startXPosition + maxHorizontalDisplacement * trajectoryProgress,
465-
y = (startYPosition - verticalDisplacement).toFloat()
490+
x = startXPosition + horizontalDisplacement,
491+
y = startYPosition - verticalDisplacement
466492
)
467493
}
468494
}
@@ -475,7 +501,7 @@ class ParticleState internal constructor() {
475501
try {
476502
animatable.snapTo(0f)
477503
animatable.animateTo(1f, tween(2000))
478-
animationStatus = AnimationStatus.Idle
504+
// animationStatus = AnimationStatus.Idle
479505
} catch (e: CancellationException) {
480506
println("FAILED: ${e.message}")
481507
}

‎Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics/ParticlePhysics.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ fun ControlledExplosion() {
4343
mutableFloatStateOf(1f)
4444
}
4545

46-
4746
val particleCount = 1
4847

4948
val density = LocalDensity.current
@@ -219,8 +218,13 @@ class ExplodingParticle(
219218
} else if (explosionProgress > visibilityThresholdHigh) {
220219
1f
221220
} else {
222-
explosionProgress
223-
.mapInRange(visibilityThresholdLow, visibilityThresholdHigh, 0f, 1f)
221+
scale(
222+
a1 = visibilityThresholdLow,
223+
b1 = visibilityThresholdHigh,
224+
x1 = explosionProgress,
225+
a2 = 0f,
226+
b2 = 1f
227+
)
224228
}
225229

226230
currentTime = trajectoryProgress
@@ -240,11 +244,6 @@ class ExplodingParticle(
240244
}
241245
}
242246

243-
fun Float.mapInRange(inMin: Float, inMax: Float, outMin: Float, outMax: Float): Float {
244-
return outMin + (((this - inMin) / (inMax - inMin)) * (outMax - outMin))
245-
}
246-
247-
fun Int.dpToPx() = toFloat().dpToPx()
248247
fun Dp.toPx() = value.dpToPx()
249248

250249
fun Float.dpToPx() = this * Resources.getSystem().displayMetrics.density

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /