Repository navigation
Expand file tree
/
Copy pathflock.html
More file actions
109 lines (93 loc) · 3.9 KB
/
Copy pathflock.html
File metadata and controls
109 lines (93 loc) · 3.9 KB
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
104
105
106
107
108
109
<html>
<head>
<title>Flock Model</title>
<script src="../lib/agentscript.js"></script>
<script src="../tools/coffee-script.js"></script>
<script type="text/coffeescript">
u = ABM.Util # Aliases
Shapes = ABM.Shapes
class MyModel extends ABM.Model
setVision: (@vision) -> @patches.cacheRect @vision, true
setMaxTurn: (maxTurn) -> @maxTurn = u.degToRad(maxTurn)
toggleConsole: () -> @useConsole = not @useConsole
setup: ->
# u.randomSeed() # use for repeatable runs
@refreshPatches = false # <3fps->4fps turtles larger part of drawing
# No optimizations: 4fps
# @patches.usePixels() # 4fps same as refresh off
@patches.cacheTurtlesHere() # 17fps, big help for inRadius
# w/ refresh off and two optimizations, 22-23fps
# Deprecated:
# @turtles.setUseSprites() # 24 -> 36
@turtles.setDefault "useSprites", true
@anim.setRate 60# , false, false # multistep, noRAF
@useConsole = true
@population = 150 # turtles (was more, Chrome regression problem)
@setVision 3 # patches & set patch rect
@minSeparation = 0.75 # patches
@setMaxTurn(3.0) # degrees -> radians
# defaults
@turtles.setDefault "size", 1.5
# @turtles.setDefault "color", [255,0,0] # slightly faster! ->38/39 ??
p.color = u.randomGray 0, 100 for p in @patches
p.sprout 1 for p in @patches.nOf(@population)
#a.color = u.randomMapColor() for a in @turtles
step: ->
if @useConsole and @anim.ticks % 100 is 0
console.log "flock alignment: #{@reportFlockVectorSize()}"
@flock(a) for a in @turtles
flock: (a) -> # a is turtle
# These two forms are identical
# flockmates = @turtles.inRadius(a, @vision).other(a)
flockmates = a.inRadius(@turtles, @vision).other(a)
if flockmates.length isnt 0
[nearestNeighbor, d] = u.minOneOf flockmates, ((f) -> f.distance a), true
if d < @minSeparation
@separate a, nearestNeighbor
else
@align a, flockmates
@cohere a, flockmates
a.forward .5 # move partial patch for smooth animation.
separate: (a, nearest) ->
h = nearest.towards a; @turnTowards a, h
align: (a, flockmates) ->
@turnTowards a, @averageHeading(flockmates)
cohere: (a, flockmates) ->
@turnTowards a, @averageHeadingTowards(a, flockmates)
turnTowards: (a, heading) ->
turn = u.subtractRads heading, a.heading # angle from h to a
turn = u.clamp turn, -@maxTurn, @maxTurn # limit the turn
a.rotate turn
averageHeading: (flockmates) ->
dx = (Math.sin f.heading for f in flockmates).reduce (x,y) -> x+y
dy = (Math.cos f.heading for f in flockmates).reduce (x,y) -> x+y
@safeAtan dy, dx
averageHeadingTowards: (a, flockmates) ->
dx = (Math.sin f.towards a for f in flockmates).reduce (x,y) -> x+y
dy = (Math.cos f.towards a for f in flockmates).reduce (x,y) -> x+y
@safeAtan dy, dx
safeAtan: (x,y) -> Math.atan2 y, x # if x is 0 and y is 0 then 0 else Math.atan2 y, x # atan ok if x 0
reportFlockVectorSize: ->
dx = (Math.sin a.heading for a in @turtles).reduce (x,y) -> x+y
dy = (Math.cos a.heading for a in @turtles).reduce (x,y) -> x+y
Math.sqrt(dx*dx + dy*dy)/@population
# div, patchSize, minX, maxX, minY, maxY, isTorus, hasNeighbors
# Defaults: 13, -16, 16, -16, 16, false, true
model = new MyModel({
div: "layers",
size: 15,
minX: -16,
maxX: 16,
minY: -16,
maxY: 16,
isTorus: true,
hasNeighbors: false
})
.debug() # Debug: Put Model vars in global name space
.start() # Run model immediately after startup initialization
</script>
</head>
<body>
<div id="layers"></div>
</body>
</html>