-
Notifications
You must be signed in to change notification settings - Fork 1
/
Vehicle.pde
165 lines (131 loc) · 4.44 KB
/
Vehicle.pde
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import java.util.TreeMap;
class Vehicle {
PVector location;
PVector velocity;
PVector acceleration;
float r;
float wandertheta;
float maxforce; // Maximum steering force
float maxspeed; // Maximum speed
TreeMap<String, Object> state;
ArrayList<String> highlights;
int highlightEnd;
PShape shape;
Vehicle(PShape shape, float x, float y) {
this.shape = shape;
acceleration = new PVector(0,0);
velocity = new PVector(0,0);
location = new PVector(x,y);
wandertheta = 0;
maxspeed = 2;
maxforce = 0.05;
state = new TreeMap<String, Object>();
highlights = new ArrayList<String>();
highlightEnd = 0;
}
void randomizeState() {
state.put("red", (float) random(255));
state.put("green", (float) random(255));
state.put("blue", (float) random(255));
state.put("a", (float) random(255));
state.put("b", (float) random(255));
state.put("c", (float) random(255));
highlights.clear();
highlights.addAll(state.keySet());
highlightEnd = millis() + 2000;
}
void run() {
update();
borders();
display();
}
// Method to update location
void update() {
// Update velocity
velocity.add(acceleration);
// Limit speed
velocity.limit(maxspeed);
location.add(velocity);
// Reset accelertion to 0 each cycle
acceleration.mult(0);
}
void wander() {
float wanderR = 25; // Radius for our "wander circle"
float wanderD = 80; // Distance for our "wander circle"
float change = 0.3;
wandertheta += random(-change,change); // Randomly change wander theta
// Now we have to calculate the new location to steer towards on the wander circle
PVector circleloc = velocity.get(); // Start with velocity
circleloc.normalize(); // Normalize to get heading
circleloc.mult(wanderD); // Multiply by distance
circleloc.add(location); // Make it relative to boid's location
float h = velocity.heading2D(); // We need to know the heading to offset wandertheta
PVector circleOffSet = new PVector(wanderR*cos(wandertheta+h),wanderR*sin(wandertheta+h));
PVector target = PVector.add(circleloc,circleOffSet);
seek(target);
// Render wandering circle, etc.
if (debug) drawWanderStuff(location,circleloc,target,wanderR);
}
void applyForce(PVector force) {
// We could add mass here if we want A = F / M
acceleration.add(force);
}
// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
void seek(PVector target) {
PVector desired = PVector.sub(target,location); // A vector pointing from the location to the target
// Normalize desired and scale to maximum speed
desired.normalize();
desired.mult(maxspeed);
// Steering = Desired minus Velocity
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce); // Limit to maximum steering force
applyForce(steer);
}
void display() {
// Draw a triangle rotated in the direction of velocity
float theta = velocity.heading2D() + radians(90);
float red = (Float) state.get("red");
float green = (Float) state.get("green");
float blue = (Float) state.get("blue");
float r = (Float) state.get("r");
float strokeWidth = (Float) state.get("width");
fill(red, green, blue);
stroke(255 - red, 255 - green, 255 - blue);
strokeWeight(strokeWidth);
pushMatrix();
translate(location.x,location.y);
rotate(theta);
beginShape(TRIANGLES);
vertex(0, -r*2);
vertex(-r, r*2);
vertex(r, r*2);
endShape();
popMatrix();
// reset stroke weight
strokeWeight(1);
}
// Wraparound
void borders() {
if (location.x < -r) location.x = width+r;
if (location.y < -r) location.y = height+r;
if (location.x > width+r) location.x = -r;
if (location.y > height+r) location.y = -r;
}
void drawCircleAround(float rad) {
stroke(255);
noFill();
ellipseMode(CENTER);
ellipse(location.x, location.y, rad*2, rad*2);
}
}
// A method just to draw the circle associated with wandering
void drawWanderStuff(PVector location, PVector circle, PVector target, float rad) {
stroke(255);
noFill();
ellipseMode(CENTER);
ellipse(circle.x,circle.y,rad*2,rad*2);
ellipse(target.x,target.y,4,4);
line(location.x,location.y,circle.x,circle.y);
line(circle.x,circle.y,target.x,target.y);
}