Monday, February 28, 2011

Isometric progress #4

Added another resource: tiredness. Doing nothing increases it slowly, programming increases it faster. Sleep decreases it. Also if you are programming while really sleepy, the chance of making mistakes becomes higher.

Isometric progress #3

The engine itself is still pretty buggy and I'm missing a lot of tiles, but it's now possible to walk (ok, slide) to the computer and start writing code. Time passes and the lines of code written increase while sitting.

Minimum viable Jones

One of my favorite games is Jones in the Fast Lane. It's a life simulation about work, education and money. There's a variety of interesting decisions you can make in the game, such as is it better in the long run to eat at McDonald's every day, or should I buy a fridge and shop at the supermarket instead? There are 13 places in the game that players can visit, each with important functions. Or how important are they really?

I took another look at the game, this time with this design question in mind: how much could you take away from the game, while still allowing for some gameplay to happen?

Jones in the Fast Lane

Playing it again while trying to avoid doing anything except bare necessities, the minimal gameplay experience is:

- Wake up at house.
- Go to employment office to get a job at hamburger place.
- Go to hamburger place. Click on "work" until run out of time. Eat.
- Sometimes go to employment office to check if I qualify for the next better job yet.
- Repeat until boredom.

So out of 13 places, only 3 are actually necessary for at least 5-10 minutes of gameplay.

This gameplay can then be extended by adding requirements like having certain type of clothing before being allowed to work at the next job level, which then introduces the clothes shop into the game. In this way elements could be gradually added to extend the time before player gets bored.

I believe adding things gradually is the path for sustaining motivation while building a game. Doing all of those 13 buildings at once would be demotivating, and I imagine also more difficult to balance.

Isometric progress #2

Been adding more tiles. Realized I need layers to avoid having to create every combination of floor + things on the floor. Putting off coding them until I have some idea what I'm really going to use this stuff for.

Joined #gamedev on freenode, started reading r/gamedev instead of my usual Hacker News sometimes. Noticed many people seem to make a tile engine but never progress anywhere after that. This alerted me to the need of adding some gameplay asap.

Saturday, February 26, 2011

Isometric progress

Scrolling works, there's sprites and tiles can be set with mouse. Latest breakthrough is that now pathfinding works. Just simple breadth-first search, but seems to be fast enough for small maps.

Had a graphics-related realization that I had been unconsciously holding the belief that scales have to be accurate. My grass looks like noise because I figured that's how big the blades of grass really are relative to my characters. But when looking at other games, I noticed that the graphics is more symbolical. You can show huuuge blades of grass if that lets you show more clearly that yes, this is grass. Screenshot from the game Sunday Lawn from Donut Games:

Some blades of grass here are as big as the character's leg, yet it looks fine. I think I'll try to change my grass to something more similar to this game, with individually visible blades so that I can show the direction of the light in them.

Friday, February 25, 2011

Isometric sorting flaw

I just realized there's a flaw in the way I was attempting to sort display objects in my isometric code. If the graphics of the tile is a thin wall to one side of the tile for example, then it's possible to walk so that it appears that the character is in front of the "wall", instead of behind.

This is because the tile graphics is just graphics to the engine. It doesn't understand that it implies some geometry to the viewer.

Works when wall-graphic tile is in (0, 1) and player is in tile (1, 1).

Fails when player is inside same tile (0, 1) and base of player is lower, so assumed nearer and sorted "wrong" (although depending on the graphics it could be right, for example if it's a picture of a tree instead of a wall).

I don't have a solution yet. More discussion about this issue on flashkit forums.

Thursday, February 24, 2011

Generating leather procedurally

Subdued textures are all the rage now in app visual design. I've been making mockups for a simple financial app. To indicate wealth, I figured a leather texture would be suitable. Leather is expensive, and also associated with money because of wallets. Not having much luck in making good use of any leather textures in my screen design, I started getting interested in the material itself.

What would it take to generate it with code? So there are some kind of cells in there, competing against each other for growth space. What would the algorithm be like for this? First come up with "birth points" for the cells. Here's my initial javascript simulation of it. Pick a random point. If no cell nearby, put one there until no more space is left. After the positions have been picked, adding a bit of randomness can lead to more interesting shapes later.

Each cell controls all the pixels nearest to it.

To emphasize the borders, for each pixel I checked about a hundred random nearby pixels and saw how much competition there was around that area. The more competition the darker the pixel. Unintentionally I got subpixel-accuracy rendering too, since this is a stochastic sampling method. The result is a greyscale picture I can use as a height map for the cells.

procedural leather heightmap

Next I opened the javascript-generated height map in Gimp. To make the top of the cells rounded, I made a copy of the depth map and did a gaussian blur on it, then grain extracted it from the height map. I used emboss and a gradient to shine a light on it, then adjusted the hue / saturation / lightness to get it to appear more leather colored.

leather texture

That's my version of leather. While researching about this, I came across an interesting Wikipedia entry on how leather was tanned in ancient times (it involves urine, feces and brains). I also ran across a cool article about how this cell-style procedure can be used for procedural computer game map generation.

Wednesday, February 23, 2011

Tokyo Subway Map

I simply wanted to know what the Tokyo subway map would look like if I look up the location of every station and connect them with lines. I used the same line colors to make comparison against an official map easy.

Official map from Tokyo Bureau of Transportation:

Real physical map of stations by yours truly:

I've learned several things while doing this.

- Physical map of the subway is almost nothing like the conceptual map published by Tokyo Bureau of Transportation. The conceptual map is more of a graph visualization than a map. It spaces out the stations so that they beautifully fit the space, while keeping out of areas that would be in the ocean or the imperial palace gardens.

- In the conceptual map, angles only change in 45 degree steps. Direction of a line can even change from going north-south to west-east if that makes the stations fit better (look at the salmon colored line at the bottom).

- Even individual subway lines aren't lines. Sometimes they have branches. Sometimes a branch connects back to the main line. So subway lines are actually graphs themselves.

- In the conceptual map, non-underground stations (private railways / yamanote line / arakawa street car) are also displayed, but they get a tiny symbol. Second largest symbol goes to metro stations that only connect with one line. When multiple lines stop at the same station, they get a big box with stopping lines listed inside of it.

- For the lines with 4 or more connections, the lines listing box can take more advanced blocky shapes if that makes it more easy to visualize. If there's an underground passage between nearby stations, that is shown as a connection between the boxes.

Tuesday, February 22, 2011

Thief Tower

I was making a social platformer game called "thief tower" last october. Somehow I abandoned it, even though it seems pretty promising. I should figure out how this game could work and continue on it.

Monday, February 21, 2011

Farm mouse

Now that I can calculate which tile the mouse is moving over, I'd like to think a bit about how mouse interaction in general should work on the tile area. I like looking at Farmville as an example, because it shows what is "good enough" according to a hundred million people.

I can see that the mouse is used at least in these ways on the area:

- Buttons overlaid on the tile area can be clicked and take precedence. The buttons can be any graphics, not just rectangular areas.

- Tiles can be clicked and have tile-specific behavior. However in FV the graphics of the tile define the clickable area, not the base of the tile. This means that if a high structure is in front of a back tile, that back tile cannot be clicked at all. Somehow in practice this doesn't seem to happen though, I suppose no tiles are that high.

- Clicking on a tile that has no specific behavior causes the character to move there. Movement seems to be happen in world space instead of tile space. The character moves towards the clicked spot in a bit of a random stagger, somehow still managing to avoid walking through buildings. There are such few buildings in the game that instead of pathfinding, perhaps being on top a building simply pushes the character away from it.

- Moving characters can be clicked too.

- Level can be dragged.

- Mouse cursor can change to indicate what kind of action clicking would do. In javascript this can be done by setting style.cursor.

There's also zooming, which I haven't thought about at all yet.

Isometric math

I have some basic code working that draws an 8x8 isometric area with no support for anything yet, except embedding. Here, I'm attempting to embed it below:

I ended up having three coordinate spaces. One is the world space, which starts at (0,0) and grows like usual, woX increases 1 pixel to the right, woY increases 1 pixel down. Then I have a "window space", which is like world space except it takes scrolling into account. Then there's tile space which also starts at (0,0), I'm calling the basis U and V, which hop from one tile to the next.

All I had to do so far was to transform between these spaces and figure out how to set the window transformation so that the tile area would be centered.

I still feel unhappy about how to store the tiles. I don't want to specify the center point and extents for each tile by hand, but how else can I cut them out from a sprite sheet?

Friday, February 18, 2011

Isometric thoughts

Next I'd like to accomplish a small test where the grid of isometric tiles is shown and mousing over a tile causes it to highlight.

I'd like to create a kind of component that would be easy to continue from in future tests. For language I'll be going with Javascript, as for me it has the fastest cycle between writing some code and seeing if it works or not. It should be totally trivial to include an isometric field of tiles in a project, otherwise I wouldn't use it. To get an isometric hello world, I should be able to copy some piece of code, similar to copying AdSense ad codes and it should just work with reasonable defaults.

The code to copy should be something like <script src=""></script>. Putting this on the page with nothing else would magically create an isometric field right there. That would also be convenient for demonstrating things here.

What kind of parameters would an isometric field need? At least some sort of description of how big each tile is. The ratio of the size is always 2:1 in my perspective, so just giving the width of the diamond should suffice. Then it should know where the graphics for the tiles are. Maybe this could be given implicitly by having the name of the graphics file be part of the name of a tile, like "car_4" would mean the fourth tile in the file "car.png". There might be big differences in the size of tiles though, so unsure how to know where they are in the file.

Size of the playing field and initial position of the window to the playing field are important too. Maybe assume 8x8 like a chess board and have the initial window be such that it would show that board reasonably.

Since there is "screen space" and "tile space", there will be two coordinate systems.

Screen space is the usual. Basis is x=(1, 0), y=(0, 1). In tile space it will be u=(width_of_tile/2, height_of_tile/2), v=(-width_of_tile/2, height_of_tile/2). To know which tile the mouse is over will involve first translating the mouse position from the current scroll position so that it's in the world position, then a change of basis from screen space to tile space.

StackOverflow had a pretty nice QA about this too

Thursday, February 17, 2011

How to Make an Isometric Game Engine #3

Previously on "how to make an isometric game engine". Confusion ensued as guy floated over some shrubberies, instead of being between the bushes as laws of physics demand. And now, the conclusion. To that one problem.

Think about what the correct drawing order should be. I claimed before that it is to draw each row, starting from the back coming to the front, in the order as indicated in the picture below.

That does happen to draw the tiles in the correct order in the case of this tile engine, but generally what should happen is that things in the back get drawn before things in the front. And depth here depends on how high the tile appears on the screen. The red block is the highest, so it should be drawn first. Next are the yellow and green tiles. The violet block is lowest, so it is drawn last and appears in front of the others.

But wait a second. The yellow and green tiles were equally high. Doesn't that mean that we could actually draw them in either order? Yes, the opposite order works just the same:

This works for the movable characters too. We can put the guy and the tiles in the same list of things to draw on screen, then sort that list such that the highest item is drawn first, then proceed to draw them all. This way the drawing order will be correct. One exception is that if characters float or jump, that height should be added after sorting to maintain correct order.

When it is time to draw things, the difference between a tile and other graphical objects no longer matters. After the tiles have been moved from the tile array to the sorted display list, they are just the same. For the game logic it might still be convenient to have the array though, as it can be necessary to be aware of any special meaning of the tile the player is over, such as is walking through the tile possible.

How to Make an Isometric Game Engine #2

Continuing from my last post, I am now going to ruin everything. Last time I said a simple 2D array would suffice for representing an isometric level, and things would appear correctly by just drawing them in the order they are in the array. For some games that might be ok, but in most cases it isn't enough.

Suppose you have a character that can smoothly walk from one cell to another.

This naughty red shirt isn't in his tile! Well, no problem you think, I'll just have the mobile characters separate from the underlying tiles. First draw tiles, then draw characters. Which works great when the floor is totally flat, but when you start having tiles that are a bit higher, like these bushes here, this happens:

The character should actually be drawn between the tiles, but now he seems to be floating in air. Your first thought might be to figure out which tile the character is in and draw him after right after that tile. The problem with that is that the drawing order could still be different if he is slightly behind the tree.

One possible solution to this in the next post.

How to Make an Isometric Game Engine #1

What does Civilization 3 have in common with Farmville? For one, they are both isometric games. Turns out many popular games use this style of graphics. Unlike perspective graphics with a vanishing point, in isometric games the world consists of isometric tiles which are laid evenly to build game levels.

It looks very simple. First of all, how would you represent such a level? That's easy you say, just have a two dimensional array of values. Each value represents what kind of tile there is in that space. Just like in a 2D tile-based game seen straight from above, X coordinate could increase to the right and Y coordinate down, except at a slight tilt.

This is not the only possible coordinate system of course, but this way the tiles can be drawn in the traditional loop of increasing X and Y, and still occlude each other correctly. That's it then? All the complexities of an isometric engine solved. Not quite.

To be continued...

Good morning

Woken 4am by a dream; iOS app devs stalking in the night with flashlights to discover each other's app development secrets. Munched on a peanut butter sandwich watching Dragon's Den. Morning ideas. There don't seem to be any good cave flying games like Auts / KOPS for iOS even though it seems suitable. Walked to convenience store for more coffee. Idea on the way. It's difficult to get backlinks for niche blogs. Maybe a sort of link trading scheme could work where blogs could get points for introducing other blogs. Maybe spin it as a social network for blogs, where your blog can friend another one. Sort of formalizing what blogrolls already are. Probably wouldn't work. Finally waking up.

Monday, February 14, 2011

Slow progress

Low point. Writing this to gather some energy again to make progress. I've been reading my own past blogposts, re-read my post about my $100 / day goal and my fantasies of creating some sort of survival game. I've made some progress towards each, but nowhere near enough.

On the game front, as you can see from some previous posts I made some progress in learning how to make pixel art. It's not that great, but to me it seems like acceptable art as long as the gameplay itself is interesting. At least it could serve as a placeholder until in a later version it could be replaced by something made by someone more focused in creating art. Re-read my post about what type of game I'd like to create. Very vague and about a few lightyears away from being a real concept of anything, but I still agree with myself that the direction / general themes I describe are still interesting to me.

In the income side I'm currently doing something like this:

$0.25 / day total from 2 paid iOS apps
$0.25 / day from 1 ad-based iOS app
$0.33 / day from Finnish-language guide to Tokio
$1.70 / day from HeartBooth which I launched a week ago
$1.00 / day from Coolest Friends

~$3.53 / day

My goal for 2011 is to reach $100 / day, so really far from that still.

What should I do to progress? I think I need to find ways to take small steps, like releasing small games that would as a side-product generate art assets that I could then use in bigger projects. However I'm skeptical enough about the chances of making any revenue on really small game projects that it's preventing me from trying. I feel pulled towards releasing social sites / more everyday tools for iOS since it's easier to picture those making money. For example I recently had an idea about making a start-up equity investment simulator for start-up founders to see how their stake in their company would evolve as it goes through several rounds of funding. I could imagine such an app to sell some copies even if pretty expensive, but I'm not sure it would take me any further on the game side.

Friday, February 04, 2011

MetaExtension part 5

isometric shower

Shower is a great time for uninterrupted thought. Today's shower thought was "Wait a minute, I have Facebook connect and through MetaExtension I can get access to peoples' list of installed extensions. Why not add an option to share the list with friends?"

I don't think I ever made any money from my shower ideas though, probably just wasted water :-)

Mailprop #2

What happened to my Mailprop idea? The idea was to get businesses subscribed to paid newsletters that customers could use to request goods and services from them. So for example companies in the promotional products industry could subscribe, and then whenever a customer uses the Mailprop form to request a quote on for example a large order on t-shirts or a pens, it would be blasted out to all the subscribers, who could then contact the customer back if they want.

Well, to see if the idea would work, I put it online and got some adwords to promote it to customers and businesses. I started with Finnish businesses in the promotional products industry. I kept the customer-side adwords up until I got one lead. Then I contacted several companies about the lead, each personally through handcrafted emails. It made me feel miserable to bother people with emails, I contacted 8 companies and managed to get the requested products to the customer, but was disappointed that I could only convince one person to subscribe to the newsletter.

Through the adwords I managed to get two more subscribers, but then they dried up and I haven't gotten any since then. I'm not really willing to do email rounds again, since it made me feel pretty bad to bother people like that, even though it did bring valuable business to them and helped the customer too. One advice I got on Hacker News was to start a niche blog about the industry and find customers that way. Well, I tried it. I started a blog about the promotional products industry in Finnish (Yrityslahjat) and wrote several blog posts for it. I did some simple research and spent about 12 hours writing pretty good quality posts and scheduled them to be published weekly. I have enough written to last until March.

But again I was hit by the simple inability to just get anyone to know about the blog. It ranks for the finnish term for promotional products "yrityslahjat" on the second page in Google already, but since it's an industry with only a few players in a very small country, I'm just not getting any readers for it. With no readers obviously I can't convert any to subscribe to the mailing lists either. So this idea is on hold until I can find some non-annoying way to get more people using it.

Tuesday, February 01, 2011

MetaExtension part 4

I managed to release the first version of MetaExtension before perfectionism got to me. install it from Chrome Store