As hinted in my last post I’ve recently
started work on a game. I intend to make this the first of a series of devblogs
chronicling my work on it. Today, I’m going to give a brief rundown of what the
game is (or how I imagine it) and the current state of the prototype I’ve been
The working title for the game is Fleet; it’s a bit of a mixture between chess
and Hearthstone with spaceships and RPG elements. Here’s how it works:
Before a match/out-of-game each player maintains his/her “fleet” which is a
collection of ships. Each ship has a pilot and some items. Pilots have some
stats, right now Precision, Accuracy, and Evasion, which control Crit Chance,
Hit Chance, and Dodge Chance, respectively. A ship’s items are things like
weapons or shields or even signal jammers that can be used in game. Pilots’ stats
or weapons can be upgraded out of game with some sort of currency that’s earned
by winning/participating in games.
Each ship additionally has a class which determines things like how many
items it can have, how much health it has, etc. For example, “Jumper” class
vessels can move around really quickly, but have low health and only one item
In game, every action (moving, using an item) consumes a portion of the ship’s
energy. A fixed amount of energy regenerates at the end of each turn.
Once in-game, the object of the game is to destroy the opponent’s mothership
before they destroy yours. The mothership will be at a fixed location opposite
your own mothership and can be damaged with weapons like any other ship.
Overall, I want the game to be simple-enough for anyone to jump in after a tutorial
and I also want it to be very open to casual play. However, I also think the
strategic elements make it a prime candidate for serious/competitive play.
I always planned on launching for desktop first, but had hoped I’d be able to
easy) but I’m starting to think that the amount of information necessary to
play will be hard to fit on a mobile screen. That’s a ways off though.
So here’s the problem: I am terrible at prototyping. I’m the type of person that
enjoys the design and architecture part of software development probably more than
the actual implementation. I’d rather spend 10 days designing the perfect API rather
than designing 10 iterations every day. This is almost always a bad thing; iteration
is crucial. One article that I found particularly interesting against the idea
of premature-abstraction was
Casey Muratori’s post on “Compression Oriented Programming.
The idea of not abstracting until you need an abstraction, rather than abstracting
in anticipation of needing it, makes a lot of sense to me, even if it isn’t
exactly what I’ve been taught.
So here’s my progression from being very bad at prototyping to being slightly
less bad at prototyping. When I started working on
this game, the first thing I started working on was the server
networking architecture. And I spent at least an hour just designing it. This
was terribly unproductive for a few reasons:
Networking is genuinely very hard to get right
Networking is not as fun as the actual game
Networking won’t tell me whether or not the game is fun
I can’t get easily get feedback on the networking without also having developed
A lot of these realizations came after having watched
Extra Credit’s excellent video on “MVP”
I ended up scrapping a lot of what I had done and
started working on a purely client-side implementation. The games would be between
a human and an AI player so I wouldn’t have to worry about anything server-side.
The next hiccup I encountered was the UI. The nature of the game pretty much
requires a fairly hefty UI to represent all the information you need and allow
you to take action appropriately. I originally had started out trying to do it all
on the canvas, trying to roll my own basic layout library before I caught myself
and searched for a better solution. I was working with web-tech anyway, so why
not just use HTML for the UI for now? Within about 20 minutes I had a fully
functional UI thanks to my existing HTML+CSS experience. That allowed me to
finally get to work on the important stuff: gameplay.
The gameplay is going well, and I have a few ideas for posts in the next couple
of weeks about interesting things I’ve done so far. Currently, the game supports
2 unique weapons
Deploying vehicles from the hanger
Moving vehicles on the board
Fully functional UI to do all of the above
An example of current gameplay is shown in the GIF below. The blue hexagons are
ally ships, and the red is an enemy ship. The green bars on the left side of hexes
represent health and the yellow represent energy.
Against my best wishes because the codebase is a mess, I’ve forced myself to
put all the code on GitHub in its current state.
Try not to look at the client code because it’s a mess. The game folder is a bit
better and more interesting.
Issues & Next Steps
I have these ordered based on how important I think they are, so if you think
I’m wrong please let me know!
Very basic AI; just enough to test more interactions
Add “win” conditions so you can play a game to the end
Allow users to customize their fleet (this actually might not be necessary in the prototype)
Add support for status effects/items other than just weapons
Improve AI to make it somewhat formidable
At this point, I’d say it would qualify as a “game”. From there, I’d need to
add art, begin adding multiplayer, add much more content & items, etc. One step
at a time.
I hope you enjoyed my first devblog; hopefully there will be many more to come.
Until then, let me know what you thought on
Twitter (@ganashaw).See you next time!
I’ve never really been one for New Year’s resolutions. Part of it is probably
that I’ve always been fairly comfortable and complacent with my life that
making any drastic changes has seemed entirely too inconvenient. As you’ve
probably surmised from the title, I’ve had a change of heart. My hope is that
by writing them down, even if no one else reads them, I might feel a tiny bit
more obligated to stick to them. Hopefully, in 365 days I’ll have a new post
to say that I actually completed them all.
1. Write More
I’ve had this blog for quite a while now (3+ years) and I have 6 posts, including
this one. That’s pretty pathetic. I think writing or at least keeping some sort
or journal is a fairly productive thing to do. Especially with respect to
technical aspects, I think writing about projects helps to review your work and
think about ways you could have done things better or differently. Assuming
someone reads what you write, it also provides a means of receiving feedback
which is invaluable. I think the most important consequence of writing about
projects is that it forces you to justify your decisions. The more detail you include, the
more you have to rationalize each decision you made. I hypothesize that this
will make me a more deliberate, careful developer since if I make bad decisions
I’ll then have to tell the entire internet about how I made terrible design choices.
2. Develop and Launch a Game
Every two months or so for the past several years, I get an overwhelming desire
to develop a video game. This typically results in me coming up with a
half-baked idea, spending an inordinate amount of time to come up with a
clever name, spend about a week tops coding up a prototype without finishing and
then abandoning the project altogether. My goal for 2017 is that I actually
follow through on one of these projects and “finish” it. Besides just developing
a game, I want to maintain a devblog, promote the game on social media, and do
all the things a typical indie developer would do. I don’t plan to go into gamedev
full-time any time soon, but I think there are a lot of skills that I can learn from
hobby gamedev that will help me in other aspects of my career. The gamedev bug
has bitten me again so I’ve currently got something in the works; with any luck,
the first entry of my devblog for that project will be out this week.
3. Read More
I’ve always vehemently abhorred reading. I don’t know why. I found it tedious and
boring. I still do, but now I recognize that it’s actually kind of a good thing
to do. Especially in the software development field, there is a ton of literature
written about how to become better at the craft. I’d like to read a few of these
books. At the top of my list are:
I’d also love any fiction suggestions to throw into the mix. I’ve read and loved
the entire “Hitchhiker’s Guide” series by Douglas Adams.
4. Increase My Faith
2017 will be the first year in which I’m not a student, seeing as I’m graduating
in May (woohoo!). A consequence of this is that I’ll no longer be held accountable
by others (e.g. religious educators, FOCUS missionaries) with respect to my faith.
It will be completely up to me to nurture and increase it. My goal for 2017 is to
accomplish this. The exact method isn’t clear, but I know I want to grow
closer to Christ and He wants to grow closer to me.
So that’s it. My four resolutions for 2017. Feel free to hold me accountable on
Twitter (@ganashaw). Hopefully, I’ll be back in
a couple days with a devblog for my latest project.
I’m definitely an idea guy. I have ideas all the time. I think that most of them
suck, but the thing with ideas is that there’s no way to know if they suck unless
you execute them. Generally, when you have an idea you want to make a prototype
as quickly as possible so you can decide where your idea falls on the scale of
suckiness (or greatness, if you’re lucky). But like I said, I’m an idea guy, not
an execution guy. Executing is hard. Whenever I sat down to try to prototype an
idea one of the major roadblocks for me were graphics. It seemed like any low
level (aka powerful) language required lots of external libraries and gross stuff.
It was a pain, for me and probably for many others. So ugly is my attempt
at fixing that. I dreamed up ugly as a universal graphics library, a graphics
library that could be used on any machine, with any language, really quickly.
And I think I succeeded.
Starting out, I had a few goals in mind when making ugly:
Good revision history
I wanted to force myself to make small, frequent commits. This has a two-part
purpose. One, by keeping the commits small, it’s easier for me to make progress
because it takes less time to make that little change here or add some safety
checks there. Secondly, it makes it easier to track down bugs. If I don’t
notice a bug right away, it’s easier to go back in the history to find out where
the bug first occured, and since the commits are small, it’s usually very obvious
what change introduced the bug.
(There’s also a third advantage: it makes writing project-recaps like this much
I had a really bad habit of not finishing projects. I wanted to finish ugly.
And I did. And I’m proud of myself for it. (Ironically, this blog post took
me several months to finish…)
So I wanted to make ugly language and platform agnostic. That means it had
to be written in a language that everyone had. And what does every computer have?
rendering in the browser. Unfortunately, there’s really no good way to get data
so I built a server implementation in node.js to forward data from the client
to the viewer. The interface was fairly simple: The client program or whatever
needed to be rendered writes data to the node.js server via stdin. The server
would validate incoming commands and then forward them to the browser-based
renderer using websockets.
At this point, there were a few things I wasn’t certain of. I was mainly worried
about the latency that would be introduced by introducing the node.js
middle-man. It was important that the rendering happen as close to realtime
as possible. However, as I couldn’t think of a better way to achieve what I
wanted, I decide to go ahead and try it out.
Note: This is pretty much me narrating my commit history. Yay version control!
I started out just having the node.js server read lines from stdin. I then
introduced a basic logging module to handle logging to a file and/or stdout
and stderr. Next I cooked up the code for serving the rendering-client where
the actual drawing would happen and forwarded the lines read from stdin to the
client via websockets. At this point, all the connections were made and I just
had to add the logic.
The next thing I had to do was define the format in which ugly would expect
incoming commands to be. I decided on a fairly minimal syntax:
command_name arg1 arg2 arg3 ...
I also introduced the concept of ‘chunks’ which grouped related commands:
There would be two types of chunks: CONFIG chunks which would define settings
to be used throughout the render and FRAME chunks which would define the
drawing commands to be used for a single frame.
I decided that the server would be responsible for validating the commands so
that the client could assume it only received valid commands. The less
non-drawing work the client would have to do, the better. As I started writing
validation code for the commands, I realized that this was going to get real
gross real fast. I essentially had a block of code that looked like
And I planned to have well over 30 commands. I decided to split out the commands
into their own module. Each command be an object with a validate function.
This way the server, could simply query the command module, get the command,
and call its validate function:
For one, this made it a tad bit easier to add commands (I didn’t have to add an
extra “if” branch for each command), but it also turned out to make executing
the command easier on the client-side.
(Note: in the end, instead of having
a validate function for the whole command, I had a validate function for each
argument, but this is a minor implementation detail; the gist remains the same)
Once the command was validated server-side, I sent the full plaintext string to
the client via websocket. Here, I once again leveraged my command module. In
Conveniently, you can also access and execute this function like
The key here being that the function is identified by a string. That meant
in my command module, I just needed to save the string representation associated
with each frame command. Additionally, I needed to get the arguments. This was
again easy because the arguments my plaintext command took were exactly the same
in exactly the same way; all that changed was the data.
Putting It All Together
To give you a better idea of how the commands are actually processed, I’ll trace
the execution of one all the way through. Here’s an example of how the
clearRect command is represented in the command module:
And here’s how that command would be provided:
clear_rect 0 0 100 250
The server would first read in the full string (line 3 in the code block above).
It would then take the first “word” ('clear_rect') and search for it in my
commands module (which would return the objct in the firstcode block above). From
here, the arguments of the plain text command would be validated. To do that, it
first sends all four parameters (0, 0, 100, 250) to the FLOATparamType,
since it is the paramType of the first parameter in the parameter list. That parameter object
would validate it and return whichever arguments it didn’t use. In this case,
the float parameter uses only the first parameter so it leaves 0, 100, and
250 (parameter types don’t always consume just one argument; a color param-type
for example consumes four: r, g, b, a). The remaining parameters then passed to the
next parameter objects until they are all validated. If no errors are encountered,
that command is sent to the client.
When the client receives the command, it again looks up the clear_rect object.
For example, for a paramTypes.FLOAT, passing the string '3' would return
the value 3. This argument list is then used to call the function:
And we’re done! Feel free to read through the code to see it in action.
So that was the basic design and structure of ugly. I’m very pleased with the way I
was able to cleanly separate the data (the commands and their arguments) from the
execution. The amount of code reuse in this project is really quite impressive
in my opinion.
I think the most exciting thing about ugly was when I got the first (and as
of yet only) pull request. Just a few hours after posting the project
on Reddit and HackerNews, someone submitted an example that used ugly to
visualize Conway’s Game of Life. It was super neat to see someone using code that
I wrote. That alone made the whole project worth it.
If ugly is something that sounds useful to you, go check it out on
GitHub. As always, pull requests are welcome!
Last year while I was looking at perspective colleges, and even once I had decided
on CMU, I was very interested in the student perspective; what it’s like to actually
be a student at Carnegie Mellon. Surprisingly, there was very little available
aside from the standard student life page on each university’s website. Seeing
as I’ve completed roughly a semester and a half now, I thought I’d go ahead
and contribute for anyone who might be interested in that sort of thing.
Since a significant portion of the post will be subjective, my background is probably
relevant as it definitely shapes my expectations and opinions of things. First
things first, I’m a freshman studying computer science. Before college, I spent
three years at The Louisiana School for Math, Science, and the Arts
a public school for high-achieving highschoolers in Louisiana. LSMSA is actually
situated on a college campus, and most of the classes are taught by college
professors at a college level; about 90% of my teachers had a terminal degree
in their field of study. As a result, I had already experienced a lot of what
is often lumped into the “college experience.” Namely, I had spent three years
living relatively independently in a dorm, I was being taught at a college level, and I was
being exposed to a truly diverse group of people; much more than an average
highschool. I point this out mainly because these are all aspects which may
have a significant impact on one’s college epxerience, but they weren’t for me,
so I probably won’t talk about them as much. Additionally, I’m one of the most
introverted people you’ll ever meet (if you ever meet me..) so I can’t comment
much on the social scene at CMU either.
As a freshman, your first real look at CMU will be during orientation week.
I mean sure, those summer tours are great, but they don’t really give you a feel
for the campus and student body. Before anything else, you have to move in. I must
say, the orientation staff make this absolutely painless. I got out of my car,
they told me to go do some logistical things like get my ID and some CMU swag,
and by the time I got back my stuff was already at the door of my room…on the
third floor. Already, I’m digging this place. The week continued pretty much
as expected, awkward ice breakers, cool performances and shows, crowded meals,
and lots of walking. As an introvert, a lot of the week was uncomfortable for me;
I suspect that that’s the case for a lot of CMU students, especially computer science
majors. I didn’t really end up with a close-knit group of friends like many people
seemed to; however, that’s not for lack of opportunities, and probably more
for lack of me trying/knowing how.
After orientation, I got my first experience of real college life. A few classes,
surprisingly not terrible food, and a pretty substantial amount of homework.
My first class was Matter and Interactions I, which is described as the “Honors Physics”
course at CMU. I felt compelled to take this course for a variety of reasons.
First of all, without it I would have been carrying “only” 40 units of classes.
(For a freshman, the maximum is 55 and the minimum is like 35, I think) Despite
having been accepted into one of the most prestigious schools in the world, while
I was scheduling my classes I for some reason still felt the need to “prove” myself.
To justify my presence. I thought that the best way to do this was to take
as many hard classes as I possibly could. As if somehow I was being a slacker
if I wasn’t taking the maximum number of units every semester. Within about two weeks, I gravely
regretted my decision. One of the most dangerous traps that I fell into during
that first semester (and still do to this day) is making the assumption that
because my computer science classes are super hard (and they are), all of my
other classes are super easy. (and they aren’t) Matter and Interactions kicked
my ass and the ass of just about everyone else in that class. It was hard, and
it took up a lot of my time. And the worst part? I don’t think it really even matters.
I mean, I’m not a physics major, I have no intention of getting a degree in physics.
I could have taken the intro physics class and my graduation requirement would
have been just as fulfilled, recruiters probably wouldn’t have known the difference,
and I would have had more time to spend doing things
that did matter, like my CS classes, side projects, and research. More on that later…
Eventually, I got into the groove of things and developed a pretty routine schedule.
I had class every day til about mid-afternoon, went to Gates and watched Netflix until
5, grabbed dinner, worked on any homework due the next day, played video games,
and went to sleep. On the weekends, I spent my Saturday afternoons playing video games
or working on side projects and my Saturday nights (about 8pm-1am) working on problem sets because I honestly
didn’t have anything better to do. Typically I could finish about half of my week’s
work on Saturday nights. On Sundays I went to my research meeting and worked on that
for a few hours, then worked on homework until a meeting for the FSAE team at 6:30,
before having dinner, going to mass, and going to bed. This was how just about every
week played out. Honestly, it wasn’t that bad, aside from the inevitable frustration
over my math assignment, I was pretty satisfied. Still, it seems as though this
pattern of routineness is inevitable; or at least I haven’t found a solution.
This semester is pretty much the same except I have a lot more work. Great
Theoretical Ideas for Computer Scientists (15-251) is, according to many, one of the most
challenging CS courses students are required to take at Carnegie Mellon; I easily
dedicate 6-10 hours per week just working on the homework not to mention attending
lectures and “homework writing sessions.” (don’t ask…)
Now, don’t get me wrong, I’m not complaining. When I decided to come to CMU, I
expected to be pushed harder than I’ve ever been pushed before, and to get my
ego taken down a few pegs. Both of those events occurred within about a week.
The grind isn’t bad…in many ways it prepares you for the real world, for a job,
but it is a grind nonetheless and it can wear you down. On the brightside, to counteract
the grind, CMU students, especially CS students, are presented with loads of perks
that make the grind worth it.
Carnegie Mellon University has one of the top computer science programs in the
country. Naturally, there are benefits. The first that I noticed was just how
eager companies and recruiters are to talk to you. I remember sitting in Gates
(the computer science building) one afternoon and a company’s recruiter came around
the study area handing out cookies and flyers for a tech talk that
evening. Maybe it’s just me, but that blew my mind. Companies really really
want to hire you. Even as a freshman, it’s pretty normal for students to get
summer internships at Google, Amazon, Microsoft, etc. as well as smaller startups
working on really cool things.
Another huge perk is the caliber of the faculty working here. World famous professors
in any field are normal, professors working on things that could truly change the
world. And the best part? They’ll let you work with them. I knew coming into
Carnegie Mellon that I wanted to get a taste for doing research, so I started
looking at professors doing cool things. I eventually found Dr. Red Whittaker.
He’s done some pretty freaking cool things like
building an award winning autonomous vehicle,
and leading the pack for the Google Lunar XPrize.
I walked into his office one day and asked him if there would be room for me to
work in his lab and within a month (he’s a busy guy) I was writing software
for a 30cm x 30cm x 30cm experimental lunar rover. Opportunities and perks abound
at CMU, and I’ve done my best to take advantage of them as much as possible.
The Journey Continues
I’ve only been here for about 6 months now, so I’m still figuring stuff out, but
I’ve definitely learned a lot already. I’ve learned that I don’t need to be the best
at everything. I don’t even need to be the best at anything. In fact, there’s
probably many people better at me in just about everything. The best I can do
is my best, so that’s what I’m going for. One step at a time, the journey continues,
and so far it’s been totally worth it.
It seems to be more and more common for students to brag (or complain, regret)
about how little sleep they got the previous night. It definitely happened at
my highschool and it’s even more prevalent here at CMU. Fortunately, I had been
lucky enough to never have to pull an all-nighter…until last weekend when
I participated in my first ever hackathon here at CMU. TartanHacks 2015 was a
blast and probably one of the most enjoyable all-nighters I’ll ever experience.
It started like any other Friday: classes until 2:20, research meeting at 2:30,
bible study at 4:00, dinner at 5:00. Then things got exciting. I waited in line
for about 5 minutes, obtained a wristband, and proceeded into the auditorium.
I met up with my group and we listened to the sponsors brag about their sweet
prizes (read: badass drones, cash money) and convince us that we should use their
APIs. Then, we rushed to get dinner (after securing our hack spot of course).
The wait for dinner was absurdly long and unfortunately we lost about an hour of
valuable hack time, but in the end it turned out not to matter.
Our idea was pretty simple: craigslist, but for rentals. A platform that would
allow students to rent out their un(der)used items to fellow students. As simple
as it was, it still turned out to be a lot of work. One thing our group struggled
with was the division of labor. All the inner workings seemed pretty connected
that it didn’t really seem possible to work in parallel. As a result, most of the
coding ended up on me while my peers helped me scope out potential APIs and other
logistics. I didn’t mind, but I felt kind of bad that I got to have all the fun.
This is definitely something I’d like to improve upon in the future.
I think I wrote the first line of code at around 8:30pm Friday night and I had
finished a somewhat working application around 9:30am Saturday morning. Luckily
I didn’t run into any significant technical challenges throughout the night; I
really had a ton of fun. Something about bringing a project from nothing to..
something in such a short period of time was really rewarding. It really affirmed
my education/career/life path. Programming is truly something I love.
After hacking had officially ended on Saturday night, there was an expo for everyone
to show off the things that they made. To say I was blown away would be an
understatement. There were devices made of card board to help the visually impaired
see in 3D. There was an augmented-reality version of Asteroids. There were so
many things I never would have thought of and yet I wasn’t surprised at all.
Hackathons seem to really bring out the most intelligent, creative, awesome people.
The kind of people that you just know will be successful.
My team’s app, shown above, didn’t win, but I wasn’t really disappointed. We got
some awesome feedback and I had a ton of fun. I was absolutely exhausted and I
think I slept for about 14 hours the next day, but it was so worth it. It is
definitely an all-nighter I’ll never forget.
Almost all programmers that I’ve talked to are huge proponents of open source
software. Recruiters avidly encourage job applicants to contribute to open source
software because they love to see it on resumes. Until a few days ago, I had never
contributed to any open source project other than my own. Finding myself terribly
bored one weekend, I decided to change that. So this is a brief summary of my first
contribution to open source software.
Step 1: Find a Project
This has almost always been the hardest part for me. Ideally, you want a project
that doesn’t have a huge codebase already. Less code makes it easier for you to
contribute right away. However, you also want your contribution to matter. The
incentive to contribute to an obscure command line utility that only works on
Ubuntu 10.02 is minimal at best. I used Github to explore interesting projects.
There are also websites that pick out Github repos with the most “issues” but
the problem with that is that most of these projects have literally 1000s of issues.
That can be pretty intimidating for a newcomer. Luckily, I stumbled upon a neat
The appeal of this project was three-fold:
It’s codebase was small and condensed. Everything was in a single file of about
The owner had included an explicit TODO list at the bottom of features he’d like
to add but hadn’t gotten two yet. A perfect place for a rookie like me!
Step 2: Write Some Code
After I had found this project and settled on how I would contribute, I forked
the repo and got to work on my solution. This should be the fun part, and it was.
I did my best to maintain the same style as all the other code that had been
written, even if I didn’t agree with it (spaces are inferior to tabs, people).
Aside from style issues, I made sure to avoid making any unnecessary globals
to avoid polluting existing code. Overall, I made sure I wrote quality code,
just like I would if I were working on my own project.
Step 2a: Test Your Code
I can’t think of anything more embarrassing than submitting a broken pull request,
so I made sure to thoroughly test my code after it had been fully integrated.
I found a few bugs, fixed them, tested some more, washed, rinsed, and repeat until
I was confident I had flawlessly implemented the feature.
Step 3: Submit a Pull Request
Finally, I submitted my pull request and waited for the owner’s response. At first,
he briefly looked at my code, said it looked good and that he was testing it locally.
Score! A few hours later he came back and told me he was experiencing a bug with
part of my implementation. Much to my dismay, there was indeed a bug in my code.
Luckily, I was able to fix it in a matter of seconds. I committed, pushed, and
waited for his response. After that, the owner and I had a brief discussion about
what different parts of my code did, and then he merged it with the existing repo!
Now, anyone who uses his library will be using some code that I wrote, and I
think that’s pretty cool.
Hopefully, this is the first of many contributions to open source software. It’s
definitely a satisfying experience that I would recommend to any programmer.
I just recently finished developing an adaptation of the classic “Lights Out”
game. For those of you who aren’t familiar, the object of the game is to turn
on all the lights on the grid. Whenever you toggle a light, all 4 adjacent lights
would also be toggled. In my version of the game, Lights, the same rules and
objective apply. However, some lights are “directed” meaning when you toggle them,
only the adjacent light(s) in certain direction(s) are toggled, which increases
the difficulty of the game. The game itself has some fairly interesting nuances
to it. Firstly, the order in which you toggle lights doesn’t matter. Assuming
you start with a board configuration A, if you toggle light 1 and then light 2, this
is equivalent to toggling light 2 and then light 1. Also, somewhat obviously,
tapping on the same light twice (or any even number of times) is the same as not
tapping it at all. Likewise, tapping a light an odd number of times is the same
as tapping it only once. What this mean is every solvable board can be solved by
tapping a subset of lights only once. Pretty nifty.
Design and Structure
I have a really bad habit of over-engineering my code. I actually started this
project last May, but I didn’t get very far. I started looking at the code again
about a week ago and was pretty overwhelmed. It consisted of about five
different classes that did somewhat obscure things in very obscure ways. I started
by pruning away almost all of the existing code, and began working in a single file.
Surprisingly, this made my code more readable than when it was split up between
classes. It was easy to follow the code which greatly aided debugging. I think that
having everything in one place will also make it easier to maintain (to a point).
I’ve always had a thing about making my code “look good” and to me, long files always
failed to achieve this. However, I’m starting to see the beauty of consolidating code
and replacing lots of little classes with lots of little functions.
As far as the design of the game, I’m actually pretty happy with it. One
aspect that I didn’t like was the fact that I couldn’t find a way to add multi-directional
arrows without cluttering the design. If you play it, you’ll notice that arrows
are always either up/down or left/right. Never both. There’s nothing difficult about
this from a programming standpoint, but I absolutely could not find a way to
elegantly add it to the design. I’m not too upset about this, but I never really
like when form gets in the way of function. Perhaps a better designer than I could
come up with a solution.
The development process went fairly quickly, which is a first. I did get to play
with a few things that I hadn’t before, though. For example, this was the first
so much simpler to have all of the animations handled by CSS. I know I’m barely
scratching the surface but I can see now why people have been so excited about
handles cookies is very interesting for me. Cookies are stored in document.cookie
as a “string.” I put string in quotes because there’s some sort of voodoo going
on behind the scenes. Namely, when you define a cookie, it’s generally of the form
name=value; expires <UTC DATE>. You then assign this value to document.cookie.
But what if you want multiple cookies? Well, you do the same thing. But you only
specify one at a time. So, as an example, the following snippet would store three cookies:
What gets to me is that it looks like we’re assigning to document.cookie each time, but it never
gets overwritten. Furthermore, if we were to then read document.cookie, we would see
What happened to the expiration dates?! Your guess is as good as mine. What made
cookies really annoying is that there doesn’t appear to be a way to test cookies
using the file:/// protocol, which makes local development very difficult. (As
an aside, Google Chrome supposedly has a flag to enable file cookies, but I couldn’t
get it to work).
I think the biggest thing I gained from Lights was finally finishing a project
and releasing it to the public. I don’t think I’ve ever done it before and it’s
a really good feeling to finish something and be satisfied with it. I would deeply
appreciate any feedback you may have, you can contact me on Github or via email.
At the moment, my best score is 31. Can you beat me?