Daily Archives: December 1, 2014

Journal Entry 60 – One Year Later

It has been exactly one year since my last journal entry! Yes, I’m alive, and the news of awful things happening to me have been greatly exaggerated. Let’s take a look to see what I’ve been up to, and where things are going from here.

First, I’ve continued to be active on Twitter, posting several screenshots throughout the past several months. If you aren’t already following me there, I totally recommend it if you want updates on Live Love Farm! That brings me to my second bit:

I’m now working on a game that uses the Voxel engine, and it is called Live Love Farm (LLF). You can sign up for alpha access here: http://llf.giawa.com and the alpha is totally free! This is a Voxel game that is inspired by games such as Harvest Moon, Zelda and World of Warcraft. I hope to have the alpha available shortly, although there’s still lots of work to do!

Anyways, you probably don’t want to hear my ramblings. You’re here for some code! So, let’s take a look at some of the stuff I am playing with. A few days ago I posted this screen shot:

With the new classes and particle effects this water wheel comes to life!
With the new classes and particle effects this water wheel comes to life!

The first step in creating this rotating water wheel is to actually create a model for the wheel. There’s a few ways to do this, and the editor comes in handy. However, instead of trying to draw perfect circles in voxels I enlisted the help of my Utilities classes. I have a simple ‘FillCircle’ and ‘DrawCircle’ method which can also be used to place voxels only at particular points along the circle (via an override). Here’s the method prototype for that:

public static void FillCircle(ushort[] data, Point3D point, int radius, ushort c, double step = 0.05)

I can use this FillCircle method to create the spokes in the water wheel, by setting the ‘step’ value to only try to fill the circle along 8 points. Since a circle goes from 0 to Math.PI * 2 we can set the step value to Math.PI / 4 to get 8 spokes. I also add the hub that connects the water wheel to the wheel house, providing power to whatever machinery lies inside.

// draw the spokes of the water wheel
Geometry.FillCircle(voxelData, new Point3D(16, 0, 16), 14, 2319, Math.PI / 4);
Geometry.FillCircle(voxelData, new Point3D(16, 7, 16), 14, 2319, Math.PI / 4);
 
// draw the center bar which will connect to the wheel house
Geometry.DrawLine(voxelData, new Point3D(16, 0, 16), new Point3D(16, 7, 16), 12684);

Now we can draw the wheel itself, which is pretty simple. I just used two circles to double up the width.

// draw the wheel itself
Geometry.DrawCircle(voxelData, new Point3D(16, 0, 16), 13, 2319, Math.PI / 80);
Geometry.DrawCircle(voxelData, new Point3D(16, 0, 16), 14, 2319, Math.PI / 80);
Geometry.DrawCircle(voxelData, new Point3D(16, 7, 16), 13, 2319, Math.PI / 80);
Geometry.DrawCircle(voxelData, new Point3D(16, 7, 16), 14, 2319, Math.PI / 80);

Finally, we can draw the buckets, which are added via a few more DrawCircle calls. I have created a loop here which varies the y value so that the buckets have some height to them.

// draw that water wheel buckets
for (int i = 1; i < 7; i++)
{
    Geometry.DrawCircle(voxelData, new Point3D(16, i, 16), 13, 12684, Math.PI / 10);
    Geometry.DrawCircle(voxelData, new Point3D(16, i, 16), 14, 12684, Math.PI / 10);
    Geometry.DrawCircle(voxelData, new Point3D(16, i, 16), 15, 12684, Math.PI / 10);
}
Using math to make some object in the world!
Using math to make some object in the world!

Now we need to orient the water wheel and let the engine know that it needs to be rotated a little bit every frame. This is very simple using the MovingVoxelChunk class. MovingVoxelChunk implements the IDrawable interface, which allows us to place these objects in the World easily. An update callback is run every frame which can affect the position (and other aspects) of the voxel chunk.

// load the water wheel and build it
VoxelChunk waterwheelBucket = new VoxelChunk(TerrainShader.Program, "vox/windmill/water_wheel.zvc");
waterwheelBucket.BuildWithOcclusion();
 
// this is the initial Z rotation of the wheel
float rotation = 0f;
 
// now we create a MovingVoxelChunk object with a callback
MovingVoxelChunk waterwheel = new MovingVoxelChunk(new Vector3(9, 8, 16.5), waterwheelBucket, (chunk) =>
    {
        // the callback updates the rotation value and generates a new model matrix
        rotation += Time.DeltaTime * 0.5f;
 
        // the model matrix consists of first moving the water wheel to the origin (-16, 0, -16)
        // now create a Z rotation (the is what rotates the water wheel)
        // and translate/scale the water wheel to the correct position
        return Matrix4.CreateTranslation(new Vector3(-16, 0, -16)) * Matrix4.CreateRotationZ((float)-Math.PI / 2) * Utilities.FastMatrix4(chunk.Position, new Vector3(0.5, 0.5, 0.5), Vector3.Right, rotation);
    });
 
// add the MovingVoxelChunk to the world and we're done!
World.AddObject(waterwheel);

Of course, there’s nothing to stop us from adding particles and performing other operations in the callback function, which is how I generate the particles for the original screenshot. This technique is what is used for wind mills, fires, and pretty much any voxel chunk that is moving around each frame.

To wrap up, let’s take a look at some screenshots of what has been accomplished over the last year! 4 legged animals:

Some of the bugs I had while creating these four legged creatures were hilarious.
Some of the bugs I had while creating these four legged creatures were hilarious.

A* Pathfinding:

A* Pathfinding

Shadows:

Shadows

Pixel perfect picking of world objects:

Pixel Perfect Picking

Terrain generation using Voronoi diagrams:

Voronoi Procedural Generation

Cuddly critters that roam around the world:

Raccoons and Cats!

Basic farming (picking up items, planting, growing day to day, throw on ground, store in shipping container/backpack, etc):

Bok Choy Gone To Seed

3D Sound using OpenAL:

The white lines are drawn to each sound source that is active.  Sound sources fade out and in depending on their location with respect to the character.
The white lines are drawn to each sound source that is active. Sound sources fade out and in depending on their location with respect to the character.

Atmospherics such as snow and rain (with corresponding changes to cloud cover):

It's Snowing!

Reflections:

Reflective Water

Light scattering:

Lots of Post Processing

Transparencies, ordering, lighting, etc:

Transparencies

There’s also a lot of work that went on behind the scenes that isn’t possible to show in a screenshot. The UI frame work has been drastically updated with new controls, performance improvements, etc. The meshing algorithms are much more efficient and robust, threading is better, and there are lots of gameplay items. For example, there is full support for inventories, crafting, recipes, NPC text, quests, achievements and so on.

The big step that needs to occur before alpha release is better world procedural generation, and the integration of all the different abilities of the engine. I’ll also need to work on generating some in-game content, such as different stages of plants, tools, and so on. I also need to begin work on my character animations, although I have some good tools for that!

Until next time,

Giawa