06 January, 2017

Making Awesome Seamless Road Tiles With GIMP

In the course of creating a desktop game, I completed the code to process some initialization and present the main menu.  The first menu item is "New Game", and it is the first logical item (in my mind) to set forth the effort of creating the main game map.  With that effort, part of the solution is the generation of the graphics files which contain a set of seamless tiles I can use to create the game world.

The game is a classic Japanese RPG (JRPG)-like adventure that combines exploration and battle.  Like with most JRPG games, there are two modes of play: one that lets the player move around on a big world map, and another that facilitates the action (battles, puzzles, etc.).

In each mode, the game will present a tiled area, upon which the player character can move and so forth.  In this post, I will focus solely on the big world map and how tiles can be made to fit together and present a professional-looking background.

The tiles will be laid out in an orthogonal fashion.  That is, the tiles are shown at right angles to each other and the axes are perpendicular.  In other words, it looks like this:

Figure 1: Orthogonal tile layout


Tiles laid out in this fashion are made seamless when the opposing sides can be fitted together and give the appearance that there is no separation.  This can be done with 3, 4, or even 6-sided tiles, but the most common approach is to use squares.

Figure 2: The seamless nature of game map tiles


From the picture, you can see that there must be some kind of symmetry within the tiles.  GIMP offers a few ways to achieve this effect, but if you understand how the edge symmetry works, it is possible to create seamless tiles with only a simple brush.  Unfortunately, that kind of process also takes a lot of time to perfect, and I would much rather be writing code than spending a year on tweaking the hundreds of tiles I will eventually need.

So, to make a seamless tile, we need to begin with a square canvas.  Open GIMP, and select File>New.... In the dialog, make sure the width and height are equal.  The rest of the dialog options are not critical, but I like to add some descriptive text to the comments and set the background to Transparent.

Figure 3: Blank canvas for tile development


With this file, we can create many tiles, each on a single layer or a group of layers.  Let us now take a look at making a simple tile to represent rows of trees.

I already have a few leaf patterns on my system, so I will use one to quickly draw a top-down view of a tree in the center of the tile:

Figure 4: Tree drawn in center of tile


Now, from the menu select Layer>Transform>Offset... and click on the Offset x/2,y/2 button.  Make sure the Wrap Around option is selected.  Press the Offset button on the bottom of the dialog, and you get something that looks like this:


Figure 5: Tree offset with tool


In essence, the picture with the cluster of leaves in the middle is seamless because there are no pixels along the edges.  However, this is an exercise in making something a seamless tile that may otherwise not be.  In a later exercise, the use of the offset tool will become much more important.  For now, let us complete this simple tile and see how it works to fill a large space in a seamless manner.

Add more leaves in the center so you get something like the following:

Figure 6: Second tree added to center


At this point, we have a tile composed of two tree images that will fit together very nicely.

One quick way to see how the tiling looks is to export the image as a pattern and then bucket fill a large space with the pattern.

You can create a pattern with this image by selecting File>Export As... and save the file as a GIMP Pattern (*.pat) to your Patterns directory.  If you do not know where the Patterns directory is on your system, you can always look in the Folders category under Edit>Preferences.  Once the pattern is saved, click on the refresh button on the Patterns dockable dialog and it will appear in the list:

Figure 7: Patterns with Orchard Green now added (Note the refresh button in the middle at the bottom of the dialog)


I have given "Orchard Green" as the pattern description.  You can see this in the picture above.

To quickly see how it looks, create a new GIMP file with a size somewhere three to ten times the size of the tile, and bucket fill the patten into the window.  Here is a portion of an image showing the pattern I created:

Figure 8: Bucket-filled orchard pattern


As it is, this particular tile is fine for a large background for something like a web page.  However, it is not very useful on a game map, unless your map encompasses the entire screen.  The problem with the tile is that the edges show only a part of a tree and as such will not make a map look very clean.

The utilization of the offset feature, however, shows how we can make something very useful on a map.  That item will be a road.

Below, you will see the set of road tiles I have conceived for the game.  Since they are only rough drawings, they are only used for reference.  Note that there are six tiles which cover the six possible configurations for a section of a single road, without intersections.

Figure 9: Six possible road configurations


The first one we will construct is the horizontal road tile.

In my game world, the main roads are similar to ancient Roman roads with large stones laid atop smaller ones.  For the large stones I will use the Bricks pattern, and for the smaller ones I will use the Crack pattern.  Both patterns come pre-packaged with GIMP.

For the actual drawing process, it is possible to select a brush, paint streaks of a custom brush with varying widths, opaqueness, and so forth, or we can simplify things a lot with the use of masks.  Now, I will not go through the basics of masks, as that information can be found with a quick search through the net.  However, I will describe a method of painting and modifying a mask in such a way that modifications for the six different road types will be simplified and easily modified for different types of environments.

To begin, we erase everything we did with the previous exercise and begin with a single transparent layer.  On this, we bucket fill the entire space with black (HTML:000000).  We then create a new layer group and rename it Masks.  Now drag and drop the black filled layer into the Masks folder.  All the masks we create will rest in this folder as normal, grayscale layers.

The concept of the horizontal road is shown below.  The green border represents the tile boundaries, the brown streak in the middle will be the rocky road, the gray areas above and below will be the small rocks providing an easement, and the yellow background should be easily replaced with grass, dirt, or whatever generic landscape surrounds the road.

Figure 10: Road features


We will use this concept to guide the actual construction of the road.  We will also endeavor to create a mirror-like balance of the graphics so that we can rotate the image and have a vertical road tile, essentially creating two tiles out of one.  Later, we will explore ways to make all the rest of the road tile types with just this one tile.

First, let's see what the brick pattern looks like in the space we have created for the new tile.  A few guides have already been added to facilitate our process:

Figure 11: Tile with unmodified brick pattern


A quick look at the pattern shows two rows of bricks that appear at approximately the center of the tile.  Capturing the two middle rows of bricks to use as the large rock portion of the road makes sense, and so guide lines were laid down at 94 pixels and 162 pixels, allowing a reference for the approximate separation of the large rocks from the small rocks.

Although the pattern tiles smoothly with the bucket fill tool, the edges do not come together clean when we copy this tile and paste it into a larger picture, simulating the process of laying out the tiles in the game.  There are a few ways to fix this, but the simplest one we have for a pattern like this can be found by selecting Filters>Map>Make Seamless.

Now, with the bucket-filled layer made seamless, when we copy and paste this version of the tile into a larger picture, we can see how the edges look much smoother.  Here is a comparison of the edge artifact from the original tile and the improvements after running the seamless filter:
Figure 12: Untouched edges look a bit jagged (four tiles come together in the center)

Figure 13: Edges look smooth after running Make Seamless filter



The change is obvious and it will make the end result much more professional.

One more thing we will do is offset the layer a bit so that the two middle rows of bricks are as close to the center line as possible.  Select Layer>Transform>Offset and set the X value to 0 and the Y value to 3.  Alternatively, you may want a brick row in the center, so you would then set the Y value to something like 10 or -16.  Experiment with this value and see which offset works best for you.

Now, to show the bricks only in the large rock portion of the road concept, we need to make a mask.  Create a new transparent layer and label it Large Rock Mask.  Then create a new layer group and call it Masks.  Drag the Large Rock Mask layer into the Masks group.  We will use this group as a repository for all the masks we create.

Select the Large Rock Mask layer and with the rectangle select tool, select the horizontal area bordered by the two guides we laid down and fill it with white.  Then un-select everything.

Next, select the brush tool and one of the Splat brushes.  Make sure the foreground color is white.  Set the brush size to some value between 50 and 70, and select an appropriate brush dynamic.  I often use the Pen Generic at this step.  You may also want to check the Apply Jitter box.

Use this brush to paint along the top and bottom areas of the filled rectangle.  The idea is to create a rough feathering effect as though bits of the large rock have crumbled at the edges to mix with the smaller rock farther out.  Additionally, you may want to set the dynamics to Dynamics Random and choose the eraser to erode a bit of the edges.  This bit of the procedure is purely dependent upon one's artistic style, but the concept road shown near the top of this post suggests frayed edges where the rocks meet.

Figure 13: Rough mask for large stone portion of road


Once you have finished crafting the white portion of the mask, you need to make sure it is seamless.  Because the only edges we must address are the ones east and west, we can offset the layer 128 pixels along the X axis (0 along the Y axis) and smooth out the portion in the middle.

When this is complete, you can add this as the mask to your large rock layer by selecting the entire frame (Ctrl-A) and copying it to the clipboard (Ctrl-C).  Then, right-click on the large rock layer, select Add Layer Mask... from the popup window, select the Black (full transparency) option, and then click on the Add button.

At this point, the mask portion of the layer is active, so you can place your mask by pasting from the clipboard (Ctrl-V), right-click on the new floating layer, and select Anchor Layer from the popup window.  This will anchor the white portion onto the mask and will now allow the layer to display only the middle portion of the bricks.  If you haven't already done so, it would be a good time to rename the large rock layer to something meaningful like Large Rock.

Figure 14: Application of the mask to the large rock layer


This method is generally the same for the small rock layer, except with a different pattern and another mask that reveals a wider portion.  When placed under the large rock layer, you will get a rough, grayish easement around the road.

Before continuing, it would be a good idea to see how well this tile actually works.  As it is a horizontal road, placing this tile horizontally next to itself will show how well we achieved the seamless attribute of the tile.

Figure 15: Road tile laid three wide


As you can see, with a plain green background added, this tile lays down very seamlessly and it looks fantastic.

Below is a picture of the mask for the small rock area and what the small rock layer looks like with the application of the mask.  Notice how the white pixels degrade above and below the grid lines specified for the large rock area.  Also note the Crack pattern has been modified with the Make Seamless filter.  The use of the Splats brush with alternating dynamics (usually Pen Generic and Dynamics Random) and the occasional application of the eraser create a randomized stippling effect that gives the illusion of eroded rocky areas.
Figure 16: Small rock mask

Figure 17: Small rock layer



Now, we test this look by laying the tiles again side by side with a green background.  Once again the look is very clean and there are no visible seams.

Figure 18: Better road tiled three wide


At this time you may want to experiment with backgrounds of dirt or grass.  Because this tile and the game uses photo-like images, modified images of grass and dirt would look best here.  One other good thing to do is create a new layer group and call it Horizontal Road.  Then place the two rock layers in that group.

The vertical road is quickly made as all the layers can be rotated 90°.  Just right-click on the Horizontal Road layer, duplicate it, and then select the new layer.  It will be named Horizontal Road copy, but you should rename this to Vertical Road.

With Vertical Road selected, Choose Layer>Transform>Rotate 90° clockwise.  You may also choose counter-clockwise, as either direction should give you a seamless vertical road tile.

Figure 19: Horizontal tile rotated to a vertical orientation


Two of these tiles laid vertically show a perfect match at the seams:

Figure 20: Two vertical tiles making a northbound road


This completes two of the six tiles needed for a road without intersections.  The other four are bends in the road that take a 90° turn.  We will label them W-N (as it connects the west side of the tile to the north side), W-S, E-N, and E-S.  They are all created in a similar fashion, so this post will concentrate only on the W-N tile.

We want the seams on the edges to be the same as the horizontal and vertical tiles we just made.  The main difference with the bends is how we merge the ends together with a smooth-looking path.  To that end we divide the work into to phases: a) modifying the masks, and b) modifying the graphics.

Start with the large rock mask in its horizontal orientation.  The west side of our W-N tile will need to match with tiles terminating on their eastern sides, so we must make sure the mask matches.  In order to make the northern edge match tiles aligned on the north, we must add the vertical mask.

We begin the new mask with a new blank layer.  Copy the horizontal mask into this new layer.  Then, copy the vertical mask and paste it into the new layer as well.  You will now have a layer we will eventually use for all the bend masks.

Figure 21:  The base mask for all four bend tiles (large rock)

For each bend, we merely start with this mask and erase the parts that do not belong, making sure we retain the same kind of eroded edge.  For the W-N tile, we will keep the west and north parts of the mask and remove the east and south parts

Start by making a copy of this layer and work with the copy, naming it W-N Mask.  Then, use the eraser tool with different brushes and dynamics to attain the same effect as with the other masks.

Figure 22: W-N large rock mask


The bricks image needs to be modified as well, but we will need to do this in a different fashion.  To make things simpler, the mask outlines a hard turn, and not a soft curve.  This will let us carry the horizontal and vertical alignments of the bricks directly into the middle.  We are going to need several layers for this, so we should create a new layer group called W-N.  In this group, drop the new W-N mask.

Hopefully, you have saved the bricks graphic.  If you did not, you can always duplicate the horizontal tile large rock layer and remove the mask.  Copy this graphic and another rotated vertically into the W-N group.  Create a layer mask for each one filled with black (full transparency).

Select the free select tool (Shift-F). and make a selection by clicking the top-left corner, the bottom-left corner, the bottom-right corner, and then again on the top-left corner.  This will create a diagonal selection.

Now, make sure that the mask is selected for the horizontal bricks and fill the area with white.  This will reveal the lower-left half of the graphic.

Invert the selection by choosing Select>Invert from the menu.  Make sure the mask for the vertical bricks image is selected and fill the other area with white.  This will reveal the upper-right half of the vertical bricks image.


Figure 23: the two layers properly masked out.

These need to be combined into one layer.  First, make sure both are visible, then right-click and select Apply Mask on the popup to both layers.  Right-click on the upper layer and select Merge Down.  This will create a layer we can now use with our mask.

Create a new mask (black full transparency) on this layer.  Copy the W-N mask we made earlier with Ctrl-C.  Make sure the mask on the combined brick layer is selected and paste the large rock mask in with Ctrl-V (be sure to anchor the pasted layer).

We now have something which is passable:

Figure 24: Mask applied to large bricks combined image

The same technique is used with the small rock layer.  When combined, they look like this:

Figure 25: W-N road curve with both rock layers


We test the edges by laying a road tile on the west and north edges of this tile.

Figure 26: Three road tiles connected to form a bend

This looks great.  The bricks in the W-N tile could use a bit of tweaking, but the majority of the work is done.

From here, you can build an assortment of road tiles, depending upon your needs.  The golden rule for road creation is to ensure the tiles show no obvious seams where they join.

There are other ways to accomplish the same thing, but I have found the layer offset feature and the Make Seamless filter to be invaluable in my graphics work.




02 June, 2016

Potential Grammar Fail


While reading a description of a book, I came across this passage:
[The Author] skips ahead years at a time, often eliding major conflict resolutions, character development and deaths...
The present participle eliding comes from the root elide, which is defined by most reputable dictionaries as:
  1. Omit, or
  2. Merge
As one can see, elide can mean one of two distinct things. Either you omit something or you bring two or more things together.  So, which one did the review writer mean?  Here is the same quote with each definition in place of eliding:
[The Author] skips ahead years at a time, often omitting major conflict resolutions, character development and deaths...
[The Author] skips ahead years at a time, often merging major conflict resolutions, character development and deaths...
Sadly, each meaning of elide works, and this is why the use of eliding in this text—without further clarification—is a grammar FAIL.  Fortunately, there is a clue to the real meaning later in the passage.  Here is the more complete quote with the clue:

[The Author] skips ahead years at a time, often eliding major conflict resolutions, character development and deaths; this choice disrupts the storytelling but smartly underscores the isolation in which the characters often operate.
It is not crystal clear, but one can safely surmise that the use of eliding, paired with isolation, indicates omissions. Yea! We figured it out!

Bring on the cake!

The problem, and in my opinion still a Fail, is that the reader needs to backtrack from "isolation" to "eliding" in order to glean an appropriate understanding of the description's real meaning. It would have been so much clearer and simpler if, instead of "eliding", the author of the description instead used "omitting" or "merging", or some similar version thereof.












29 March, 2016

Notes From the Edge of Depression

Just a quick note before I crawl away and expire.  I've noticed that I tend to write better when I get hit with depression.  And, I don't mean I somehow write gloriously or with an otherworldly ability for organization, character arc, or accuracy.  I mean that words tend to pour out of my head in bursts and--if I am of a keen enough mind to remember--I am able to craft short memos or missives that tend to sound a bit silly, yet magically contain a very nice cadence.

I have often taken these silly things and worked on them later when I was not so depressed, and I found that I liked the results.  When I am not depressed, words fail me, but I can maintain a fair amount of concentration and mien whilst editing or restructuring.

Now, if I can only harness that process with due diligence, I might actually be able to START that Great American Novel I have been pining to write for the past 30 years or so.

<grins>

Right.  Well, back to my depressing day...

05 February, 2016

Finer Points in Java: Shadowing vs Overriding

I have recently run into a "feature" of Java which really caused me a lot of head scratching and testing before I discovered the core of a recent coding problem.  Because I was unclear of certain peculiarities of shadowing and overriding, I was expecting A, when in fact I got B.

The Problem


In a nutshell, shadowed variables come from the declared type of an object, but overridden methods are run from the constructed object.

Ok, that isn't very clear, so here is some code to make it simpler.  It's all in one file called Derived.java:


class Base {
    public int x = 0;
    public String aMethod() {
        return "Base";
    };
}

public class Derived extends Base {
    private String secretmessage = "a secret!";
    public int x = 1;
    public String aMethod() {
        return "Derived " + this.secretmessage;
    }
    
    public static void main(String[] args) {
        Base b = new Derived();
        //
        System.out.println("x:aMethod = " + b.x + ":" + b.aMethod());
        //
    }
}


The output of this when run is:

x:aMethod = 0:Derived a secret!

What that shows is that b.x returned the Base class's variable x, and b.aMethod() returned the Derived class's method aMethod.

Access to Unreachable Data


In Derived, the function aMethod returns a string that contains the contents of the private instance variable secretmessage.  If I were to substitute b.aMethod() with b.secretmessage, I would get a compiler error because b.secretmessage is not available in class B:

Derived.java:23: error: cannot find symbol
        System.out.println("x:aMethod = " + b.x + ":" + b.secretmessage);
                                                         ^
  symbol:   variable secretmessage
  location: variable b of type Base
1 error

But, I can access the variable via aMethod!  This also means I could execute any method in Derived, as long as it overrides the same method in Base.

If an able Java programmer did not know this, then reading the code may be problematic: one would expect a base class's method to run when in fact the derived class method was run.  Likewise, the opposite could be said for a shadowed variable.

Bottom line: be aware of the shadowing and overriding rules.







28 January, 2016

Updating Table From Another Table With Row Mismatch

I currently work with financial software based, mainly, in stored procedures in a few Microsoft SQL Server databases.  A lot of my efforts are directed toward maintaining the current processes while integrating enhancements and modifications whenever possible.

Recently, I ran into a problem with an UPDATE statement.  Here is the way the update process was built:

with CTE_1 as (...),
CTE_2 as (...)
    update TargetTable
    set
        Value_1 = case c.TransType when 1 then c.ComputedAmt else Value_1,
        Value_2 = case c.TransType when 2 then c.ComputedAmt else Value_2            
    from
        CTE_x c
    where
        TargetTable.Key = c.Key

My intention was simple: update one column when the transaction type was one value, and update another column when the transaction type was another value.  But, it failed.  Let's take a look at the data generated in the CTE section for table CTE_x (that being either CTE_1 or CTE_2):

KeyTransTypeComputedAmt
ABC011123.45
ABC012989.02
EFG33134.00
EFG3323024.63
...

Now take a look at how TargetTable is populated:

KeyValue_1Value_2
ABC010.000.00
EFG330.000.00
...

The problem with the UPDATE statement above is that I want to update each row in the target table twice.  This is forbidden.

The solution was to add another CTE that took the data from CTE_x and pivoted it so that I would have a one-to-one relationship between the target table and the source of the updates:

with ...
,
CTE_pivot as (
        select
            Key as "SourceKey",
            [1] as "VAL_a",[2] as "VAL_b"
        from (select Key,TransType,ComputedAmt from CTE_x) as x
        pivot (
            max(ComputedAmt)
            for TransType in ([1],[2])
        ) as pvt
)


With the pivoted data now in CTE_pivot, the data was correctly organized thusly:

KeyVAL_aVAL_b
ABC01123.45989.02
EFG3334.003024.63
...


And with this, the final UPDATE statement gets a single row with both columns from the source table (now CTE_pivot):

with ...
update TargetTable
  set Value_1 = VAL_a, Value_2 = VAL_b
from
  CTE_pivot
where
  CTE_pivot.Key = TargetTable.Key


28 May, 2014

HTML5 "Programming" is Not Programming

As the HTML5 craze sinks its teeth into more and more programmer-hopefuls, I see a rise in articles that say: "Doodz!  I programming in HTML5!"  Yerk!

The reason I yerk at statements like the above is simple: the "programming" displayed in the articles isn't really HTML5 programming, but Javascript programming.  Oh, yes, these doodz use objects and methods that are built into the user agents which utilize HTML5-only elements;  however, they are not programming in HTML5.

HTML5 programming looks like this:

<!DOCTYPE html>
<html>
    <head>
        <title>Awesome Programmer Dood</title>
    </head>
    <body>
        <article>Look!  Iz programming!</article>
    </body>
</html>


What these starry-eyed neophytes are really programming is this:

<script type="text/javascript">
  function drawSquare(len) {
    cvs = document.getElementById("whiteboard");
    ctx = cvs.getContext("2d");
    ctx.fillStyle = "red";
    ctx.fillRect(0,0,len,len);
  }
</script>

Huh?  What's that I see?  Did that script element say it was Javascript?  Gee, I guess it did.  Any noob can type "<canvas id="whiteboard>", but creating all of the Javascript to do the drawing and so forth is a horse of a different color.

But, I digress.  The point is, programmers who write Javascript code to draw pretty things on HTML5 elements should really be more accurate.  They are programming in Javascript using an api in the user agent.

18 August, 2013

Caught Myself

I am taking a Critical Thinking class, which so far has shown me two important things:
  1. There is an assumption (at least at my college) that students have a lot of trouble performing the act of Critical Thinking.
  2. I am one of them.
I have performed well in tests and assessments, but I still have a lot of work to do in order to incorporate critical thinking into my life.

On one question, the teacher asked us about a politician's point of view.  We were to choose from a list of statements that supported this politician's point of view.  One of the statements was:
  •   The politician believes society has a moral obligation to care for the poor.
Keeping in mind the fact that the politician in question is a devout liberal, I raised my hand and said: "Yes."  Then the teacher raised one eyebrow and asked my if I thought that the statement was only a liberal point of view.

Again, I said "yes."

Then, I was told that the statement spoke of society's obligations, not a government's obligations.

Chagrined, I was.  I jumped to an immediate conclusion that caring for the poor was only liberal belief and not a conservative one.  Furthermore, I assumed that the monikers "liberal" and "conservative" represented a concrete set of beliefs.

Reality says otherwise.  Not all liberals hold the exact same beliefs; nor do all conservatives.

My error in thinking was that I, a left-leaning independent, knew something without questioning where I received that knowledge.  In other words, why did I believe that liberals believe society has a moral obligation to tend to the poor?

This is the question  that I should have asked before I opened my mouth.  Instead of pulling away from my biases and looking at everything objectively, I let an inner sentiment drive me blindly along.  Basically, I just parroted a sound bite that I have heard and read countless times without really thinking about it.

So, I caught myself somewhat after the fact making an improper judgement and leaping to a conclusion without giving my assumptions due thought.