Interactive Simulation: Urban System
Brief
Create a sketch that would simulate an existing natural system - look at physics, biology, and other natural sciences for good examples. Start with the environment - where is the system situated? What are the forces the environment might exert on the system? Examine the agents in the system, their relationships to each other and the environment they are in. The look at how this system would develop over time. What are the rules that you are going to come up with, what are the parameters you are going to feed into them and what effect will the changes have on the development of the system.
create classes of entities to represent the components of the system
use vectors to represent forces existing in the system
use randomness or noise to generate at least one
add direct or indirect mouse or keyboard controls
Ideation
First Phase (In-Class)
When I was first introduced to this brief, my idea was to create a eco system in rainforest. Then I changed my plan because eco system in rainforest was too complicated for me.
Next idea was a very simple sketch where cows are eating grass, and when they eat 70% of the grass on the canvas, cows would leave (no food for them). Although it was a very simple idea, I was having trouble making path that follows cows to indicate that the area was eaten already. It wasn’t for me.
Here are the ideation sketches that I designed during the workshop:
After the first phase at the workshop, I went home very, very sad.
Second Phase (Revenge)
After the class, right outside of my apartment I almost got hit by a car. With a lot of frustration, I decided to just change everything that I brainstormed during the class, and make a road full of cars and a poor pedestrian who increases their anxiety level whenever getting hit by cars.
Here are some of the ideas I wanted to include:
The system is situated in an urban city environment with cars, traffic lights, and a pedestrian.
The environment exerts forces on the cars in the form of traffic lights that control when the cars can move. Additionally, there's the presence of a pedestrian who interacts with the cars.
The agents in the system
cars (the cars interact with traffic lights and potentially with the pedestrian)
traffic lights
a pedestrian
The system develops over time as cars move, obey traffic lights, and potentially interact with the pedestrian. Traffic lights change colors over time.
After creating this first design, I realized that there were some issues:
The cars were too big considering that this is a small 800x400 canvas
As you see the number “1012”, whenever a car touch a pedestrian the number goes up way too much, even if it’s just a one second interaction
This design didn’t include function triggered by mouse or keyboard, so there was no interaction
Final Design: Urban System
After the second phase, I started implementing what I thought would be able to do to make the design better. This includes adjusting the size of the cars and adding mouse and/or keyboard triggers to the design.
Here’s the video of the final design:
The rules of the system include traffic light behavior, car movement, car interaction with traffic lights, and interaction with the pedestrian.
The code uses vectors for positions and speeds of entities, such as the positions of cars and the pedestrian.
Randomness is used in the initial speed and color of the cars, as well as in the traffic light change intervals.
There's direct keyboard control to pause the cars (with the 'P' key), accelerate the cars (with the right arrow key), and change lanes (with the left arrow key).
Overall, the code simulates a natural system, resembling aspects of traffic flow in a city. It incorporates various elements, forces, and interactions to create a dynamic simulation.
Takeaway
This coding assignment enhanced my skill of turning my creative idea into reality by coding, which I thought I could never do. This helped me understand how different parts of a system interact and how to solve problems, all while having fun, and I learned from various fields to make my simulation realistic.
Adding interactivity turned this design into an engaging game, and it was an opportunity to me to make my project visually appealing and practice troubleshooting.
Overall, even with the struggles, it was a fun way to be imaginative and improve my coding skills.
Code
Here’ s my final code, or you can check it at my OpenProcessing page!
🚨 The keyboard triggers are not working on OpenProcessing for some reason, so I also attached the zip file here as well.
int canvasWidth = 800; int canvasHeight = 400; boolean pauseCars = false; boolean accelerateCars = false; TrafficCitySimulation trafficSimulation; void setup() { size(600, 400); trafficSimulation = new TrafficCitySimulation(); } void keyPressed() { if (key == 'p' || key == 'P') { pauseCars = !pauseCars; } if (keyCode == RIGHT) { accelerateCars = true; } } void keyReleased() { if (keyCode == RIGHT) { accelerateCars = false; } } void draw() { trafficSimulation.updateAndDisplay(); } class Car { float x; float y; // Add y variable float radius = 15; // Car radius float speed; color col; boolean stopped = false; Car() { x = random(canvasWidth); y = canvasHeight / 2 + 10; // Set initial y position speed = random(1, 3); col = color(random(255), random(255), random(255)); stopped = false; } void update() { if (!pauseCars && !stopped) { if (accelerateCars) { speed = random(3, 6); // Increase speed when the right arrow key is pressed } else { speed = random(1, 3); } x += speed; if (x > canvasWidth) { x = 0; } if (x < 0) { x = canvasWidth; } if (y > canvasHeight / 2 && y < canvasHeight / 2 + 20) { float distance = dist(x, y, trafficSimulation.pedestrianPosition.x, trafficSimulation.pedestrianPosition.y); if (distance < radius + trafficSimulation.pedestrianRadius) { // Car touched the pedestrian, increment count trafficSimulation.pedestrianCount++; } } } } void display() { fill(col); noStroke(); rect(x, canvasHeight / 2 + 10, 40, 20); } void checkTrafficLight(ArrayList<TrafficLight> lights) { boolean anyRedLightInFront = false; for (TrafficLight light : lights) { if (light.isRed() && light.isCarInFront(this)) { // Adjust the stopping distance to create a safety buffer float stoppingDistance = random(20, 50); if (light.distanceToCar(this) < stoppingDistance) { anyRedLightInFront = true; break; } } } stopped = anyRedLightInFront; if (!stopped) { speed = random(1, 3); } } } class TrafficLight { float x; float y; boolean red; int changeInterval; TrafficLight(float x, float y, int changeInterval) { this.x = x; this.y = y; this.changeInterval = changeInterval; red = true; } int getChangeInterval() { return changeInterval; } void update() { // Implement traffic light behavior here } void display() { fill(100); rect(x, y, 20, 60); if (red) { fill(255, 0, 0); ellipse(x + 10, y + 20, 15, 15); fill(0); ellipse(x + 10, y + 40, 15, 15); } else { fill(0); ellipse(x + 10, y + 20, 15, 15); fill(0, 255, 0); ellipse(x + 10, y + 40, 15, 15); } } void toggleLight() { red = !red; } boolean isRed() { return red; } boolean isCarInFront(Car car) { return dist(x + 10, y + 20, car.x, canvasHeight / 2 + 10) < 50; } float distanceToCar(Car car) { return dist(x + 10, y + 20, car.x, canvasHeight / 2 + 10); } } class TrafficCitySimulation { ArrayList<Car> cars; ArrayList<TrafficLight> lights; PVector pedestrianPosition; // Position of the pedestrian float pedestrianRadius = 10; // Pedestrian radius boolean pedestrianActive; // Flag to activate the pedestrian float pedestrianSpeed; // Speed of the pedestrian int pedestrianCount; TrafficCitySimulation() { cars = new ArrayList<Car>(); lights = new ArrayList<TrafficLight>(); // Create traffic lights with different intervals lights.add(new TrafficLight(canvasWidth / 2 - 120, canvasHeight / 2, 120)); // Change every 2 seconds lights.add(new TrafficLight(canvasWidth / 2 + 120, canvasHeight / 2, 90)); // Change every 1.5 seconds // Create cars for (int i = 0; i < 10; i++) { cars.add(new Car()); } // Initialize pedestrian properties pedestrianPosition = new PVector(canvasWidth / 2, -20); // Start from the top edge pedestrianActive = true; // Activate the pedestrian pedestrianSpeed = 2; // Set pedestrian speed pedestrianCount = 0; } void updateAndDisplay() { background(155, 153, 153); fill(0); ellipse(pedestrianPosition.x, pedestrianPosition.y, 20, 20); // Update and display traffic lights for (TrafficLight light : lights) { light.update(); light.display(); } // Update and display cars for (Car car : cars) { car.update(); car.display(); car.checkTrafficLight(lights); } // Update and display pedestrian updatePedestrian(); displayPedestrian(); // Display pedestrian count fill(232, 232, 232); textSize(24); text("Pedestrian's Anxiety Level: " + pedestrianCount, 30, 60); textSize(18); text("- Press 'P' to stop the cars", 30, 320); text("- Press & hold right arrow key to spped up", 30, 340); text("- Hitting the pedestrian makes them anxious :(", 30, 360); // Check if it's time to change the traffic lights for (TrafficLight light : lights) { if (frameCount % light.getChangeInterval() == 0) { light.toggleLight(); } } } void updatePedestrian() { if (pedestrianActive) { pedestrianPosition.y += pedestrianSpeed; if (pedestrianPosition.y > canvasHeight) { // Reset the pedestrian when it goes off the canvas pedestrianPosition.y = -20; pedestrianPosition.x = canvasWidth / 2; } } } void displayPedestrian() { fill(0); // Black color noStroke(); ellipse(pedestrianPosition.x, pedestrianPosition.y, 20, 20); } }