|
@@ -0,0 +1,121 @@
|
|
1
|
+-- particle type influences attractive/repulsive forces
|
|
2
|
+-- heat
|
|
3
|
+width, height = love.graphics.getDimensions!
|
|
4
|
+clamp = (n, x, y) -> math.max x, math.min y, n
|
|
5
|
+sign = (n) -> math.abs(n) == n and 1 or -1
|
|
6
|
+
|
|
7
|
+class Particle
|
|
8
|
+ new: (n=1, x, y) =>
|
|
9
|
+ rng = love.math.newRandomGenerator n
|
|
10
|
+ @color = { rng\random!, rng\random!, rng\random!, 1 }
|
|
11
|
+ @mass = n
|
|
12
|
+ @charge = n % 5 - 2
|
|
13
|
+ @radius = math.log(n + 10)
|
|
14
|
+ @x = x or love.math.random 0, width
|
|
15
|
+ @y = y or love.math.random 0, height
|
|
16
|
+ @vx = 0
|
|
17
|
+ @vy = 0
|
|
18
|
+
|
|
19
|
+universe = {}
|
|
20
|
+new = {}
|
|
21
|
+for i=1,500
|
|
22
|
+ table.insert universe, Particle love.math.random 1, 5
|
|
23
|
+-- table.insert universe, Particle 1, width / 2 - 4, height / 2 - 200
|
|
24
|
+-- table.insert universe, Particle 5, width / 2 + 4, height / 2 - 200
|
|
25
|
+-- table.insert universe, Particle 1, width / 2 - 4, height / 2 + 200
|
|
26
|
+-- table.insert universe, Particle 1, width / 2 + 4, height / 2 + 200
|
|
27
|
+
|
|
28
|
+physics = (a, b) ->
|
|
29
|
+ -- distance, direction, collision checks
|
|
30
|
+ dx = a.x - b.x
|
|
31
|
+ dy = a.y - b.y
|
|
32
|
+ d2 = dx * dx + dy * dy
|
|
33
|
+ theta = math.atan2 dy, dx
|
|
34
|
+ x = math.cos theta
|
|
35
|
+ y = math.sin theta
|
|
36
|
+ r2 = (a.radius + b.radius)^2
|
|
37
|
+ m = a.mass + b.mass
|
|
38
|
+ if d2 > r2
|
|
39
|
+ -- gravitational force
|
|
40
|
+ g = 1 / d2
|
|
41
|
+ a.vx -= b.mass * g * x
|
|
42
|
+ a.vy -= b.mass * g * y
|
|
43
|
+ b.vx += a.mass * g * x
|
|
44
|
+ b.vy += a.mass * g * y
|
|
45
|
+ -- electromotive force
|
|
46
|
+ unless a.charge == 0 or b.charge == 0
|
|
47
|
+ e = (math.abs(a.charge) + math.abs(b.charge))^3 / d2^2
|
|
48
|
+ -- print a.charge, b.charge, e
|
|
49
|
+ if sign(a.charge) == sign(b.charge)
|
|
50
|
+ a.vx -= b.charge * e * x
|
|
51
|
+ a.vy -= b.charge * e * y
|
|
52
|
+ b.vx += a.charge * e * x
|
|
53
|
+ b.vy += a.charge * e * y
|
|
54
|
+ else
|
|
55
|
+ a.vx -= b.charge * e * x
|
|
56
|
+ a.vy -= b.charge * e * y
|
|
57
|
+ b.vx -= a.charge * e * x
|
|
58
|
+ b.vy -= a.charge * e * y
|
|
59
|
+ elseif d2 < math.log(r2) / m^3 / 10
|
|
60
|
+ -- making new elements
|
|
61
|
+ p = Particle m
|
|
62
|
+ p.vx = a.vx / a.mass + b.vx / b.mass
|
|
63
|
+ p.vy = a.vy / a.mass + b.vy / b.mass
|
|
64
|
+ p.x = (a.x * a.mass + b.x * b.mass) / m
|
|
65
|
+ p.y = (a.y * a.mass + b.y * b.mass) / m
|
|
66
|
+ a.dirty = true
|
|
67
|
+ b.dirty = true
|
|
68
|
+ table.insert new, p
|
|
69
|
+ else
|
|
70
|
+ -- anti-collision force
|
|
71
|
+ f = math.min 0.4, 100 / math.max d2, 0.01
|
|
72
|
+ a.vx += b.mass * f * x
|
|
73
|
+ a.vy += b.mass * f * y
|
|
74
|
+ b.vx -= a.mass * f * x
|
|
75
|
+ b.vy -= a.mass * f * y
|
|
76
|
+
|
|
77
|
+love.update = (dt) ->
|
|
78
|
+ for a = 1, #universe - 1
|
|
79
|
+ for b = a + 1, #universe
|
|
80
|
+ physics(universe[a], universe[b])
|
|
81
|
+
|
|
82
|
+ for i=#universe, 1, -1
|
|
83
|
+ if universe[i].dirty
|
|
84
|
+ table.remove universe, i
|
|
85
|
+ i += 1
|
|
86
|
+
|
|
87
|
+ while next new
|
|
88
|
+ table.insert universe, table.remove new, 1
|
|
89
|
+
|
|
90
|
+ for particle in *universe
|
|
91
|
+ -- particle.vx *= 0.9
|
|
92
|
+ -- particle.vy *= 0.9
|
|
93
|
+ particle.x += particle.vx * dt
|
|
94
|
+ particle.y += particle.vy * dt
|
|
95
|
+
|
|
96
|
+love.draw = ->
|
|
97
|
+ types = {}
|
|
98
|
+ for particle in *universe
|
|
99
|
+ if types[particle.mass]
|
|
100
|
+ types[particle.mass] += 1
|
|
101
|
+ else
|
|
102
|
+ types[particle.mass] = 1
|
|
103
|
+ love.graphics.setColor particle.color
|
|
104
|
+ love.graphics.circle "fill", particle.x, particle.y, particle.radius
|
|
105
|
+
|
|
106
|
+ -- love.graphics.setColor 1, 1, 1, 0.5
|
|
107
|
+ -- love.graphics.line width / 2, 0, width / 2, height
|
|
108
|
+ love.graphics.setColor 1, 1, 1, 1
|
|
109
|
+ love.graphics.print #universe
|
|
110
|
+ for i,v in ipairs types
|
|
111
|
+ love.graphics.print "#{i}->#{v}", 0, i * 12
|
|
112
|
+
|
|
113
|
+love.mousepressed = (x, y) ->
|
|
114
|
+ for i=1,50
|
|
115
|
+ a = x + love.math.random -25, 25
|
|
116
|
+ b = y + love.math.random -25, 25
|
|
117
|
+ table.insert universe, Particle 1, a, b
|
|
118
|
+
|
|
119
|
+love.keypressed = (key) ->
|
|
120
|
+ love.event.quit! if key == "escape"
|
|
121
|
+ table.insert universe, Particle!
|