ON THE SUBWAY
Brief intro:
The initial idea for my project was to create a train, primarily showcasing the scenery outside through the train windows. It has many stops, with numerous passengers boarding. At the outset, I wanted to make it the train of life, where the passengers represent the positive qualities we embrace at each stage of our lives.
But then I find I cannot bring all the positive qualities onto the canvas within less than one week. And I cannot draw that many sceneries. So, I only bring two of them. They might look a bit disjointed right now. If I had more time, I would try to unify their styles. At the meantime, Prof.Moon also told me that I can focus on the scenery outside and what can be triggered through the interaction. So, I finally finished with this sketch.
Just as a flame lights up the darkness, confidence illuminates a person’s abilities and talents, allowing them to shine brightly. It helps to dispel the shadows of doubt and insecurity, highlighting strengths and capabilities.
For self-care, I depicted it as a creature resembling a blanket. This design mainly stems from my own feelings. Enveloped in a warm blanket. A warm blanket offers a sense of comfort and security, much like self-care practices that provide a mental and emotional refuge from the stresses of daily life. Just as a blanket wraps us in warmth, self-care envelops us in practices that promote well-being and peace.
The most tormenting part of Project B for me is coming up with ideas. When presenting ideas on Tuesday, I still hadn’t decided what to do. I had many initial concerns; I felt that projecting had to consider the issue of shadow obstruction, such as when a person stands in front, it inevitably blocks part of the projected light. I also had a misconception that a project must have interaction… All these anxieties kept me awake at night and left me feeling completely lost.
When I met with Prof. Moon to discuss, he initially affirmed my first presentation’s concept, which surprised me greatly because I thought it would be full of flaws due to being rushed. Moon’s affirmation gave me a certain level of confidence, and I started trying to calm down.
After discarding the first two ideas in various meetings with Moon, I focused on creating a sense of forward movement or displacement for the audience through changes in the environment (see inspiration1). I wanted to create a subway where the environment outside the window could be displayed using the skills learned this semester. I would then give them a certain speed to move in the opposite direction, to give the sense that the entire subway was moving forward.
I started by giving a simple rightward displacement to the positions of the vehicles in the flowing field, simulating organisms moving forward at the same pace as the subway but not as fast. Next, to depict the rapid movement of the train, I used noise to draw distant mountains and gave them a greater rightward displacement (simply put, I increased the frequency of the noise). To simulate the feeling of scenery passing by the train window, I surrounded the canvas with four black rectangles.
So, what we have are two objects moving to the left relative to the ground (the subway and the creature) and one object (the noise mountain) staying still relative to the ground. However, our reference frame is set inside the subway compartment, so for the actual audience, what moves relative to them are the creature and the noise mountain, while the subway compartment remains stationary.
Then I began to think about what the creature should look like. I am very grateful for the question Moon asked during my presentation, “Why not make them realistic this time, but instead assemble them using simple geometric shapes?” I hope I can provide a clearer answer in this blog post.
Because at that time I was exploring my higher concept – the journey of life (although it wasn’t portrayed as satisfactorily later on), for me, this simple term concludes people’s entire lives. Consequently, the passengers on this journey – representing the good qualities people possess at different stages – also needed to have a certain level of generality, like one thing that could concludes others. This generality is specifically reflected in what kind of things can contribute to these qualities at each stage.
Obviously, I couldn’t list all the real-life events that contribute to these qualities, but I could use sharp shapes to represent setbacks, circles to represent fulfillment, straight lines to represent things that require you to invest time and effort to persevere, and so on… By assembling these shapes representing events together, I could get a rough appearance of this quality. Then, by linking each part with certain algorithms, I could ensure they have their own trajectories while still moving as a whole.
I deeply realize that I didn’t represent the concept above very well. I acknowledge this as an area for improvement. Within the limited time frame, I appeared restless and unsettled, failing to calmly contemplate the structure each creature should have.
The jellyfish-like creature was actually something I stumbled upon. Because I applied a sinusoidal displacement to its position, it’s like applying a cyclic force to an object. Starting with zero initial velocity (vel = createVector(0, 0)), it undergoes periodic motion. In my setup, this jellyfish-like creature essentially moves back and forth around the origin point I assigned, and later translating it to the position of a moving object makes it appear as if they’re naturally swimming in one direction. (Hope I explained clearly here.)
To ensure their swimming in water looked more natural, I decided to give them tails. Haha, here comes my favorite part, the Spring force! There’s a reason why I love the Spring force, let me explain! Compared to simply using position, velocity, and acceleration to simulate an object’s motion (such as coding a bouncing ball, which used to confuse me a lot — why under some conditions it maintains its height, and why under others it gradually “loses its energy”), the behaviors triggered by the Spring force seem more natural and closer to real-world physics.
To create a bunch of creatures, I wrote another class to draw a complete one, allowing me to mass-produce my creatures. After drawing multiple of them, I updated their positions (translated them) using the flowing field’s vehicles.
After finishing each creature, I started thinking about how to set up the scene and what should be triggered. “It could be something fun or very eye-catching,” as Moon put it.
I admit it! I did consider going in that direction at the time, but because I couldn’t think of a specific creature or a fun-looking action in the short time, I temporarily abandoned the idea. But! Let’s save it here for now! Who knows, maybe we can pick it up later!
In the sketch test3, I made the creatures a bit larger. Fortunately, I drew the creatures at the origin point, so translating, rotating, and scaling became much easier. Note that at this point, the creatures started moving forward relative to the subway car. I vaguely remember that I did this because, well, if they’re that big, they should swim faster than the subway, right? 😅
(Intense feeling of oppression!)
Later in a meeting with Moon, I learned that the canvas size is ideally 16:9. In test4, I urgently adjusted the size, leaving a blank area for the subway car, where the creatures would also swim to and be visible. My hope at the time was that this area could be projected onto the ground, creating a sense of space between two vertical planes. This idea was inspired by my second inspiration, “Augmented Shadow: Chasing Stars in Shadow.”
Most importantly, in test4, I arranged the sequence of the subway moving forward, stopping, opening doors, and closing doors in chronological order. I also made sure that the scenery outside the window would correspond to stopping or moving to simulate a more realistic environment. Additionally, I used the mouse’s position to check the effect of having two scenes outside the subway car, making it easier for me to arrange the appearance of different scenes based on time or trigger counts later on.
For the first effect triggered, I chose to have a larger creature come out and swim around. The size of the creature is determined by its distance from the bottom. This was mainly to show the perspective of nearer objects appearing larger and further objects smaller, further emphasizing the three-dimensional space. I placed it above the subway car layer to make it seem closer to the audience. To easily determine the rotation angle of the creature, I ultimately used vectors to determine its movement trajectory, then translated the creature to the corresponding position and rotated it accordingly using heading().
In the process of developing test5, I encountered my first problem: since I made creature a class, in my main sketch, I directly called the creature class, not the ball and spring classes where the graphics were drawn and colors assigned. So, how could I differentiate the background creatures from the triggered ones? After all, I couldn’t change the colors of the ball and spring classes when calling the creature class.
Hopefully, you’re not too confused by now. Actually, the solution was pretty simple, though I only realized it after Moon pointed it out to me. 😵 Oh my, my question was kind of silly.
The solution was to not set the stroke and shape colors in the ball and spring classes initially. Then, when calling them in the creature class, I could simply use this.r, this.g, and this.b to assign the colors.
To make the triggered creature more distinct, I filled the triangle part. Meanwhile, to maintain the noFill() effect for background creatures, I added a variable this.t and set this.t to 0 for background creatures.
Besides, I add another trigger stuff for the first scene. I let the background to change color. I first try it here.
sample code for change of “background” color
looking at the reference page, I find that I have to have a amt for lerpColor(). However, I want to fill all the canvas with the gradient color, instead of getting one color between two with only on amt value. So, I make amt a variable and let it increase to get different yPos. Then I use line with different yPos to fill all the canvas to mimic the sense of gradient color.
Meanwhile, assigning different moving speeds to the stars made the canvas even more three-dimensional.
Most of test5 and test6 were developed during Monday (one day before the presentaion1), and at that time, I was really, really rushed, and my mind was really, really chaotic.
For test6, I struggled with the transition part and also deciding when to have another background. At first, I wanted to do it based on the trigger count. To avoid repetitive counting, I developed a small sample.
Here I can explain why I used mouse position as the trigger condition. I believed that mouse position, like pose position, is being constantly detected. If the animation triggered by it requires some time to complete, you must ensure that you can’t trigger it again within that time, or else it might restart before finishing. To prevent a situation where the mouse position continuously satisfies the trigger condition and the trigger count keeps increasing (because normally, the mouse entering the detection area should only count as one trigger), I added a condition called wasDetected. This condition turns true only after the mouse leaves, and it turns false again when the mouse enters, preventing the trigger count from increasing continuously.
But I found that this approach required me to also consider the time it takes for passengers to board the subway after the doors open. After multiple unsuccessful attempts, I got frustrated and simply changed the transition condition to the number of stations reached.
Finally, all we had left was to get our passengers on board:
They are mainly made by spring force.
To make them undergo a series of displacements, I also racked my brains:
At first, because I had the idea of projecting part of it onto the ground, I also wanted to create footprints for them on the ground to echo their movements. But due to time constraints, I temporarily gave up on that. Save it for later.
At this point, my code was almost done. I made a final attempt to replace the triangles with slimes. However, the visual effect wasn’t very satisfactory. So, I back to the triangles.
About Presentation on Thursday:
A special thanks for Thursday’s presentation, which gave us the opportunity to communicate with Professor, fellow students, and classmates.
Moon’s questions have been answered earlier in the text.
When asked where this work should be displayed according to my ideas, I was truly stumped. I’ve never seriously thought about this question for my coding projects. Professor Inmi told me that before starting a project, it’s important to think about who the targeted audience is. Yes, this makes it easier to determine the artistic style and presentation content. Prof.Inmi also voiced what I was feeling – that this concept wasn’t fully realized, but it doesn’t mean the project can’t be showcased independently. Absolutely! I couldn’t agree more! Additionally, Inmi appreciated the layering I did but suggested that the subway car seemed too static, making it less realistic.
Carrot mentioned it would be nice if the background could move in response to the subway’s motion. Later, I realized that although my noise mountain, green wave, and butterfly all moved accordingly, the most obvious jellyfish-like creature indeed didn’t move with the subway!
Many thanks to everyone for their great suggestions; this work still has a lot of room for improvement!
Before my presentation, I was actually very dissatisfied with my work, feeling quite upset. But hearing everyone’s encouraging words made me feel much better, and I’m now brave enough to face the aspects I’m not satisfied with. My mom said it’s like my child, a bit clumsy, but with effort, I can make improvements. So as this “parent,” I’ll spend more time improving this “child.”
For IMA show:
Due to the venue setup and some oversights on my part, “On the Subway” wasn’t showcased as ideally as I hoped. We decided to abandon the idea of projecting part of it onto the ground and, to simplify the code, I removed some interactions. And because we add moveNet, the code runs slower than before, so for some, I adjust their frequency manually. However, I’m still very happy that people were willing to come and listen to my ideas, and were willing to stop and take a look.
I love Nature of Code!!!