0% found this document useful (0 votes)
2 views11 pages

Lab 3 GC

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views11 pages

Lab 3 GC

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

MINISTERUL EDUCAT, IEI, CULTURII S, I CERCETĂRII

AL REPUBLICII MOLDOVA
Universitatea Tehnică a Moldovei
Facultatea Calculatoare, Informatică şi Microelectronică
Departamentul Inginerie Software s, i Automatică

BELIH DMITRII FAF-232

REPORT
Laboratory work n.3
of Computer Graphics

Checked by:
Olga Grosu, university assistant
DISA, FCIM, UTM

Chis, inău – 2024


1. The Purpose of the Laboratory Work
The goal of this lab work is to understand how to simulate behavior through physical attributes such as acceler-
ation, velocity, and position. Learn how to use vectors to simulate movement in 2D space. Develop individual
creature personalities based on interaction rules (e.g., avoiding collisions, chasing prey, wandering randomly).
Demonstrate how acceleration-based control creates natural, organic motion.

2. The Condition
Create a simulation of an ecosystem. Imagine a population of computational creatures swimming around a digital
pond, interacting with each other according to various rules.
Develop a set of rules for simulating the real-world behavior of a creature, such as a nervous fly, swimming fish,
hopping bunny, slithering snake, etc. Can you control the object’s motion by only manipulating the acceleration?
Try to give the creature a personality through its behavior (rather than through its visual design).

• Use array of creature objects class and PVector class:

• Pvector location, Pvector velocity, Pvector acceleration.

3. The Program Code

1 //Code for the laboratory work Belih Dmitrii


2

3 ArrayList<PVector> points;
4 float sunX = 100; // X
5 float sunY = 70; // Y
6 float sunZ = -70; // Z ( )
7 NervousFly nervousFly;
8 Environment environment;
9

10 void setup() {
11 size(800, 600, P3D); // P3D 3D

12 background(135, 206, 235); //


13 points = new ArrayList<PVector>();
14 points.add(new PVector(0, 0));
15 nervousFly = new NervousFly();
16 environment = new Environment();
17 }
18

19 void draw() {
20 background(135, 206, 235); //
21

22 drawSun(); //
23 drawGrass(); //

1
24 drawPath(); //
25 drawPond(); //
26

27 environment.display();
28 drawFlower(); //
29

30 drawAnimal();
31

32 nervousFly.update();
33 nervousFly.checkEdges();
34 nervousFly.display();
35 }
36

37 void drawSun() {
38 // ( )
39 stroke(255, 242, 98);
40 strokeWeight(2);
41 noFill();
42 pushMatrix();
43 translate(sunX, sunY, sunZ); //

44 timedTumble(40); //
45 pointSphereFibonacci(80, 600); //
46 popMatrix();
47 }
48

49 void drawFlower() {
50 //
51 stroke(23, 116, 2);
52 float offsetX = 550;
53 float offsetY = 100;
54

55 for (int i = 0; i < points.size(); i++)


56 point(map(points.get(i).x, -2.1820, 2.6558, 0, 200) + offsetX, map(points.get(i).y,
9.9983, 0, 0, 200) + offsetY);
57

58 for (int i = 0; i < 100; i++) {


59 PVector currentPoint = points.get(points.size()-1);
60 PVector newPoint = new PVector(0, 0);
61

62 float r = random(1);
63 if (r > 0.99) {
64 newPoint.x = 0;
65 newPoint.y = currentPoint.y * 0.16;
66 } else if (r > 0.92) {
67 newPoint.x = currentPoint.x * 0.2 + currentPoint.y * -0.26;
68 newPoint.y = currentPoint.x * 0.23 + currentPoint.y * 0.22 + 1.6;
69 } else if (r > 0.85) {
70 newPoint.x = currentPoint.x * -0.15 + currentPoint.y * 0.28;

2
71 newPoint.y = currentPoint.x * 0.26 + currentPoint.y * 0.24 + 0.44;
72 } else {
73 newPoint.x = currentPoint.x * 0.85 + currentPoint.y * 0.04;
74 newPoint.y = currentPoint.x * -0.04 + currentPoint.y * 0.85 + 1.6;
75 }
76 points.add(newPoint);
77 }
78 }
79

80 //
81 void drawPath() {
82 fill(139, 69, 19); //
83 noStroke();
84

85 float pathWidth = 60; //


86

87 beginShape();
88

89 // :

90 for (float t = 0; t <= 1; t += 0.05) {


91 float x = lerp(width, 0, t); // X
92 float y = lerp(height / 2, height, t); //
Y
93 float yOffset = sin(t * PI * 2) * 30; // -
94 vertex(x, y + yOffset); //
95 }
96

97 // :

98 for (float t = 1; t >= 0; t -= 0.05) {


99 float x = lerp(width, 0, t);
100 float y = lerp(height / 2, height, t);
101 float yOffset = sin(t * PI * 2) * 30;
102 vertex(x, y + pathWidth + yOffset); //
103 }
104

105 endShape(CLOSE); //

106 }
107

108 void drawPond() {


109 //
110 fill(205, 133, 63); //
111 ellipse(width / 2, height / 1.45, 500, 110); //
112

113 //
114 fill(0, 191, 255); //
115 ellipse(width / 2, height / 1.45, 450, 100); //

3
116 }
117

118

119 void drawGrass() {


120 fill(34, 139, 34); //
121 noStroke();
122 rect(0, height / 2, width, height / 2); //
123 }
124

125

126 //// Timed 3D tumble, rotations cycle back to start every ‘duration‘ milliseconds
127 void timedTumble(float duration) {
128 duration = duration * 1000; // milliseconds
129 float spin = TWO_PI * 2 * (millis() % duration) / duration;
130 rotateX(spin);
131 rotateY(spin / 2);
132 rotateZ(spin / 8);
133 }
134

135 void pointSphereFibonacci(int radius, int points) {


136 //

137 float phi = (sqrt(5) + 1) / 2 - 1; //


138 float ga = phi * 2 * PI; //
139 for (int i = 1; i <= points; ++i) {
140 float lon = ga * i;
141 lon /= 2 * PI; lon -= floor(lon); lon *= 2 * PI;
142 if (lon > PI) lon -= 2 * PI;
143 float lat = asin(-1 + 2 * i / (float)points);
144 pushMatrix();
145 rotateY(lon);
146 rotateZ(-lat);
147 point(radius, 0, 0);
148 popMatrix();
149 }
150 }
151

152 // NERVOUS FLY


153

154 int LENGTH = 10;


155

156 class NervousFly extends Mover {


157

158 void update() {


159 float xloc = map(noise(tx), 0, 1, 0, width);
160 float yloc = map(noise(ty), 0, 1, 0, height / 2);
161

162 location.x = xloc;

4
163 location.y = yloc;
164 tx += 0.01;
165 ty += 0.01;
166 }
167

168 void display() {


169 noStroke();
170 fill(0); //
171 ellipse(location.x, location.y, 8, 8);
172

173 fill(50); //
174 ellipse(location.x - 4, location.y - 4, 6, 12); //
175 ellipse(location.x + 4, location.y - 4, 6, 12); //
176

177 fill(0); //
178 ellipse(location.x, location.y - 6, 4, 4); //
179 }
180 }
181

182 class Mover {


183 PVector location;
184 PVector velocity;
185 PVector acceleration;
186 float tx, ty;
187 float topSpeed;
188 float mass;
189 float G;
190

191 Mover() {
192 location = new PVector(random(width), random(height));
193 velocity = new PVector(0, 0);
194 acceleration = new PVector(0, 0);
195 topSpeed = 4.0;
196 tx = 0.0;
197 ty = 10000.0;
198 mass = 1.0;
199 G = 0.04;
200 }
201

202 void update() {


203 }
204

205 void display() {


206 }
207

208 boolean checkNegativeFrictionPocket() {


209 if ((location.x >= 320 && location.x <= 340) &&
210 (location.y >= 20 && location.y <= 280)) {
211 return true;

5
212 } else {
213 return false;
214 }
215 }
216

217 void applyForce(PVector force) {


218 // No more wrapping around the edges
219 // There are force fields at all edges now
220

221 acceleration.add(force);
222 }
223

224 void checkEdges() {


225 float rightDistance = abs(location.x - width);
226 float leftDistance = abs(location.x - 0);
227 float topDistance = abs(location.y - height);
228 float bottomDistance = abs(location.y - 0);
229

230 if (rightDistance <= 40) {


231 applyForce(new PVector(-rightDistance, rightDistance));
232

233 } else if (leftDistance <= 40) {


234 applyForce(new PVector(leftDistance, leftDistance));
235 }
236

237 if (bottomDistance <= 40) {


238 applyForce(new PVector(bottomDistance, -bottomDistance));
239

240 } else if (topDistance <= 40) {


241 applyForce(new PVector(topDistance, topDistance));
242 }
243 }
244 }
245

246

247 class Environment {


248 Bubbles[] bubbles;
249 float colorChanger;
250

251 Environment() {
252 colorChanger = 0;
253 bubbles = new Bubbles[100];
254 for (int i = 0; i < 100; i++) {
255 float bubbleX = random(width / 2 - 225, width / 2 + 225); //

256 float bubbleY = random(height / 1.45 - 50, height / 1.45 + 50); //

257 bubbles[i] = new Bubbles(bubbleX, bubbleY);


258 }

6
259 }
260

261

262 void display() {


263 //
264 for (int i = 0; i < bubbles.length; i++) {
265 bubbles[i].display();
266 bubbles[i].move();
267 }
268 }
269 }
270

271 //
272 class Bubbles {
273 float x, y;
274 float speedX, speedY;
275

276 Bubbles(float x_, float y_) {


277 x = x_;
278 y = y_;
279 speedX = random(-1, 1);
280 speedY = random(-1, 1);
281 }
282

283 void display() {


284 fill(245, 100); //
285 ellipse(x, y, 5, 5);
286 }
287

288 void move() {


289 x += speedX;
290 y += speedY;
291

292 //

293 if (x < width / 2 - 225 || x > width / 2 + 225) speedX *= -1;


294 if (y < height / 1.5 - 50 || y > height / 1.5 + 50) speedY *= -1;
295 }
296 }
297 void drawAnimal() {
298 //
299 fill(250, 212, 243);
300 noStroke();
301 ellipse(360, 230, 100, 100); //
302 ellipse(318, 241, 75, 75); //
303 rect(282, 233, 128, 90); //
304

305 //
306 ellipse(412, 315, 25, 25);

7
307 rect(320, 317, 25, 35);
308 rect(345, 317, 25, 35);
309 ellipse(365, 345, 25, 15);
310 ellipse(322, 345, 25, 15);
311

312 //
313 fill(255, 250, 250);
314 ellipse(340, 225, 23, 23);
315 ellipse(364, 225, 23, 23);
316

317 fill(0, 0, 1);


318 ellipse(340, 226, 5, 5);
319 ellipse(365, 226, 5, 5);
320

321 //
322 stroke(0);
323 strokeWeight(4);
324 arc(380, 255, 15, 25, PI / 2, 3 * PI / 2); //
325 arc(354, 252, 11, 20, PI / 2, 3 * PI / 2); //
326 arc(352, 274, 33, 11, 0, PI); //
327

328 //
329 fill(255, 62, 136);
330 ellipse(353, 241, 15, 5);
331 noFill();
332

333 stroke(0);
334 strokeWeight(4);
335 arc(351, 251, 45, 25, 0, PI); //
336

337 //
338 pushMatrix();
339 rotate(radians(-35));
340 noStroke();
341 fill(250, 212, 243);
342 ellipse(214, 367, 50, 30);
343 ellipse(223, 385, 50, 30);
344 popMatrix();
345

346 //
347 stroke(0);
348 strokeWeight(1.2);
349 fill(255, 253, 193);
350 rect(283, 288, 126, 35);
351

352 //
353 stroke(0);
354 strokeWeight(1.4);
355 fill(201, 171, 0);

8
356 rect(282, 309, 137, 15);
357

358 //
359 fill(108, 92, 0);
360 ellipse(349, 299, 8, 11);
361 ellipse(349, 291, 10, 7);
362

363 //
364 fill(250, 212, 243);
365 stroke(0);
366 strokeWeight(0.8);
367 rect(282, 270, 15, 50, 10); //
368 rect(395, 270, 15, 50, 10); //
369

370 //
371 fill(201, 171, 0);
372 rect(320, 323, 25, 15);
373 rect(344, 323, 25, 15);
374 }

4. Screen Captures of the Program Execution

Figure 1: Program execution showing the creature sketch

9
5. Conclusion
In this lab, I successfully created a simulation of an ecosystem featuring a nervous fly, which exhibits behavior
reminiscent of real-world creatures. The use of the PVector class allowed for effective manipulation of the crea-
ture’s position and movement dynamics through acceleration. The fly’s erratic motion, driven by Perlin noise,
simulates a nervous disposition, making it appear as if it is darting around in response to its environment. Ad-
ditionally, the inclusion of environmental elements, such as the sun, grass, a pond, and bubbles, enhances the
ecosystem’s realism and interactivity.
The simulation illustrates how behavioral rules can be applied to create a dynamic and engaging environment,
allowing the nervous fly to navigate its surroundings while interacting with other elements. This project highlights
the importance of incorporating personality and behavior into computational creatures, transforming the visual
representation into a more lifelike experience. Overall, the lab demonstrates the principles of physics and behavior
in a digital ecosystem, paving the way for more complex simulations in the future.

10

You might also like