A few weeks ago, I had been struggling with exactly what data structure to use for the plant. It felt like the NxN grid was the wrong data structure – code was hard to write, the abstraction just didn’t feel quite right, etc. I wanted something that could more properly represent each “node” of plant, and I wanted something that contained pointers to the next node(s) of the plant, and a pointer to the parent node…
And then I realized…
Clearly the right data structure was a TREE!
The plant is now represented as a 7-ary tree, where each node of the tree maps to a “plant pixel”.
Every plant pixel can be connected to another pixel in 8 directions, but it’s a 7-ary tree because one of these directions will be the parent pointer, and then 7 child pointers, many of which will be null.
nodes is an array of PlantNode references that are connected to the current node. The nodes array is ordered consistently, where the 0th index represents the TOP_LEFT space, the 1st index represents the TOP_MIDDLE space, etc.
The parentIndex indicates which of the nodes references is the parent node.
The canvas is still represented as an NxN grid, and the plant tree checks against the canvas to see where it is possible to grow in that space
Once I got the plant represented as a 7-ary tree (and once I finally got all the bugs out…), the rest of the code was pretty straightforward, though it’s not too pretty.
Things I could (but probably won’t) clean up later:
Code redundancy between the 4 orientations of strawberry
Smarten up some of the arbitrary growth heuristics (e.g. when strawberries bloom)
A fun intermediate stage
When I was playing around with plant growth algorithms, I made this happen:
Didn’t stick with this algorithm, but it’s fun to watch!
I was having trouble getting my 7-ary tree working perfectly, and honestly what I should have done was written a unit test for the PlantNode data structure itself. Had I gone that direction from the beginning, I am certain it would have saved me time. But that’s not what I did!
Instead, I mostly suffered through print-statement debugging, until I realized that the tree growth would be easier to “see” with a little bit of color.
So I wrote a debug mode that was kind of cool, where I color-coded each branch of the tree, and matched the console log statements to the color of the branch:
I guess technically this is grow-and-blooming, but the blooms will turn into strawberries tomorrow, I think!
I chose a straightforward implementation that’s slightly broken in the following ways:
Sometimes there are less than 4 growing stems:
Sometimes a stem gets stuck and doesn’t end up blossoming:
I think I want to fix issue (1) and possibly also issue (2), but since it’s kind of a tricky problem, I decided I won’t fix them right away. I’m going to focus on finishing a simple version of the game first. After I get a mostly-good-enough version of that, I’ll work on polishing up the grow behavior!
I also added some debug functions that you can call via the DevTools console:
And I looked up how to add style to your console messages! The code is not super elegant:
const consoleStyle = 'color: #008751; font-size: 12px';
console.log('%c Welcome to PLANTSIM', consoleStyle);
console.log('%c You can use the following commands to debug:', consoleStyle);
const commandStyle = 'color: #FF004D; font-size: 12px';
console.log('%c > %cworld.debugStep(n)%c: Draw n steps of the plant (must plant seed first)', consoleStyle, commandStyle, consoleStyle);
console.log('%c > %cworld.bloom()%c: Try to draw flowers at the stems', consoleStyle, commandStyle, consoleStyle);
But it’s pretty fun!
TODOs for next time
Add some decorative leaves and stumps
Add some roots
Grow the flowers into strawberries
For Friday (probably): Fiddle with cosmetic improvements, such as guiding the shape of each stem to dip then grow upward
Live demo here: Same as last time: click within the top half of the soil to plant a seed, then keep clicking the <canvas> to make the plant grow from the seed! But now with two (2!) semi-randomly growing stems.
It’s really fun to figure out the algorithm for strawberry pixel plant growth! It’s being driven from my pixel art, actually. I start drawing a random pixel strawberry plant, then I try to figure out what decisions I’m making as I’m manually making a pretty pixel picture. Then I try to figure out how to code them up!
I rewrote the guts of the Plant class today to get both stems growing:
The Plant is composed of different parts, starting with a single Stalk.
The actual game will not involve clicking a canvas to make the plant grow - you’ll need to give it water and love and attention etc. But I’m going with this for now, just to get the random generation part working.
I made this CanvasGrid object that keeps track of each “pixel” of the world, then different objects (such as Plant and Ground) update it. We’ll see if this structure works long-term.
Hehe object-oriented design for games is fun. You have code like this, where ground.addSeed returns a Plant :)
Pixel Art Notes
The art of this game is important to me (and to the game!), but I’m very new to pixel art. I found MortMort’s YouTube channel super helpful for tips on creating pixel drawings, esp this video:
I’ve already incorporated the “Avoiding doubles” tip in my plant generation, for a smoother pixel line. I think on Monday I’ll try to incorporate his “Avoid jaggies” suggestion as well.
I also gave a little presentation on Thursday on “Beginning” a project, for the beginner-themed Thursday presentations.
lol rambled too much about Tamagotchis and the “millenials and plants” phenomenon to get to much actual content, but it was fun! Giving a talk was a nice way to force me to make some progress on the game, haha, and it sparked some super fun conversations afterward.