-
Notifications
You must be signed in to change notification settings - Fork 15
/
GravitationalAttraction.kt
103 lines (85 loc) · 2.5 KB
/
GravitationalAttraction.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package examples.forces
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.input.pointer.pointerMoveFilter
import k5
import math.Vector2D
import math.constrain
import math.divide
import math.k5Random
import math.magSq
import math.plusAssign
import math.set
import math.setMag
import math.sub
import math.timesAssign
import math.toOffSet
import kotlin.math.sqrt
import kotlin.random.Random
data class Moon(val x: Float, val y: Float, val m: Float) {
val position = Vector2D(x, y)
val velocity = Vector2D.randomVector()
val acceleration = Vector2D(0f, 0f)
val mass = m
val r = sqrt(mass) * 2
init {
velocity *= 10f
}
fun applyForce(force: Vector2D) {
val f = force.divide(mass)
acceleration += f
}
fun update() {
velocity += acceleration
position += velocity
acceleration *= 0f
}
fun render(drawScope: DrawScope) {
drawScope.drawCircle(Color.White, r, position.toOffSet())
}
}
data class Attractor(val x: Float, val y: Float, val m: Float) {
val position = Vector2D(x, y)
val mass = m
val radius = sqrt(mass) * 2
fun attract(ball: Moon) {
val attractorPosition = position.copy()
val force = attractorPosition.sub(ball.position)
val distanceSq = constrain(force.magSq(), 100f, 1000f)
val G = 5 // Universal Gravitational Constant
val gPull = G * (mass * ball.mass) / distanceSq
force.setMag(gPull)
ball.applyForce(force)
}
fun render(drawScope: DrawScope) {
drawScope.drawCircle(Color.Magenta, radius, position.toOffSet())
}
}
@OptIn(ExperimentalComposeUiApi::class)
fun gravitationalPull() = k5 {
val moons = List(15) {
Moon(
k5Random(50, dimensFloat.width.toInt()),
k5Random(50, dimensFloat.height.toInt()),
Random.nextInt(30, 100).toFloat()
)
}
val attractor = Attractor(dimensFloat.width / 2, dimensFloat.height / 2, 600f)
show(
modifier = Modifier.pointerMoveFilter(
onMove = {
attractor.position.set(Vector2D(it.x, it.y))
false
}
)
) { drawScope ->
attractor.render(drawScope)
for (moon in moons) {
moon.update()
moon.render(drawScope)
attractor.attract(moon)
}
}
}