Tuesday 23 December 2014

SpaceChem should be taught in school

Greetings interwebs, long time no... blog?

Anyhoo, I just started playing SpaceChem last weekend, (got it for a dollar. Thank you Steam sales.) and while I only just finished the second world this morning, I'm not kidding about that title.

For the uninitiated, SpaceChem is a game in which you are an engineer working for a chemical engineering firm in the 2700's. Your job is to build and connect custom reactors which take one to two chemicals in and sent one to 2 chemicals out. The inside of a reactor is split into 2 halves, the red half on the top and the blue half on the bottom. Each half has its own input, output, and 'waldo', a bull's eye looking thing that travels at a constant speed along the 2D circuit you layout. Along the circuit are commands to grab or drop an atom (and any other atoms attached to it),  bind/unbind atoms, admit a new input, release an output, or wait for the waldo on the other circuit to pass a given point. There are probably other commands I haven't seen yet, but what I've described is enough to get the gist of it.

The trick is that while the waldos can run over and through each other all day, the atoms they are carrying cannot. Any collision between atoms crashes the whole process, so you have two parallel systems that have to work together and cannot collide. On top of that, your reactor will be part of a pipeline and if a reactor down the line is slower than the reactor feeding it, the unused input will queue up at the pipe until the molecule at the back is unable to leave the reactor and is it by the molecule behind it, again causing a crash.

So you have a set of procedures with inputs and outputs that run in parallel, form a pipeline, and must not crash. Some of you are probably thinking, "Man, that sounds a lot like programming!" and if so, good, because thats basically my thesis here. Not that I'm the first person to say it by any means, in fact that was basically the pitch from my friends trying to get me to play it. But I think it's more interesting than that.

On the surface, the game is obviously very different than conventional programming. But I think the reason everyone relates it to programming is that it captures the core experience of programming without duplicating the everyday mechanics. When you open a fresh reactor, you come up with some idea of what you need to do, assemble the circuits, and then run. And then it breaks. Something doesn't happen the way it's supposed to, so you look it over and diagnose the problem, then change the circuits to fix it, and try again. And it breaks in a different way, so you find the new problem, and fix that. Test, analyze, modify, and repeat until done. And when it works, it's just as surprising and thrilling as seeing seeing your program finally doing what it's supposed to do. If I wanted to explain to someone how programming worked, I would probably show them a simple program or point them to turtle graphics or something. But if I wanted them to understand why I program, to understand what it felt like, I would make them play SpaceChem. It hits all the same notes without having  installing any new libraries on their computer, except Mono if they're on a Mac. (Pro tip: nothing makes a downloadable application sound safer than naming after an actual virus.)



And that is why I think everyone should play this game at least once. It communicates the basic appeal of programming that so often gets lost amongst the jargon when you try to explain it to them. I don't think it should be a mandatory course, just one of the many applications on the elementary school lab computers that students ate encouraged to try. And if a student really likes it, get them started on python or javascript, because they're probably good candidates for future programmers. And your future software engineers? Look for the kids who can't abide a backup even if it isn't bad enough to keep them from winning.

As for people who are already programmers. Play SpaceChem anyway, it will be good training for you too. The game's focus is on parallel processes in a pipeline, where the goal is fast, reliable throughput. These are concepts we talk a lot about in computer science, but for practical reasons, rarely get to play with. At one point in the game, I wound up having to slow down one a producer to keep from overwhelming a necessarily slow consumer. That situation would never come up in my hobby projects or my job, but in large scale data management, it's a very real possibility.

So there you have it. Whether your a programmer yourself, or someone trying to understand what  programmers are on about, or even just a person looking for unique and interesting game, you should definitely check out SpaceChem.













....Why are you still here......

Oh you want update on the other thing... *sigh*...

Stratagem (working title) has been through rather a large pivot over the last several months. After my last post I dove into getting an HTML5 javascript version a good way in, but I was dragging my feet. At the same time, I came to a realization that nearly every studio in Vancouver is using Unity, so my not knowing how to use it was a bit of a negative for future resumes. And then I thought about why I chose the HTML5 javascript route in the first place: playability on lots of devices (via the good ol web) and a skill set I needed to build anyway, and I realized that both of those apply to Unity way more. So I dropped the old prototype and started working on a Stratagem Unity project. The only problem was that I knew jack all about Unity and was slow to force myself through learning it. I've gotten over that particular ump now and I've officially surpassed the old prototype's functionality. I'm hoping to have a really simple playable version by new years eve, but I have other stuff I need to do as well and it's Christmas, so we'll see how far I actually get.

See ya.






.... What? You need me to sign off? But it's super embarrasing!

Fine.

I'm Lambwatt, and this is day.... 236?!  OH #*@& ME!

Sunday 22 June 2014

Collision Course

Howdy Interwebs,

So about a month ago I was inundated with a stream of emails informing me that a tweet I made back in November had suddenly started recirculating.  November was the Concentric Game Jam, in which I succeeded only in failing spectacularly, partly because I was trying to to use an engine I'd been working on and it wasn't ready by a long shot, and partly because I got hung up, as I often do, on getting reliable collision detection working. That prompted me to tweet this:



I think it resurfaced because I barely tweet at all these days, so when I announced I was updating this blog again last month, this relic was the most recent tweet before it. And at 7 retweets and 2 favourites, this is easily the most traffic I've gotten on twitter, or even the web at large. Admittedly I'm still a bit shy of internet famous, but it's a a start.

But I didn't come here to advertise a tweet.  God help me if I ever do. I just thought it was an odd coincidence, since that collision problem has continued to gnaw at me, and since I was getting back into the habit of working, I set about fixing it.

Side note, throughout this post, some of my fellow developers will be screaming "VECTORS! VECTORS! VECTORS!", and they're not wrong. In the later part of development of this library and the writing of this post, I came up with a 3 box check that can solve the whole problem and many other problems relating to angular collisions. Should I need it, I will probably code that library up too, but most of the times i have found myself in need of collision detection, I was just using simple x, y, width, height hit boxes (Henceforth WHYX hit boxes) and so that is what this program and post concentrate on.

So in simple platformers, the easy solution to collision detection is to ask 4 questions of each object in the scene. Is it above me? Below me? To my left? To my right? If the answer to all of these is no, the object must be inside you. This method easily tells you if you are colliding with something in your current position. Of course if you're moving, things get more complicated. If an object is 20 pixels by 20 pixels and is fall down at 10 pixels at a time, it will always detect the the ground beneath it by checking if its new position is hitting the ground. But if it's falling at 40 pixels at a time and the ground is only 2 pixels thick, then the objects new position underneath the ground is clear so it will proceed as if the ground isn't there and fall forever. Very sad.

To solve this problem, most tutorials I've read suggest using a super simple technique. Instead of moving all at once, we move in even increments, say 20 pixels at a time, and detect collisions as we go.  This solves the first problem, but there are two other important problems it doesn't solve. Suppose the object is falling toward a deadly spike, but above that spike is a thin platform. It is possible that the same collision check of a 20 by 20 pixel box that first detects the platform also detects the spike. So now you need to know which was hit first. In this case we were going down so the object that is higher is hit first. But if it's moving up then this is all backwards and if we move diagonally, it introduces a whole bunch of new possibilities. So should you resolve the x first or the y? Either way you will slightly favour the player in some situations and hurt them in others. A player trying to avoid falling down a pit stands a better chance of snagging a ledge if the x is resolved first, while a player trying to just barely jump over a spike will find it a lot easier if the the y is resolved first. You could resolve both first, but now an object might move through a diagonal hole much smaller than the object because the two object sized check regions are on opposite sides of the whole with an overlapping region in the middle that does fit. (Think of how the overlapping section of a venn diagram isn't as long as the full diameter of either circle.)

You can solve most of these problems for a simple game by moving the object one pixel at a time. This way you hit the first object first and if you balance your x and y changes you can move in approximately the right diagonal shape. with slips only ever being by one pixel, which the user is unlikely to notice. The problem here is one of scalability. Checking every object against every other project for every pixel traveled is painfully inefficient once there are more than a hand full of objects.

And this is the meat of the problem and the point I wanted to make with that tweet. Collisions are n squared no mater how you handle them. Every object against every other object. Almost all the well known techniques are made to make the check simpler, or reduce the number of objects considered: only check the collisions with moving objects, combine walls in a row or column into a contiguous object, only collide with certain types of objects, narrow the field with quad trees (or oct trees in 3D), all just reducing n. Nothing can really fix the complexity of it. No matter how you slice it, it's going to make you cry.

And what I've ben working on doesn't really do much better, but it does aim to be an improved version of the simple iterative method, only checking the space at the necessary level of detail. It's gone through a couple revisions since the original idea of expanding the above, below, left of, right of test, (henceforth ABRL) breaking each line into a combination of a sloped line and a vertical or horizontal section as shown below.

At the outset this seemed like a clever idea, setting up 4 tests for each motion, then running every object against them to basically use the same technique, but accounting for the motion of the object. The tests of course would have to be generated for each moving object (or subject), but that wasn't the killer. The problem was deciding weather to measure each the other object against the slope or the orthogonal portion of each side. This was easy if this was the only case, but invert either the x or y direction and every one of those tests would change. This led to an if tree that got about 4 layers deep and differed only in the very fine details from case to case, making it extremely difficult to generalize, and really hard to write bug free by hand. A wise man once said that good programmers are lazy. If something looks like it's going be a gigantic pain in the ass in which you have to fine tune every little detail, you probably aren't using a very efficient method of doing it.

I briefly hit upon the idea of using vector math to rotate all objects about the origin until the situation mirrored the one case with a positive x and y shown above, this may still be a viable idea, but the process of rotating all the objects changes the relation between their width and height and the origin of the object, since that origin may be in a corner other than the top left. There may be a smart way to deal with that, but I was starting to see another giant if tree forming and decided to back up and rethink the entire strategy.

Having shelved this for a while, I looked it over again after my last post, vowing to complete a project, any project, and a good collision library has been a sorely missed asset in my various jam projects, so it seemed like a good choice to get myself up to speed with again. (Yes I do realize that almost 2 months have passed and I really need to focus on that speed part.)

I went back to the iterative solutions and came up with a three level collision check. On the first level, I check one box containing the initial position in one corner, the final position in the opposite corner, and everything in between. This is over checking by a lot, but it is only here for two reasons: one, find out if more detailed collision checking is necessary, and two, narrow the list of objects that might be crashed into to only those which collide with this box. This way, later checks with very little movement between checks, will compensate by having very small lists of candidates.

The second level moves the object moves the object by unit differently depending on its velocity. If the velocity has an x component of greater magnitude, the object moves based on its width, otherwise it moves based on the objects height. Whichever is chosen is considered the primary length, while the other is the secondary length. The idea is to define a series of boxes with the original position once again in one corner with the opposite corner containing a new position that is moved one primary length forward in the primary dimension, and an appropriate distance in the secondary dimension according to the velocity. This way the box encompasses this step's actual covered area and the box around it the same way the first level did for the entire trip. If there is no object in the box to collide with, the destination becomes the new origin, and the process repeats.

If a collision was detected, the method goes back to the tried and true, move the object along its course one pixel at a time until a collision is detected. If no collision, go back to level 2, if there is a collision, then there was a collision and the object, or objects detected are returned as the result.

I could go into more detail about the inner workings, but I think it's all better explained by this visual debugging program which I build to develop it. The blue box is the subject. Move the mouse and click to test a final position. The box moving with the mouse is the intended final position will be green if it made it there without colliding, and red if it did not. The pink sections are the collision boxes used in the section of code that returned the result. Level one collision boxes are not shown. The lines that can be collided with will turn red if they were considered in the deciding check.

Download test page at:
https://github.com/Lambwatt/CollisionSys/blob/master/debugCollisionDemo.html

As you can see, the last collision box in level two can actually extend beyond the final position. I intended to specially handle this edge case, but it turned out to be rather problematic, and it didn't seem to be having problems with it anyway. The reason no new problems emerge is that the level 2 checks only check the results from the level 1 check, not the global list of objects. This means that an object colliding with a level 2 check but not a level 1 check is actually invisible to the level 2 check so it doesn't cause any errors.

It's not a pretty algorithm. It's a bit more convoluted than I intended and it uses a lot of complex return values, (objects sent back with companion data to the intended return value), and it isn't sophisticated enough to handle hit boxes being on an angle. But for most of the games I would be making at jams, this is sufficient without requiring any new infrastructure around it, like a quad tree implementation, and works well enough even with a huge number of objects flying around the screen. And my real criteria for success was to be able to hold a bunch of objects with 1 pixel thick walls. As shown in the demo below (press and hold the left mouse button to advance time.), I believe I've done that*.

Download demo at:
https://github.com/Lambwatt/CollisionSys/blob/master/stressTestDemo.html

All code related to this project can be found at https://github.com/Lambwatt/CollisionSys.git

I'm Michael Pattie, and this day <checks calendar> 53.... damn.

*The demo piece hit some weird cases with particles below about 6 pixels by 6 pixels and completely breaks for 1 x 1 particles, however these seem to be more related to the less well thought out way in which I resolve collisions than a failure to detect them. I decided what I had was good enough for me to move on. It's time I got back to a certain other project.

Thursday 1 May 2014

Lambwattage 2.0

Greetings interwebs,

I've been pretty quite lately, and for that I'm sorry.

I also didn't do that thing I was going to do, and I'm sorry for that too.

What thing you ask? Pick any one you want, this blog has basically been one long string of broken promises. (Except the hair thing. It remains uncut.)

I want to promise that will change tonight, but I feel I've lost my credibility.

Nevertheless, tonight IS different. Up till now, I've been a student. My life came in 4 month blocks, each its own fresh start. Each time I swear I'm going to get more done, and each time I have failed. But tonight is different.

The last two terms have been a co-op in Vancouver. I liked the job and they liked me enough to hire me indefinitely. Today is the first time in 6 years that there is not another semester coming. Of course if you count high school and elementary school, then it's been nineteen years all together. 19 years of another fresh start just around the corner. but not tonight. From now on, some other institution is not sending me things to learn nor burning up my off hours. The learning, the teaching, the work, and the motivation will only come from me.

I recently saw "The Wind Rises," an anime about an aviation engineer as he creates the Zero fighter amongst the political turmoil of the twentieth century. He is told at one point that an engineer has 10 good years before he becomes old and useless. The count started from the day he graduated and he is told to use them well. I am also an engineer, and as of today I am no longer in any form of school. My ten years start tonight.

I want to use my ten years well too, so I'm dusting off this blog and trying to buckle down again. One last fresh start. No more mulligans.


This is Lambwattage 2.0,

I'm Michael Pattie, a software engineer and game designer,

and this day 1.

Friday 24 January 2014

On The Dangers of Creepy Pasta

Good morning(?) interwebs,

So I'm writing this stream of consciousness style while sitting in bed at 3:30 in the morning because roughly an hour ago I listened to a creepy pasta story and wanting the benefit of actually sleeping without the cons of having to have my eyes closed or dreaming. In order to get myself more comfortable I have been watching a bunch of Ze Frank and TED talks, but this has only led me to hear my own thoughts in Ze's voice and phrasing. Not a terribly good sedative, but a great motivator to go blog.

I've been allergic to horror in pretty much all forms since I was a kid. I didn't go near it except when I saw pieces of it accidentally while tuning in for something else. And I wasn't even comfortable with the tame kids stuff, I was uncomfortable with "Goosebumps" and "Are you afraid of the dark?", the latter probably owing to the fact that I was, and still am. sort of. It mellows out most of the time, but when I've seen something that disturbed me, I find it comes roaring back and I need the lights to always be on around me. That and opening closed doors to dark places becomes a terrifying experience as I picture what might already be detecting me on the other side and preparing for an ambush in that first blind moment.

As I've gotten older though, It has become more manageable. Much like pain tolerance, the familiarity of the sensation and the perspective of more intense emotions allows me to ignore it more easily. I find myself remembering a comment by Susan Arendt about watching a lot of horror movies and playing horror games, and finding that over time, they had a sort of inoculating effect. Confronting horror through experiences that are intense, but ultimately safe. The mind gets used to these feelings and is therefore better to manage them in the real world.

And in relating this back to games, I thought about a classic game design skill: learning through analysis of your own emotions. It's tricky to do, since you need to thing about what you are feeling and why at the moment when you are feeling it, and you still have to have be feeling it at the same time. But if you can get good at it, it's a great way to study experiences in all forms and figure out what about them is compelling or off putting. And I find this has also been the technique by which I manage this fear. As I'm walking down the dark hallway, which I know is empty even though my mind keeps conjuring things to be in it, I am aware of my fear of the dark, the things my mind is conjuring and the physical sensations. And that helps me label them and put them in a box to study instead of feeling. There's a kind of distancing there, as if I am in fact in a horror movie, but my consciousness is outside sitting on the couch, watching it all on a screen and knowing it is a movie and not real.

The whole thing also reminded me of a conversation from earlier today. (or yesterday I guess.) One of my co-workers children was getting shot, and the nurse was surprised to see the child intensely, and calmly observing the shot rather than looking away or crying. Here to there seems to be a calming effect from observation. I think it's a combination of increased apparent control and distraction. Now that you are observing, you expect that sensations will soon be traveling to your brain and you will need to pay attention to them and make mental notes. This sort of observation and distraction can also bee seen on those unfortunate occasions when you need to remove a sliver from your skin with a needle. Not being a surgeon, I find i usually tear up the area of the skin with a lot of misses, but the experience doesn't feel anxious because I expect the pain, and as the source of the pain, I can stop damaging myself at anytime.  On the whole, it's a far less distressing experience than  having the same thing done to you by someone else.

I think I've gone on long enough with this, but before I go, I should probably explain why I am still awake and watching youtube videos this late. I left some personal project work to this point in the week, still hoping to sneak most of it in before friday when the global game jam starts. Then I realized this morning that my evening was already occupied by an event I'd almost forgotten about. When I got home, I still wanted to get it done, so I downed some tee to stay awake and got down to work, by which I mean watching youtube videos with the attention of working at some point. And then I came across the aforementioned pasta, and the rest I've told you.

This was fun, but I really need to get to bed. Good ni............