1401.003: Review of Game-Making Week Milestone 1

Project 1401 Milestone 1 Happy Monday! Since I last posted, I’ve been working on my video game project, Project 1401. Although I’ve worked on a few commercial games, my goal with 1401 is to make my own video game. It’s one of many creative challenges that I’ve never fulfilled. I gave myself 10 years to get them done.

Anyway, spending a week on 1401 also gave me a chance to test my willpower against the demons Guaranteed Uncertainty and Guaranteed Tedium, two of the resistances that sap my enthusiasm before I even start working. A few insights bubbled to the top of my awareness in the course of battle:

  • Even thinking about how long something will take is a huge distraction, because it takes one’s focus away from immediate problem solving to the unproductive realm of an unreachable, unknowable, fictional future. It’s even worse if the current task itself is uncertain in some aspect. While there is a place for time management, worrying about it when you are trying to learn how to do something is really counterproductive. I have to remind myself that 1401 is a learning project in many respects, as much as I want it to be DONE NOW so I can reap the feeling of having finished it. Such thinking is the downside of being a dreamer I suppose; dreaming of rosy futures is just where my mind goes. Sticking in the moment and not letting distractions or negative feelings derail me is a huge challenge. I’m trying to cultivate a zen-like Not thinking of time and effort mentality, which seems to be helping.
  • Thinking about how much there is to do is another demotivation, creating significant threshold to starting every task.
  • A lot of the systems I’m making for 1401 are conceptually simple (isn’t everything?) but complex in the details. Because there are so many programming tasks involved, it can be quite daunting because there are a lot of details to take care of before the “good stuff” happens. This is demoralizing. To bypass this, I’ve bene using the trick of fixing something really small after just looking at the system as it exists; once I have the code up and in my face, my curiosity starts to take over and I start working as my focus is productively applied to problem solving, not assessing time, effort, and difficulty. There’s nowhere to go but THROUGH, you know?

The remainder of this post delves into more detail about the time expended over the past week. This is both a review of technical process (but not too technical) and the personal challenges I faced. Read on, if you dare!

Recap of Milestone 1 Goals

The milestone was to have a spaceship moving on a starfield, and I got very close, but didn’t achieve it. I did get significant systems defined and reorganized:

  • Renderer – This is a code module that manages the drawing of graphics objects in the browser in a systematic way, according to my notion of what that means in the context of my game framework. The heavy lifting is done by a 3D graphics library called ThreeJS (look at these pretty examples).
  • VisualFactory – In the 1401 system design, “Visuals” are the visual representations of an underlying bit of data. The VisualFactory module makes graphical sprites, 3D objects like spheres, planes, and complex meshes. Like Renderer, it uses ThreeJS to do the heavy lifting.
  • PieceFactory – Everything you see in a video game has an underlying bit of data; in 1401, these bits of data are called Pieces. Pieces can be placed in the world, be collected into groups to be managed all at once, and work independently when left on their own. Pieces can have their own Visuals.
  • Master – A video game typically has to load data, initialize, then run through a set of calculations for every frame of animation. It’s important to establish a set of conventions for how this is all coordinated, otherwise chaos will descend and make it very difficult to get anything done. The 1401 Master does all this stuff, and it’s a pretty important bit of code. I spent quite a bit of time reorganizing it to make adding modules and objects easier.

As a high-level example of how these modules work, one can create a piece in the world by executing the following bits of code:

// INITIALIZE RENDERERING SYSTEM ///////////////////////////////////
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

// initialize renderer and default world cameras
RENDERER.Initialize ({
    attachTo: '#container',    // WebGL attaches to this
    renderWidth: 1024,         // width of render context
    renderHeight: 768,         // height of render context
    worldUnits: 768            // world units to fit in shortest dim
});
var bg_png = SETTINGS.GamePath ( 'resources/bg.png' );
RENDERER.SetBackgroundImage ( bg_png );
RENDERER.AutoRender();

// DEFINE SPRITE VISUALS AND PIECES ////////////////////////////////
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

// create a sprite visual for spaceship, add to Renderer draw list
var shipSprite = VISUALFACTORY.MakeDefaultSprite();
RENDERER.AddVisualToWorld(shipSprite);

// define a spritesheet animation
var shipSpriteSheet = SETTINGS.GamePath ( 'resources/crixa.png' );
var shipSpriteSequence = {
    grid: { columns:2, rows:1, stacked:true },
    sequences: [
        { name: 'flicker', framecount: 2, fps:4 }
    ]
};
shipSprite.DefineSequences ( shipSpriteSheet, shipSpriteSequence );

// create ship piece and give it visual
var shipPiece = PIECEFACTORY.NewPiece ( "crixaship" );
shipPiece.SetVisual(shipSprite);

// manipulate the ship
shipPiece.SetPositionXY(0,192);
shipPiece.Visual().PlaySequence("flicker");

It may not look very exciting to the layperson, but it’s really nice to be able to write code in terms of how I think. For me, ideal code is the code that you can read and understand what it’s doing without having to look anything up. It’s like inventing my own language, and the better the language is the easier it will be to develop further.

Recap of My Productivity for the Week

I didn’t find it easy to get into the groove at first. As excited as I was about starting the project, the asshole demons Tedium and Uncertainty were there to fill my head with downer thoughts like, “You don’t know the best way to do this, and it’s going to take FOREVER to figure it out” and “Wow, you’re going to have to rewrite that entire module from scratch? Hope it doesn’t break!” and “Surprise! You’ll have to learn how to use a poorly-documented code library before you can do anything further!”

I found that I tended to procrastinate early in the day, often doing other chores before getting down to the distasteful tasks of sorting through the code I’d written 5 months earlier, and knew was in sorry shape. I was about as excited about doing this as I would be cleaning out my basement or attic just so I could find a memento from high school.

I kept a journal for each day to see what I ended up doing. Here’s a distillation of where the time went, with actual coding tasks bolded.

day time hrs description
SUN 11:00 7.50 chores, naps, watch “The Blacklist”, dinner
SUN 18:30 0.25 look up how browser div dimensions are calculated
SUN 18:45 1.75 more “The Blacklist”, another nap
SUN 20:30 1.75 open code, stare at it feeling blah about starting
SUN 22:15 5.25 port and refactor renderer cleanly!
MON 10:30 4.75 morning spent on email, social media, eating lunch
MON 15:15 0.25 settle-in at Starbucks
MON 15:30 1.00 revisit RenderPass method design, write pseudocode
MON 16:30 3.00 rewrite RenderPass
MON 19:30 1.75 cook dinner, reflect, look at bills, search for old files
MON 21:15 2.00 port rudimentary VisualFactory, minimum tests work
MON 23:15 5.00 debug loader, redo Renderer world calcs, rewrite RenderPass
TUE 14:00 7.25 emails, interviews, long naps, cooked.
TUE 21:25 0.75 test git/node on Windows
TUE 22:00 2.25 create PieceFactory and Piece classes
WED 09:00 9.00 dental surgery in morning, slept until 6PM afterwards
WED 18:00 2.75 refine PieceFactory and ProtoPiece update chain
WED 22:45 1.50 add autonomous system updates, autosys.js
THU 08:00 9.00 moved car for plow, take out trash, clean cat box, answer emails, clean living room, find missing mail, facebook, twitter, watch “Agent Carter”, restore system to undo Chrome window bug.
THU 17:00 2.00 clean kitchen, clean dining room, eat gruel.
THU 19:00 1.50 ice cream social time with friends
THU 20:30 1.50 clean up kitchen, watch “Fresh Off the Boat”
THU 22:00 2.25 open editor. fall asleep on couch.
THU 24:15 2.00 open editor, add some tests, debug code, check features
FRI 12:00 4.00 read mail and newsletters, debug server problems, upgrade wp installs, optimize databases, eat yogurts, take meds
FRI 16:00 1.50 add MovingPiece code chain; implement super() call
FRI 17:30 0.50 chill out, look at screen capture software
FRI 18:00 1.00 add debug inspect module
FRI 19:00 3:00 watch first three episodes of “Deadwood”
SAT 11:30 4.75 dig out snow, take long nap
SAT 16:15 2.00 surf the net
SAT 18:15 1.50 clean, eat dinner
SAT 19:45 0.50 plan OS upgrade
SAT 20:15 5.00 begin OS upgrade

Some statistics:

  • I was awake for approximately 99.75 hours for the measured period, maybe a little more if I include time getting ready for bed.
  • I was productively coding for 28.25 hours, or 28% of my waking
  • I spent 62.25 hours “living” the mundane details of life, 62% of my time.
  • I spent 7.75 hours actively procrastinating from coding, mostly in the beginning of the week, 8% of my time. This figure is probably higher with the naps that I didn’t separate out of big “living” chunks of time.
  • I spent 1.5 hours actively socializing with other people, a mere 2% of my time.

Some observations:

  • The first few days of the week I was procrastinating hard. It took me almost 8 hours before I even started to look at code, suffering a series of headaches followed by naps. I suspected that this was my brain being filled with BS reasons from the demons Uncertainty and Tedium; once I started, I found generally that I would work for a big chunk of time.
  • I observed that once my brain latched onto the simplest of answerable problems, I could enter the flow state. That’s when I had the insight that any thinking about efficiency or the future was a distraction, and started looking for ways to just do the simplest things in the code base. Once I’m thinking in the moment of how to do something I could see, I was ok. Getting past defeatest thinking like “it’s going to take a long time” or “I don’t know a way to implement a priority queue off the top of my head” by making a change—really, ANY change at all—in the code base seemed to draw me in. I knew that I could trust myself to follow rigor.
  • Procrastination tended to occur before major systems. Renderer, VisualFactory, and PieceFactory were all systems that were messy-enough under the surface that I didn’t look forward to dealing with it. My attitude toward these systems was like, “this is a clogged toilet, or it’s a toilet that could overflow if I’m not careful.” I tend to want to have a clear system view in my head before doing anything, but in these kind of programming cases it takes a bit of trial-and-error to get a “feel” for how the system works, and then try to develop clarity from there. Once I got into the goo, I could emerge better solutions or experiment with a new approach. Now everything “flushes GREAT”, and I feel a measure of pride at how much better it is. But hoo boy, getting to that point that I can just dive into the shit is still a moment of truth for me.
  • Once a major system had be tamed, I found I had energy left-over to make little cosmetic tweaks here and there. Sometimes I would find a subsystem that I realized I could make a little better or a little clearer. For example, several times I renamed the Renderer’s “AddToRenderpass” routines to try to make them less verbose but still have the right grammatical fee. I’m thinking of changing them AGAIN, actually, to sound more action-oriented (e.g. changing AddWorldVisual() to AddVisualToWorld()).
  • I’m not sure if this is related to procrastination or a preference for nights, but I tended to do my programming after dark, starting between 4PM and 10PM on average.
  • Most of the programming was done at home because my environmental computer setup is pretty good. I worked on a few architectural things at Starbucks just to get out of the house and remember what people looked like.
  • My waking schedule is really uneven. Some days I wake up at 8 (particularly if it snowed and I had to move my car in the morning for the snow plows). Some days I woke up close to 4PM.
  • Keeping the daily journal actually helped keep me focused. I think my mind may work very conversationally, which is why I like chatty programming partners. Since I’m doing this project solo, the chatting has to be with myself. I’m using Scrivener as my journal.
  • It’s amazing having the Internet around to search for answers to my programming questions. AMAZING. One of the challenges is to weed the bad/outdated information from the good, but it’s so fast now to find answers to basic questions. I’m not sure it’s always good; sometimes the solution has been to rethink a problem from basic assumptions because the answers on the Internet often are of lowest-common denominator quality.

I should note that this was, perhaps, not a representative week due to the dental surgery I had on Wednesday (tooth extraction, socket reconstruction for an implant). This wiped me out for a day and a half. The pain hasn’t been bad at all, thankfully, so I can just take ibuprofen. Strangely I feel I’ve been more productive AFTER the surgery. I’ve taken less naps, for example, possibly because I’m not inclined to eat with all the stitches in my mouth plus the requirement of rinsing with medical-grade antibacterial mouthwash every time I swallow something. However, it was also mid-week that I had the realization about distracted thinking, and I was riding the momentum of getting stuff done.

It’s worth mentioning that the progress made this milestone is artificially inflated because I’m rewriting code that I’ve written before. It’s essentially a third draft. The code I need to write next—incorporating physics, AI, player management, leveling, game logic—are less well-defined and are in a rough state even in the parent project we’re doing for UCLA. This will require more design thinking, so I am anticipating (and trying to embrace) a slower pace. That will be a challenge!

The Next Milestone

Milestone 2 (M2) will be making a spaceship fly around a starfield. That was the original goal of M1, but I got bogged down in making the fundamental systems (Master, Renderer, VisualFactory, and PieceFactory) as good as I could make them. There were dozens and dozens of conceptual tweaks and clarifications that I was compelled to make, and forcing myself to meet the letter of my goal specification would have resulted in a half-assed implementation.

That said, there’s some interesting challenges to come:

  • The spaceship flight routines involves expanding the Piece class to support calls like PointAt() and MoveTo(), which can be done either through pure parametric geometry calculations over time, OR be implemented with a Physics simulation library. I’m not particularly strong with this kind of stuff; ultimately I will need to support both. This means that I need to dig into a field of Physics called “Dynamics”. Fortunately I am somewhat familiar with it already from past products, but it will still be time consuming. I wish I could learn it faster, but I will embrace the slowness of learning at my own pace, and stay calm. Once learned, this will be very powerful knowledge to wield!
  • Drawing the starfield behind the spaceship, in all its twinkling deep-space glory, will require both some physical modeling AND writing a whole new kind of visual object. This will probably take a few days, which again I wish I didn’t have to do, but will be necessary. Again I am fortunate to already know how my former co-worker Bretton approached the problem 20 years ago for our old game Crixa, and I’m familiar enough with 3D graphics to not be totally lost digging into ThreeJS’s underlying data structures.

After that, there’s MORE support systems to write!

  • I don’t have a control input module that reads keypresses, so there’s no way to control the ship once it’s in-place. I don’t think this will be tough, but it will require some design time to think of how it will work with the overall system.
  • I don’t have a sound module either, but I chose a library a while ago that will seem to do the trick.
  • There is a whole bunch of timers, triggers, filters, and events that I have to port/write, not to mention the state machines, rule enforcers and artificial intelligence behaviors that will make use of them. I’m looking forward to this.
  • Level loading and management along with runtime game control is another level of complexity that tends to make writing simple games hard. Making this super-clean and easy to develop modularly is a major design goal.

Not to mention updating the project Wiki, describing what all these things do. And I haven’t even considered the art side of game development, but for now I’m not going to worry about it.

I have another week to work on this, as the UCLA project is doing another week of classroom tests (week 1 went well, I hear). Because the work I’m doing now on my 1401 project can directly improve the UCLA project for the next stage of development, I may start on timers, triggers, AI, state machines, and level management. Our current system is an ad-hoc collection of custom logic, written very rapidly so the team could get it in front of the kids during their President’s Day break.

So here’s my M2 Specification, influenced a bit by UCLA/STEP’s upcoming needs:

  • timers/triggers/filters/events
  • behaviors and state machines
  • stage and level management
  • simple move-to physics
  • starfield
  • sound manager

I will be amazed if I get that all done.

If any programmers out there want to check out what I’m doing, all the ongoing progress on Project 1401 is on my 1401 Project Page here on davidseah.com; there’s a link to the 1401 Github Repository there.

I also made an installation video to walk people through the process of installing the necessary development tools, using some new video tools I had lying around:

So that’s it for this milestone report! Thanks for reading this far!