Category Archives: Java

BoardBuilder design

Introduction

BoardBuilder is a factory class used for creating Board model for the Farout game. In following I will briefly go through the design of the BoardBuilder and give you reasoning behind my decisions. In my next post I will go in more detail by showing you some source code and hopefully I have a working example as well.

By creating dedicated builder class we separate construction role from the model role that the Board class represents. It also keeps Board class simpler and makes it possible to change construction process without a need to touch Board’s implementation.

During the construction we have to allocate memory blocks which are no longer needed when construction has finished. By keeping those allocations in builder only it is easier for us to control how memory is used and when it is freed.

Construction process is divided into small simple steps to make source code easier to understand and maintain. As a rule of thumb every function has only one purpose and if I see copy paste code anywhere I will move that code into own function. I prefer a lot of small methods to few monolithic ones, therefore my classes usually have quite long definition.

Below is the static model of the BoardBuilder and after that you can find description of each class and their purpose.

BoardBuilder's static model

Vertex

Vertex represents single point in 2-dimensional world. It has x and y value defined as floating point numbers.

Segment

Segment represents one line segment that is constructed of two or more Vertices. Vertices are referenced by the Segments. Therefore same Vertex can be used in several Segments.

Hexagon

Hexagon represents one hexagon and is constructed of exactly six Segments. Neigbouring Hexagons share one segment with each other. Segments are referenced by the Hexagon instances, that way we can modify Segment and modifications are instantly visible in every Hexagon referencing the modified Segment.

Region<T>

Region is a tile that is constructed from one or more Hexagons. Region is defined as generic class and the unqualified type parameter is used for referencing the actual region data. Regions own instance of java.awt.Polygon that defines their shape. Polygon class is created because it can be used as a tool for several tasks. E.g.

  1. To check if certain point is located inside Region (e.g. region.shape().contains(x, y)).
  2. To mask (clip) textured blitting (e.g. graphics.setClip(region.shape())).
  3. To draw region borders (e.g. graphics.drawPolygon(region.shape())).
  4. To get maximum bounds of the Region (e.g. region.shape().getBounds()).

BoardBuilder

Board construction is handled by the BoardBuilder class. Construction parameters are given in a BoardBuilderParameters class. Construction happens in following order.

  1. Hexagonal Vertices are constructed
  2. Segments are constructed by connecting proper Vertices
  3. Hexagons are constructed by collecting proper Segments from all Segments
  4. Hexagons are dehexified as described in earlier post
  5. Regions are constructed from Hexagons by combining selected neighbour Hexagons, adjacency is validated when new Hexagon is added to a Region and if the added Hexagon is valid all, except the connecting Segment, are added to the Region
  6. Shape is constructed for each Region
  7. Board is created and ownership of the created Regions is transferred to the Board
  8. Created Board instance is returned to the caller and is ready to be used

Inaria Java..

This is a bit old stuff, but I wanted to share it with you. Inaria is a very simple role playing game that was originally created by Anthony Salter as a result of 40-hours game project. When Anthony released source code for Inaria, someone took initiative and ported it to C#. After trying out C# version I began my own Java port of Inaria and here are the results.

The basic game play should be equal to Anthony’s version. I also added some eye candy and improvements to the user interface. E.g. actions have shortcut keys, buttons are animated when pressed and there are some fading effects and animations added.

Select either Inaria Java without Line of Sight or with Line of Sight.

Requires Java Runtime 1.5 or newer to play this game.

Deform algorithms for dehexifying process

In my last post I talked about how to make hexagon map look less dull using dehexifying algorithm. I mentioned that we need to deform vertices but I did not give any examples how to do it. As you probably remember we need to do deformation in two steps, first for the hexagon vertices and later for segment vertices.

Deforming the hexagon vertices is pretty straightforward. We just move all the vertices by certain random amount. One thing to remember though, do not move any vertex more than half the width of the hexagon, and tag vertices that have already been deformed because same vertex can be referenced by several hexagons. Below is a very simple deformation algorithm implemented in Java.
[xscode etext=”Click to show example code” ctext=”Click to hide example code”]
// Vertex
class Vertex {
static Random R = new Random();

public float x;
public float y;
boolean deformed;

public void deform(float range) {
if (!deformed) {
deformed = true;
x += (R.nextFloat() – 0.5f) * range;
y += (R.nextFloat() – 0.5f) * range;
}
}
}

// Hexagon
class Hexagon {
List<Vertex> vertices;

public void deformVertices(int size) {
for (Vertex v in vertices) {
v.deform(size);
}
}
}
[/xscode]
Next I will show the simplest possible segment deformation algorithm. It is virtually same as Hexagon vertex deformation algorithm except for the range of deformation and how it is calculated. I have added Rules class to maintain creation variables. In example below we query segment deformation range from Rules class using method segmentVertexDeformRange() which takes number of vertices in the segment as parameter.

Using the number of vertices as damping factor we have better control of what the deformation result will look like. It is also good for preventing overflows in deformation which would result in silly looking hexagons.

In Hexagon class we just loop through every segment and call deformVertices() for each one. In Segment class deform() is called for each Vertex referenced by the segment.
[xscode etext=”Click to show example code” ctext=”Click to hide example code”]
// Hexagon
class Hexagon {
List<Segment> segments;

public void deformSegments() {
for (Segment s in segments) {
s.deformVertices(Rules.segmentVertexDeformRange(s.vertexCount()));
}
}
}

// Segment
class Segment {
List<Vertex> vertices;

public void deformVertices(float range) {
for (Vertex v in vertices) {
v.deform(range);
}
}
}
[/xscode]
In this naive solution borders can appear jagged. Jagginess can be controlled by tweaking the Rules, but what if we wanted smoothly curved borders? One possible solution would be the use of splines. Below is a sample implementation that uses Java 2D API for this task.
[xscode etext=”Click to show example code” ctext=”Click to hide example code”]
class Segment {
public void deformSplines(float range) {
deformVertices(range);
createSplineVertices(range);
}

void createSplineVertices() {
// Create path
Path2D.Float path = new Path2D.Float();
Vertex v = vertices[0];
path.moveTo(v.x, v.y);
for (int i = 1; i < vertices.size; i++) {
Vertex vold = v;
v = vertices[i];
Point2D.Float[] cps = randomControlPoints(vold, v);
path.curveTo(cps[0].x, cps[0].y, cps[1].x, cps[1].y, v.x, v,y);
}

// Collect new vertices from path
List<Vertex> cubicVertices = new ArrayList<Vertex>();
PathIterator pi = path.getPathIterator(null);
FlatteningPathIterator fi = new FlatteningPathIterator(pi, 0.1f);
while (!fi.isDone()) {
float[] p = new float[6];
fi.currentSegment(p);
cubicVertices.add(new Vertex(p[0], p[1]));
fi.next();
}

// Preserve reference starting and ending points
cubicVertices[0] = vertices[0];
cubicVertices[cubicVertices.size() – 1] = vertices[vertices.size() – 1];

// Apply new vertices
vertices = cubicVertices;
}

Point2D.Float[] randomControlPoints(Vertex b, Vertex e) {
Point2D.Float[] cps = new Point2D.Float[2];
float r = b.distanceFrom(e) / 2.0f;
float a = R.nextFloat() * PI_2;
cps[0].x = b.x + r * cos(a);
cps[0].y = b.y + r * sin(a);
a = R.nextFloat() * PI_2;
cps[1].x = e.x + r * cos(a);
cps[1].y = e.y + r * sin(a);
return cps;
}
}
[/xscode]
It is possible to mix naive and curved implementations to create even more realistic looking tiles. Just add random threshold point that will decide which implementation to use for the segment.
[xscode etext=”Click to show example code” ctext=”Click to hide example code”]
class Segment {
public void deformRandomly(float range) {
if (R.nextFloat() <= Rules.percentageOfCurvedSegments() / 100.0f) {
deformSplines(range);
} else {
deformVertices(range);
}
}
}
[/xscode]
We have seen that using deform algorithms it is possible to create realistic looking map tiles for hexagon maps. Deformation can be done in many ways and I have shown two different algorithms to do this. Next I would suggest you to experiment with different algorithms to generate even more realistic looking tiles.