Making a shop background has been difficult for me. First of all, I lack the drawing skills. Given an hour or so, I can do a decent job at realistic sketches, but comic-style drawing is what matters for games. After many, many false starts, I got a mediocre shop sketch done. I put a (hopefully) greedy-looking pig merchant in the front, a bookcase with blocks in the back and various low-tech shop stuff in the background. After taking a picture of my drawing with a digital camera and uploading it to my computer I went to Aviary, a web-based art-suite. It's not as powerful as Photoshop, but it's no slouch and it doesn't cost hundreds of dollars, either. I used the vector app to create polygon-based shapes on top of my sketch. Here's what it looked like part way through:

After finishing, then I saved the file as a png, and opened it with Paint.net to do the coloring and the details that had to be drawn. This process took me forever. Part of the problem is that I was using a mouse instead of a tablet, but I think most of it was just various rookie errors. Never resize stuff before using the paintbucket tool. The shapes will leak! Also, There were some serious perspective errors. Erasing and re-drawing huge chunks of picture really sucked. Next time, I'll try a lot harder to get it right with the vector based shapes at the beginning. I'm not completely proud of the final project, but I think it's better for my learning to just finish it and then be able to work on the next project sooner.

As far as I know, rotation in all the classic block games such as Tetris or Blockout was done in about the same way-- by storing an array of values for each of a block's possible states. For example, a long block in Tetris would have been stored something like the following. In its default rotation, it's horizontal with the following coordinates: [0,1], [1,1], [2,1],[3,1]. In after rotating clockwise, it's vertical like this: [1,0], [1,1], [2,1], [3,1]. The other two rotations would just be mirrors of the first two, so the entire block data could be stored in a multi-dimensional array like this:

rotation = 0;
L = [
  [[0,1],[1,1],[2,1],[3,1]], 
  [[1,0],[1,1],[2,1],[3,1]], 
  [[0,2],[1,2],[2,2],[3,2]], 
  [[2,0],[2,1],[2,2],[2,3]]
];

Then the variable L[rotation] would return the coordinates of L in whatever rotation it happened to be in (in this case [0,1], [1,1], [2,1],[3,1]). Rotating blocks is very quick this way, but the downside is that rotational info has to be manually inputted for each block.

Since the block game I'm making isn't just a tetris clone, and I want to have a shop in in where players can buy or maybe even design their own blocks, I've decided not to use this method. Instead of entering everything in by hand, I'll use math and let the computer do the work of coming up with the transformations for each block. 2D rotations are a simple 2x2 matrix multiplication, and 90 degree rotations are even easier than that. This way, each time a piece is rotated, the locations of its constituent tiles will be updated by a matrix multiplications.


Problems

1) Matrix multiplication is very slow compared to an array lookup. I can live with this. It's not 1985 and there will only be one block being rotated at a time anyway.

2) Repeatedly rotating a piece can make it drift until the coordinates of its squares are hugely positive or negative and further rotations just make it orbit around a point instead of just rotating in place. This was really annoying. I fixed it by making the 2,2 location the "center" of each piece, subtracting [2,2] from each tile's coordinates before doing rotation multiplications and then adding [2,2] back to them after the rotations. This fixed the problem with a couple of caveats. Pieces have to be created such that rotating around their 2,2 point looks reasonable, and...

3) Some pieces should just stay in place when they rotate. A 2x2 square is a perfect example. Yes, I could just have it rotate around whichever of its four tiles happened to be at location 2,2. It would look stupid, though. The center of the visible part of the piece isn't on any of its constituent tiles, it's between them. I solved this problem by allowing a property to the block class to state that rotations should do nothing. I'm not 100% satisfied with this, but off the top of my head I can't think of any pieces that must transform when rotating and yet would look bad rotating around one of their constituent tiles.

Here's my rotation function for my block class. Note that shape is an array in the block class that holds the locations of a block's tiles:

function rotate():Array {
  var xoff:int = 2; // every block will rotate around 2,2
  var yoff:int = 2;
  if (rotatable == false) return shape; //rotation doesn't change this shape

  var newshape:Array = new Array;

  for (var coord in shape) { //use 90 degree matrix rotation [0 -1]
                               //                              [1  0]
    newshape[coord] = new Array;
    newshape[coord][0] = (shape[coord][1] - xoff) * -1 + xoff;
    newshape[coord][1] = shape[coord][0];
  }
  return newshape;
}

I ran into some problems with handling the block sprites. I was basically just using the same built-in .x and .y properties built into flash sprites and adding some number to currentBlock.y in the event loop for gravity, and either adding or subtracting from currentBlock.x when a direction arrow was pressed. The problem with this was that it made collision detection a pain, and it also raised questions like what to do with a block partway between two square locations. In a game like Tetris or Blockout, the squares of the playing pieces have to fit into the squares on the board.

The way I decided to fix it was this-- give the block class getters and setters for x,y coordinates in terms of the grid of the playing area, not in terms of pixels on the screen. I made all animation in discrete 1 square increments and this also made collision detection much easier. Here's the top of my block class:

public class Block extends Sprite {
  static const size:int = Board.gridSize; //size of the board's "squares"
  static var list:Array = []; // for keeping track of all the blocks

  var edge_color:int;
  var inner_color:int;
  var shape:Array;
  var type:String;
  var _gy:int; // the y position in grid squares rather than pixels
  var _gx:int; // the x position in grid squares rather than pixels
  var _gwidth:int;
  var _gheight:int;

And the getters and setters for the grid variables:

function get gy():int {
  return ((this.y-Board.top)/ size);
}
function set gy(gy:int):void {
  this.y = gy * size + Board.top;
}
function get gx():int {
  return ((this.x)/ size);
}
function set gx(gx:int):void {
  this.x = gx * size;
}

With the convenience of these getters and setters, along with a few others for width and height of pieces in terms of grid squares, it made animation very easy. I didn't need to refer to x,y screen coordinates again in the block class and could just increment or decrement currentBlock.gx or currentBlock.gy by one to move a block one square. Collision detection was similarly simplified. Instead of needing to use hitTestObject() as I did in the other two games I've made, all that was necessary was 2 dimensional array of the playing grid, filled with zeros for empty locations and ones for locations with a block. Then, before moving a piece, I just check to see which grid locations the piece would occupy and not allow the move if they're occupied. For example, If I had a long thin piece occupying squares (5,4), (5,5), (5,6), and (5,7) then all I'd have to do is check (6,4), (6,5), (6,6) and (6,7). If all of them are unoccupied then I can increment currentBlock.gy and move the piece. Moving left, I'd check (4,4), (4,5), (4,6) and (4,7).

In retrospect it seems obvious that a grid representation would be the way to go for a game with pieces and a playing field broken up into discrete squares (or cubes for blockout), but it wasn't the first idea I had.

I didn't get much programming done in November or December. I did pick up a copy of The Land of Lisp, which was awesome. I'm not quite sure it was ideal for a beginner such as myself, seeing as I used nothing but the REPL for two weeks not knowing I had other options and found myself bogged down about 40% of the way through. The author's enthusiasm and ability to make interesting exercises out of so many otherwise dry activities was great. I may return to the book later.

One reason I didn't do so much coding was the fact that all of my acquaintances here in the Beijing hostels seem to have social lives that revolve around drinking at bars. Some of them are great people... but you really don't have much to show for a late night at a bar the next day, except maybe some good memories. For that reason I think it's much better as an occasional event than a regular way of life. Tons of my buddies in Taiwan loved to drink, but the two groups I regularly met up with were centered around either strategy board gaming or outdoor endurance sports. Surprisingly both groups included a lot of computer people and some artistic people as well. Beijing is a big city, though, and I'm sure those people have to be around, with the possible exception of the distance runners.

Another thing that slowed me down is that my Chinese classes got way tougher than they had been before. Our teacher is great, and she's willing to regularly correct our essays, but that means we regularly have to write essays. Even now, I've got all kinds of non-standard Taiwanese phrases and the occasional traditional character popping up in my writing. I guess it's a good thing to have a teacher tell me though. I must have said 綁鞋帶 a five or six times since getting to the mainland instead of 系鞋带, but nobody pointed it out to me since they could all understand me... and that's just one of hundreds if not thousands of phrases I've got a little bit off.

One area in which I made a great deal of progress was drawing. Somehow, and I don't even understand how myself, I went from barely being able to do anything realistic to being able to draw a decent portrait given enough time, or a potted plant in 15 minutes or so. The aspect of this that surprises me most is that absolutely nobody helped me at all with it. I literally just got on google, searched "learn to draw" and took it from there.

Right now, I'm feeling energized. I've had time off from exercising the coding part of my brain and now I've got the desire to go at it again. I'm going to start working on that game like Tetris with a shop.

It's a little startling to notice that a month has gone since my last entry here and I haven't made any real progress on my quest to become the programmer I could have been a decade ago. Naturally this less than thrilling progress assessment leads to introspection. Here are some of why I haven't done any programming:

I've been spending time studying Chinese in the mornings -- I don't want to solve this... not now. Due to the massive Taiwan/Beijing regional differences, I'm learning more words faster than ever before and I'm actually getting to where I can almost write normally in simplified. Getting used to reading it was a pain, but writing is a joy.

I've been working out 3 afternoons a week -- Taking at least some care of myself is important. I've started taking an iPod to get some learning done while I'm at it, though.

I've been trying to teach myself to draw. It was flash games that drew me to it, and it's also a really cool life skill I'm determined to have eventually. It's really slow going, though and maybe I should put it on the back burner until I'm actually making money from something (my last few projects have died down).

It's hard to program in this little Beijing hutong hostel where I'm living. There's no desk in my room and it's cold enough in the courtyard that I have to wear gloves and type slowly. I could move. I'm planning on it actually, but most landlordspeople in Beijing really want to rip off non-Chinese. As a result, it's a long complicated bargaining process that often ends in me walking away from a bad deal. I've found a good-enough place, but the guy living there won't be out for another month or two.

Random other stuff keeps drawing my attention away. For example, I've started learning Swedish. I'm not sure why, but I felt supremely motivated to give it a wing a couple of days ago. This will probably pass within a week, but then it will be Chinese ktv or dancing or some other thing thing I've long been drawn to. Those kinds of things are great for the social life, but they don't exactly lead to prosperity. The world, especially the modern world, rewards specialization and I have to concentrate my efforts to some extent... somehow.

Related thoughts:

Rapid Improvement


http://www.paulgraham.com/wisdom.html

My second flash game is a breakout clone. It should be very familiar to anyone who ever played Arkanoid, Breakout or other paddle games. It's simple in terms of graphics, but it was much more work for me than the side-shooter I made since I had no stock graphics to work from. The collision detection was also a bit of a headache. Since there are multiple levels and score screens, I tried putting them into different frames instead of keeping everything in a single frame as I had in my first game.

It is a little disappointing to have taken so long to put this online, but life has been busy. My distractions have included moving to Beijing, making a visa run to Mongolia, fending off a beggar who tried to rob me, getting started on my HSK prep classes and a really cool girl I've recently met.

Anyway, the game is up on Kongregate now and if you play it there, it's hooked into their high scores api and your achievements will get recorded.
(more…)

Last week, I worked through Kongregate.com's flash game tutorial and made my Urban Defense game in Actionscript 2. It took me a little bit of effort at first getting used to the "Stage", and the onEnterFrame() loop, but all in all I found it intuitive and easy to get going. It took me three days to make the game in the tutorial and add some significant enhancements to it.

Shortly after uploading it, I discovered another tutorial for the same game that used Actionscript 3. I decided to rebuild my game, in AS3. It turned out much more difficult than I'd expected and ended up taking more time than doing the original game had!

The first frustration was that AS3 is more verbose. Seriously, it reminded me of Java, and I am not impressed when someone finds a way to make a modern scripting language feel like Java. Even though I took greater advantage of inheritance than I had in my original game, the source code was 22k vs 17k in the AS2 version.

More importantly, AS3 makes doing a lot of things that I want to do a pain. For example, the code I wrote for handling wingmen power-ups in AS2 made use of being able to check what is on the stage via the _root variable.
(more…)

I've been inspired by Patrick's example, and have decided to share my thoughts and business results as I proceed with this endeavor. Here's the first earnings report:

I recently uploaded my first game to Kongregate, Urban Defense. It was based on the tutorials, and it was an extremely simple side-scrolling shooter game. There are under 5 minutes of game play. It wasn't just what was covered in the tutorials, though. I found some background music to add to it and also coded some wingmen that will join your main ship and help you fight against the alien invaders.

Since I released the game exclusively on Kongregate.com and I used the Kong API, they share half the ad revenue. My portion came out to $2 for the first day. Since the new games always get a bit more traffic, I suspect the lifetime earnings for this game will be under $10. That's not much, but considering I hadn't ever used flash before and I was able to build the game in 3 days, I don't feel too bad about it. In order to make this a self-sustaining enterprise, I figure I need to get about 14,000 plays a day. That would earn me about $20USD/day and cover my living expenses here in China.

I have two ideas for my next project:

1) Maybe I could do a slightly harder game such as a Tetris or Arkanoid clone.
2) Or, I could make further improvements to Urban Defense, such as a more weapons and levels.

I'm kind of on the fence. I might learn faster from making another game, but I could probably make a more enjoyable one by polishing the one I already have.

I've been staying with my friend in Kunming over the past 3 weeks and have really enjoyed the vacation. I was definitely a bit burnt out when I left Taipei. I've lost a bit of motivation as far as my rails project is concerned, largely because it was aimed at people learning Chinese in Taiwan and I'm neither in Taiwan, nor learning Chinese (other than a few character simplifications) at the moment.

I'm not sure what compelled me to do it, but I just started on Kongregate.com's tutorials for making flash games. Ever since Sonia showed me her art work and what she could do with flash a couple of years ago, I've had a bit more interest in the subject. Anyway, Kongregate linked to Adobe's free trial version of CS5 Flash and I downloaded it. It's good for 30 days. Interestingly, it says that Actionscript is an ECMA script. I guess that means some skills I pick up will transfer to Javascript once I get back into the rails project.