Complicated Code and Creative Blocks
The past several weeks have been a struggle, productivity-wise.
First, I spent quite a lot of time working on proto-slots. That may seem productive, but the amount of effort I put into polishing and documenting it was way out of proportion to the benefit I would get from it. I think I did a pretty good job on that project, but I also recognize now that I was using it as a way to avoid actually working on Ambienome.
It was about three weeks ago that I realized what was happening, so I tried to force myself to focus on Ambienome. That didn't really work, and I just ended up with a serious creative block. I spent about two weeks making almost no progress. My code had been accruing unnecessary complexity, mostly due to exploring a lot of unfamiliar territory (Lisp, and OpenGL), which made it difficult to work on when my motivation was not very high. Each time I would try to focus on Ambienome, I'd run into some obstacle, grimace, and reflexively go find some way to distract myself. (In hindsight, it was probably not wise to start a challenging new project at the beginning of winter, since my energy levels and motivation always dip during the winter.)
(Those two weeks weren't a complete loss, though; I did beat a lot of games! :P If you're curious: Dungeons of Dredmor, The Binding of Isaac, Limbo, Glowfish, Blocks That Matter, and a couple others that I can't recall at the moment.)
I finally broke through the creative block about a week ago, by unplugging the internet, shutting out all distractions, and just tackling my code head-on. I spent 3 days just simplifying and cleaning up my code to make further development feasible. All told, I managed to eliminate 9 classes:
job
, which acted as a central coordinating structure for the OpenGL rendering pipeline. The important functionality was transformed into methods of theprogram
class, which is slightly lower-level coordinating structure for the rendering pipeline. The rest of the code was scrapped.uniform
andattribute
, which represented OpenGL shader uniforms and attributes. These classes were also reduced into methods ofprogram
, and the unnecessary code scrapped.rectangle
,triangle
, andcircle
, which represented instances of those geometric shapes. They were reduced into arender-shape
generic function, with a method implemented for each shape based on a keyword. For example, to render a circle you'd do(render-shape :circle ...)
. Lisp's method dispatching system is pretty handy sometimes!shape
, which was the parent class of the three shapes mentioned above. Aside from the rendering code, which (as I said) became methods, this class also stored the shape's transformation (position, rotation, scale), and other properties such as color. I moved this functionality to thepart
class, which represents a creature body part.group
, which held multiple shapes that would move together, just like SVG'sg
element. Instead, I decided that it's simpler and more intuitive to allow body parts to be parented to other parts. To handle the case of an invisible pivot point, the parent shape can be made invisible, in which case it's functionally equivalent to a group.prop
, which represented a property of a shape, such as its color. The idea behind this class was that it would contain not only the data, but also some metadata (its type, human-readable name, etc.) that could be used later to generate an appropriate user interface to edit the property. For example, the color property would have some metadata indicating that the data was a color, so it should be edited using a color swatch widget. I decided to just store the data and metadata in hash tables instead.
My code is now much leaner and more function-oriented than before, and much more approachable and easier to work with. I actually eliminated (temporarily, I think) the need for my proto-slots library — which, after all the work I put into it, is either really funny or really frustrating.
Yesterday and today, I've been making progress (not a great deal, but enough) on new code, specifically the ability to serialize and deserialize creatures and their body parts, so that they can be saved and loaded from file. I'm nearly done with this, but I'm not sure yet what I'll tackle next.
Perhaps I'll try to plot out a more concrete roadmap, start to define and narrow the scope of the game, and lay out some specific tasks and goals. I'm sure my unorganized, exploratory approach is a significant cause of my slow progress. It would be good to have some concrete milestones to chase after, and maybe even some deadlines to push myself forward. What a radical notion!