Plant Growth Game

A calming and meditative plant-growing game!

By: Asma Ansari (ara89), Fiona Rae (fmr35), Emmy Yancey (mdy9)

Introduction

Nature's mental health benefits inspired us to develop a video game where the player can grow their own plant. We wanted to replicate the peaceful, and even meditative, experience of interacting with nature. This led us to consider what factors impact a plant's growth, such as sunlight, water, and fertilizer. Additionally, if a plant is under the care of a person, that person wields a significant influence on the plant's health.

In our game, we gradually animate the growth of a plant over time as the player adjusts the sun's position and intensity and provides rain and fertilizer at desired intervals to the plant. The end result is a beautiful cherry blossom tree reminiscent of real trees on Cornell University's campus. Ultimately, the game encourages the player to be focused through fostering the plant while providing a visually-appealing and calming "environment" for the player to take a break from studying or work.

High-Level Design

Sources

Since our project involves simulating "organic" growth patterns, we researched fractal generation. The class repository includes some fractal-based projects, such as the Barnsley Fern, which were relevant to our project's final animation. Additionally, Hung Wen-Chen, a Computer Science student at Cornell University, developed a plant generator using L-Systems for computer graphics purposes. This provided additional direction for how to implement a system that can progressively "grow" a plant and have the user's input actually impact the plant's growth.

To further enhance our game interface, we attempted to incorporate a real GameCube controller for the user to interact with the plant. Thus, we found a driver that maps the GameCube controller's buttons and toggles to a USB driver. We ultimately chose to simplify our user interface, but this was a significant part of our initial design.

All of the resources mentioned in this section as cited appropriately in the Appendix under "References". These include any and all fractal generation code we took inspiration from as well as research papers with pseudocode that allowed us to develop our own design.

Structure

We structured our project such that we utilized minimal hardware components and based our software primarily on the course's demo code. The Pico microcontroller, VGA display, and several buttons and potentiometers for our user interface and running our program. We based our code in the VGA Animation demo code as well as pseudocode describing generating a plant in Python using L-System. This structure not only makes our project more accessible and reproducible, but it also challenges us to cleverly make use of limited resources (memory, ADC inputs/outputs, etc.).

In addition to programming the Pico in C, we chose to use Python to validate the logic of both the L-System's animation and alternative methods. This was especially crucial for parallel programming because we still had to implement our user interface before we could validate our animation on the VGA display. Therefore, we used Turtle Graphics in Python to illustrate our animation code on our individual computers before rewriting the code in C and combining it with the VGA Animation code.

Node-based tree generation organized in a generic tree structure

Figure 1. Node-based tree generation organized in a generic tree structure.

As mentioned earlier, nature contains countless examples of fractals, such as snowflakes, rivers, and even plants! Therefore, we initially used an L-System, a mathematical system that can generate fractals, to model our tree's growth in the video game. However, this system was too deterministic, so we switched to a generic tree structure where each branch or leaf is represented by a node.

This node-based design allowed us greater control over how a node is generated. The player can adjust the water level, fertilizer level, sun's position, sun's intensity, and plant's natural tilt which affects the plant's size, growth rate, and growth direction. Thus, a node can be generated or updated based on these factors in real-time whereas the L-System only allows a "node" to be generated based on a discrete command.

Design

Hardware

The hardware consists of only the VGA display and the 5 input channels determined by the player. Two of these inputs are pull-down resistor GPIO ports that are set with a button. These buttons toggle whether the game enters the fertilizing and watering states. The other three pins correspond to the pico's 3 ADC channels and determine the values of Sun position, sun intensity, and plant angle. These channels linearly map the range of 0V - 3.3V to an integer range of [0, 4095]. Notably, this range is larger than the VGA's x-array zsize of 640. As a result, the high resolution of these channels allows for manipulation of the sun object at the VGA pixel level, which yields a smooth animation upon adjusting the potentiometers.

Hardware diagram showing connections to the Raspberry Pi Pico

Figure 2. Hardware diagram showing connections between the Raspberry Pi Pico, buttons, potentiometers, and VGA display.

Software

VGA Display

The VGA Animation demo code from the course's repository guided our video game's development. Our objective was to refactor this demo code such that we combine concepts from our previous labs and build upon them with a unique implementation. On the VGA display, we wanted to display a histogram, text, and dynamic objects, similar to the Digital Galton Board lab. However, compared to that lab, ours required less physics and more tuning once the mathematical basis was set up, similar to the PID Controller lab.

Before attempting to implement the L-System code into C, we used Python Turtle Graphics to iterate on our animation design. As mentioned in "High-Level Design", we did animate a tree using L-System, but the output was too deterministic. Since the L-System design was recursive, that gave us the idea to switch over to a generic tree structure which is also traversed recursively.

Three iterations of L-System animation in Python

Figure 3. Three iterations of the L-System animation in Python.

Three iterations of node-based animation in Python

Figure 4. Three iterations of node-based animation in Python.

A key difference between the two animation styles is the randomness of the designs. The L-System design resulted in the first "branch" tilting to the right with some level of randomness in direction after that. The node-based animation allowed us to generate more variance in the direction of growth, and we also adjusted the "thickness" of each branch throughout the animation based on the depth of recursion (lower depths means newer branches which are thinner).

We refactored the node-based Python code into C which allowed us to statically generate a tree on the VGA display when the program started running. Initially, the program would take a random number to generate the tree as per the Python code's specification so we updated this to where the tree's growth is not just random. We incorporated the parameters into the growth and direction calculations for each branch or leaf.

The other major animation task was the rain and fertilizer falling. We wanted these to as closely appear as rain or fertilizer falling as possible. Therefore, we incorporated a bit of real world physics. Once rain has reached nearly the ground, it has also roughly reached temrinal veloctiy. Therefore the rain falls at a constant rate. However, the fertilizer should not be at terminal velocity if it is just dropped. Therefore, each fertilizer piece starts with a random velocity, and they all accelerate with gravity. This led to fertilizer and rain which looked realistic.

Parameter Tuning

Due to the limited number of ADC channels that the Pico had, we were unable to implement the wind parameters into our design. We needed to use all 3 of these channels and a few digital parameters to fully implement a properly animated plant. The parameters we included were plant tilt, water, fertilizer, and sunlight direction, as well as position. The water and fertilizer are each controlled by digital buttons connected to pull-down resistors. The remaining parameters each correspond to the ADC channels on the pico.

Thus, the end result is a tree starting out with only one stem that grows until it generates a variable number of branches. From there, the branches grow until it either generates more branches or generates a leaf which automatically terminates growth. Adding fertilizer speeds up the growth of the branches while adding water increases the length of the branches but not leaves. Therefore, adding water and fertilizer at key intervals can change the shape of the tree.

Furthermore, the sun's position and intensity impact how strongly the plant grows towards the sun where the sun's position determines growth direction while intensity is actual probability that the plant will grow towards that direction. The plant's tilt also influences the plant's direction of growth, so the impact of the sun as well as the plant's set tilt oppose each other depending on the sun's intensity.

The Sun position parameter is shown via its visual location on the VGA display. The tilt has no graphic representation. The rest of the parameters are represented via a histogram. Each parameter has a value on a scale of 0-100. The fertilizer and water parameters increase when their corresponding buttons are pressed. The state of the given parameter changes to allow to the value to increase over time. When the button is released, the value of the given parameter will slowly decay until zero. Note that fertilizer increases at a faster rate than water when its button is pressed. The sun intensity is also represented as a bar in the histogram. This value is not a direct mapping of the sun intensity ADC channel, but the evolution of the bar value is influenced by the current integer value of the channel. There is a band in the middle of the ADC channel values for which the intensity bar does not change. Above this, the value increases at a constant rate, and below this, it decreases at the same rate. Note that the decay rate of all values is the same.

Memory

Storing the VGA display's pixel data takes up more than half of the Pico's memory on its own, so this was another hardware limitation we faced. Recursive calls take up significant amounts of memory in the stack, and with extremely limited memory, dynamic memory allocation usually results in memory fragmentation. Thus, we had to incorporate a memory pool design in which we generate all of the nodes at the start of the program and assign those nodes to specific parts of our animated plant.

We initialized two arrays, one holding all of the nodes and one which kept track of which nodes were being utilized. After implementing this into our animation code, we experimented with different array sizes for the number of allocated nodes. We chose to keep the number of nodes under 2000 because the actual tree animation still looked reminiscent of a real cherry blossom tree and it preserved some memory for other recursive processes.

Results

Our primary objective was to illustrate a realistic and aesthetically pleasing plant. We wanted the game's end result to be meditative without being boring. We feel that we achieved this through our carefully thought out gameplay mechanics and animation methodology.

Each run of the game produces a different tree due to both the user's input and the small element of randomness while still resulting in a realistic, beautiful tree. As described earlier, we simulated how a real-life tree would grow where the largest branch would be the stem followed by each successive branch. Finally, each tree reaches the end of its growth once all branches reach a leaf which is colored pink to mimic the cherry blossom tree, as can be seen below.

Two cherry blossom trees that are comparable to the game's end result

Figure 5. Two cherry blossom trees that are comparable to the game's end result.

Tree with Left Tree Tilt, Minimum Sun Intensity, and No Water

Figure 6. Tree with Left Tree Tilt, Minimum Sun Intensity, and No Water.

Next, we slowed down the tree's growth significantly to ensure that users can set the pace of gameplay. This also allowed the user to play around with each of the buttons and potentiometers to change the tree's final look. The user could also continuously add fertilizer to speed up the tree's growth rate, but otherwise, the user can allow the tree to grow on its own for the end result illustrated in Figure 6. As illustrated above, the lack of water resulted in very small tree branches and a "fuller" looking tree with a slight left tilt. The tilt in this case is not due to the sun's position but rather the plant tilt parameter being set to the left.

Tree with Left Tree Tilt, Maximum Sun Intensity to the Right, and No Water

Figure 7. Tree with Left Tree Tilt, Maximum Sun Intensity to the Right, and No Water.

When sun intensity was at its maximum, the tree tilt had no effect on the growth of the tree and it grew entirely towards the sun as seen in Figure 7. Despite the tree tilt being to the left, the tree is growing to the right due to the very high sun intensity. Still, without any water, the tree branches are quite small.

Tree with Left Tree Tilt, Maximum Sun Intensity to the Right, and Maximum Water

Figure 8. Tree with Left Tree Tilt, Maximum Sun Intensity to the Right, and Maximum Water.

Finally, adding the maximum amount of water significantly impacted the final tree's look. We maintained the same conditions as Figure 7, but we continuously added more water until the water levels remained consistently high until the tree finished growing. Comparing the previous two trees to this third one indicates that water and sunlight drastically impact the final look of the tree. Overall, we achieved our goal of designing a meditative, interactive, and aesthetically pleasing video game.

Execution

Since we wanted our game to have a meditative effect, we ensured that our game did not progress too quickly. Initially, we verified our tree generation logic by statically animating the full tree once. We iterated on this by illustrating the branches growing longer and randomly generating a leaf to end growth on that particular branch. Our end result mimicked the growth of a real cherry blossom tree as it begins to bloom in early Spring.

To compensate for this, we also wanted any actions by the user to have an effect on the game. Therefore, changes made by the user needed to have an immediate effect on the game. This meant that when a button was pushed or a potentiometer was turned, this should be taken into the game in a way that the human brain perceives it to be instantly. We did not have quantitative timing constraints, just the qualitative timing constraint that the player should perceive effects as immediate. This was met easily, when the rain or fertilizer buttons were pushed, each respectively immediately began falling, and the histogram began increasing. When the sun dials were changed, similarly, the sun on the screen would move and the histogram would change as necessary. Additionally, each of these factors had an effect on the tree as it slowly grew. These decisions make the game interesting while still being meditative and slow.

The only dial that did not have a perceivable immediate effect was the plant tilt potentiometer. Because this only affected parameters in the shape and direction of the tree, it was not something that had an immediate visible impact. However, over time, the user could see this change. This still met our requirements, however, as we intended for this to have less visibility than the other changes. An effect of this decision is that it, possibly, makes this parameter a bit less interesting to the user as it is not easy to perceive it as having any effect on the tree unless the user runs the game several times with several different settings for this.

Accuracy

We had very little quantitative expectations for our game, as our focus was on the aesthetics. One note on accuracy was that the sun size and position often flickered more than originally intended. This was, primarily, due to the noise on the potentiometer. While we attempted to fix this by checking that the change in values from the potentiometer exceeded a minimum value, there was still some flicker. There was a limit to the amount we could set, because we still wanted the sun to move across the sky and change size smoothly. We accepted this slight flicker on occasion over jumping positions.

Safety

We have no obvious safety concerns. The project uses low-voltage components (5V or less) that pose minimal risk to users. Standard precautions for handling electronic components apply.

Usability

The user interface consists of three buttons and three potentiometers which is relatively straightforward. Our controls are rather simple and most have visible and immediate effects on screen. While none of them are labeled, they are easy to figure out for the most part. Pressing the fertilizer button causes fertilizer to immediately fall, same with the water button. The sun intensity and sun position potentiometers both have immediate effects on the sun. The plant tilt is the least obvious of any of the controls, as the effect is truly only visible upon completion of the plant. In order to further improve usability, it would be beneficial to label these going forward.

Overall, our game is fairly usable in terms of its current setup. Equally, it is very accessible to most people as it comprises primarily two buttons, three potentiometers, and a VGA screen. This means that many people could download this code and fairly easily acquire these parts (for relatively cheap for most of them) and play our game. No soldering required.

Conclusion

Our project changed fairly drastically over the course of our project. This was due to many issues including resource constraints, stylistic choices, and lack of initial knowledge about the proposed ideas. Some ideas, despite not being included in the initial specs, we brainstormed and worked towards during the process, before realizing this would ultimately not work. The main changes throughout the process were the tree design, the effects of the parameters, and the physical controller.

Despite the drastic changes in our fractal generation, it allowed us to brainstorm a unique implementation of a fractal design. Once we realized that fractal generation could be represented recursively, we used our prior knowledge of data structures and mathematical principles to alter our animation as per our specifications. We are happy with this resulting change as it creates a tree which is aesthetically pleasing and completely different from run to run of the program.

Parameter Expected Specification Actual Specification
Sunlight Intensity (1) Increase feature frequency
(2) Contribute to net growth direction
Contribute to net growth direction
Sunlight Position (1) Contribute to net growth direction Contribute to net growth direction
Wind Direction (1) Decrease feature frequency
(2) Contribute to net growth direction
NOT IMPLEMENTED
Wind Intensity (1) Contribute to net growth direction NOT IMPLEMENTED
Plant Tilt (1) Contribute to net growth direction Contribute to net growth direction
Fertilizer (1) Increase feature frequency
(2) Impact feature morphology
Growth Rate
Water (1) Increase feature frequency
(2) Impact feature morphology
(3) Determine plant stiffness
Feature Morphology

Table 1. Changes of parameters and effects between initial plan and actualized results.

Many of our parameters were implemented quite differently than initially expected. The full list can be concisely viewed in Table 1 above. One major change was the sunlight, water, and fertilizer affecting feature frequency. Since our specs were drafted before we began playing around with the tree system and appearance, this initially seemed like it would be decently easy and interesting. When a plant is healthy (with enough sunlight, water, and nutrients), it generally grows large and bushier. This was the intuition behind the feature frequency aspect. However, once we started attempting to create the tree, the system we were using changed and the node system, due to its recursive nature, did not lend itself to easily implementing this.

Fertilizer, instead of affecting the appearance of the features, affects the growth rate of the features. When we began drawing the tree, we realized that our initial method of having layers of tree appear all at once was both jarring (interrupting the calming atmosphere) and far too quick. This meant that the game was over too quickly with little effect from the user's choices. Therefore, we moved towards the size of the tree increasing at a set rate. From here it seemed most reasonable to have the fertilizer affect the rate of growth.

The water was initially going to affect the stiffness of the plant. Once again, this was changed due to how we designed the tree. The tree is composed of straight lines. This meant that stiffness being affected by the water required completely changing the design of the tree. We therefore moved away from this idea, and focused on changing the shape of the plant in other ways. Therefore, as the plant is growing, it now affects the maximum height of each individual branch. This still gives the user the ability to change the resulting tree through the amount of water and allows more variety in each of the branches and overall trees.

The plant's angular orientation went through many iterations. Our initial specs simply described it as a component of the plant's growth direction. However, we thought it would be interesting if the tilt parameter rotated the plant about its stem. The resulting tree would move to its new location and then new branches of the tree would grow towards the new relative growth direction ie. the plant still grows towards the sun even when the whole tree is moved. To achieve this, we would need to recursively parse out the tree and rotate the coordinates of each node about the stem's base. To this end, we created a rotation matrix with an angle dependent on the change in the plant tilt parameter. This calculated the new coordinates and angle of every single branch on the whole tree. Unfortunately, despite the functions working properly in small-batch testing, this method took up too much memory. Half of our RAM was already dedicated to the VGA protocol, so could not find a way to fix this problem. The design choice was dropped and replaced with the initial idea for the plant's growth direction.

Plant tilt now has an identical effect to sun, but without a corresponding graphic. What makes it interesting is that it is diametrically opposed to the directional component of the sun based on the sun intensity parameter. Basically, there is an angular component corresponding to both the sun position and the tilt parameter, and the resulting direction from these two parameters is the weighted sum of radian angles. When sun intensity is high, the sun direction is weighted more heavily. Otherwise, the plant tilt is weighted more heavily. This can be seen in the limit tests where plants will grow mostly toward the sun when intensity is maximized. And off to another direction determined by tilt when the sun intensity is minimized.

Wind was dropped primarily for the lack of ADC channels on the Pico. This would require two additional channels and, given we already used three, this would not be possible. Therefore we decided to not to waste time on this and dropped the idea entirely.

Finally, our physical controller was another part to changed drastically. We originally considered using a game controller to control each of the parameters. This, however, proved to be more expensive than initially expected so we dropped the idea. The issue we had was that the slider potentiometers were rated at 110kΩ instead of the needed 10kΩ. We decided that building the passive circuit was not worth the time when there were perfectly functional 10kΩ potentiometers available from the last lab.

Next time, many of our efforts will be dedicated to improving the physical controller. The main issue with the buttons was their size. They were so small that holding them down could be painful for the user. In the future, we would exchange this for a different button. The potentiometers were somewhat noisy due to weaker connections on the breadboard. This noise resulted in the sun sometimes changing position or shrinking/growing randomly. To fix this, in the future we would like to solder these and the buttons as well, to a board to have more secure connections and less noise. Additionally, we would like to make this more controller-like with a custom setup of the buttons which includes labels. This would make it a more appealing user interface and improve the usability.

Our project did not include any IP nor did we use any trademarked or patented code. We did not have to sign any non-disclosure agreements or reverse engineer any designs, but the design we did create is not eligible for patenting. Since our objective was primarily aesthetic, we do have intellectual property due to the creative nature of our project, but this project is meant to be accessible which places our project under Creative Commons.

Overall, we were quite happy with the way our program turned out. While it was not precisely what we originally planned, the setbacks and changes did not affect the overall turnout. It is visibly simple, easy to use, and aesthetically pleasing. This makes the game fun to play, meeting our meditative purpose. While there are a few places it could be improved, we are proud of our game and our work. We also had a great time along the way with making design decisions and building an entire system from the ground up.

Appendix

A. Permissions

The group approves this report for inclusion on the course website.

The group approves the video for inclusion on the YouTube channel.

B. References

  1. Wen-Chen, Hung. "L-System Plant Geometry Generator." ECE Cornell University, January 1995, https://people.ece.cornell.edu/land/OldStudentProjects/cs490-94to95/hwchen/. Accessed 11 April 2025.
  2. Torvalds, Linus. "Nintendo GameCube, Wii and Wii U RTC driver." GitHub, 2022, https://github.com/torvalds/linux/blob/master/drivers/rtc/rtc-gamecube.c. Accessed 11 April 2025.
  3. "Coding L-Systems." The University of Texas Austin, 2004, https://www.cs.utexas.edu/~bajaj/graphics25/cs354/lect9a.pdf. Accessed 11 April 2025.
  4. Van Adams, Hunter. "Barnsley Fern." GitHub, 2024, https://github.com/vha3/Hunter-Adams-RP2040-Demos/tree/master/VGA_Graphics/Barnsley_Fern. Accessed 11 April 2025.

C. Task Delegation

Asma Ansari

Fiona Rae

Michael Yancey

D. Code