AutoBrush – FilterForge filter

AutoBrush is a painting filter I wrote in Lua for my own postwork needs. It distributes brushes/images over an image procedurally, similar to the standard bomber component in FilterForge.

The filter is free to download here: https://www.filterforge.com/filters/15767.html

You will need a copy of FilterForge version 7 or higher to use the filter.

First update 2021-02-27:

version 1.1

  • Fixed a bug that would sometimes cut off certain brushes halfway if they had a brush size of 50 or less.
  • Added another locked checkbox called DoubleStrokes. Once this is checked, the number of brush strokes will double. Warning: this is only for users with a high performing PC. If the stroke number is set to 500, it will be 1000 instead once this box is checked, increasing the rendering time substantially.
  • Changed the last presets, number 10-14.

Easiest way to apply the filter from PhotoShop:

  1. In PhotoShop, select the drop-down Filter –> FilterForgeFilterForge version X
  2. You find AutoBrush in the Creative folder inside FilterForge.
  3. Apply a preset.
  4. Uncheck the UserImageOn checkbox to use the image you brought from PhotoShop.
  5. At the bottom of the sliders panel to the left, lock “Size, pixels” at maximum resolution. You don’t want to randomize this slider.

How to improve the render speed:

  1. Keep “StrokeCap–300” checked for faster performance, it will cap the strokes at maximum 300. If you want more strokes you need to uncheck this.
  2. Lock “EdgeBrushes” at 1 for best performance. This slider adds extra strokes that are applied on edge areas.
  3. Set “LongerStrokes” to 1 for best performance. This slider causes some strokes to get lengthened in a random direction, with some amount of rotation and decreasing size.
  4. Set “LongStrokeChance” to 1 for best peformance. This is the percentage chance for every stroke to get lengthened. Be careful, a high value for this slider will significantly slow down the render time.
  5. The “Speed” slider will speed up the render but also results in a loss of quality.

Adding your own pre-made brushes:

You can add your own pre-made brushes in .png format by following these steps:

  1. Edit the filter by pressing the button up to the top right; “Filter Editor”.
  2. Save the filter with a new name so that your changed filter is a separate variant from the original filter.
  3. The mapscript already comes with 8 standard presents for brushmaps that you plug in. The image below shows the first 3 presets that have 100, 16 and 16 brushes in each brushmap. Presets 4-8 are designed for user-imported grids of brushes. The slider “Select Brushmap” selects between these 8 presets.

Inside the main Lua mapscript, find this function:

“function InitBrushSelection()”

Inside this function you find 8 Switch statements that define parameters for each of the 8 brushmap presets. Find the Switch statement that corresponds to the brushmap you want to edit.

If you have a grid with 10 * 10 brushes, you want to make sure to have the setting:

MaxBrushTypes = 100

If you are only using 10*2 brushes, then set it to 20 instead.

Support:

The fastest way to contact me for support is through my Twitter account:

https://twitter.com/fernevak/

Shoreline

Shoreline, 2019.

For the scene I wanted to create a pose similar to the painting by John Liston Byam Shaw; “The woman, the man and the serpent”, though in a sci-fi setting. Also I had a bit inspiration form Boris Vallejo. I set up the scene in 3d and made postwork and paintover in Photoshop.

Shoreline

Image link: Shoreline – [1200 x 675]

Shoreline closeup

Image link: Shoreline closeup – [1200 x 675]

Interactive fiction concepts

I wanted to share a few concept locations and characters that I am designing for my interactive fiction. I’m coding the game prototype in Lua and have the story develop in a sci-fi horror setting illustrated with a bleak atmosphere.

As I explore the background events and overarching plot I find it engaging to visualize areas, locations and persons of interest at an early stage. Even as the details change over time this process adds fuel to the storybuilding where I am able to test out ideas to see how they fit into the larger narrative.

While I will rework these illustrations further on to fit the exact situations that will occur during the player’s journey, defining the atmosphere and narrowing down the variety of possibilities help me tying the project together. Once an idea is visualized the opportunity to iterate and expand upon the thread of imagination from there is opened up.

I have been in the process of revising the game code structure a bit and will share some of the code further on when I have sufficient time. Mainly I have centralized the data access to ease future code changes and reduce method dependencies.

Laboratory

Image link: Laboratory – [1200 x 675]

Arches of the past

Image link: Arches of the past – [1200 x 675]

Remnants

Image link: Remnants – [1200 x 675]

Character concept

Image link: Character concept – [1200 x 675]

Landingsite

Image link: Landingsite – [1200 x 675]

Interactive fiction in Lua – Part 03

 Third part – Object IDs and object properties

For my interactive fiction game I want to access my objects via ID codes. The benefit of this approach is that you don’t need to move around a lot of data when moving the objects in the game. While you could compress the object IDs to hexadecimal format or using bits and bytes, I prefer having the IDs clearly readable for code debugging reasons.

    object 1 = ‘ID000001’
    object 2 = ‘ID000002’
    object 3 = ‘ID000003’

Below is a simple function I wrote that transforms numbers into an ID code format like the above example.

function get_ID_format(id_short) -- Returns a long ID
    local maxlength = 6
    local num = tostring(id_short)
    local zeros = string.rep("0", maxlength - #num)
    return "ID" .. zeros .. num
end

local id_long = get_ID_format(1)
print(id_long)

Above, tostring(id_short) transforms the value of id_short into a string.

string.rep replicates the first argument “0” as many times as needed; maxlength – #num.

#num returns the length of the number string, similarly like writing string.len(num).

Finally the function returns the ID. The string is comprised of “ID” + the number of zero’s + the short id number in string form. The double periods “..” concatenates the strings together as a single string. Print result: ID000001.

With the object ID approach, moving objects from a room to the player inventory, or vice versa, is relatively simple and mainly involves moving the object IDs around, combined with changing a few properties.

 Object properties

At this point I would like to store object properties in a global table, which we could call g_objData.

g_objData = {} -- initializes 'g_objData'

In Lua it is useful to store data not only in numbered dimensions but also by using keys (strings).

Let’s say that I want to set up my object properties like this;
two functions are listed below, with the main code that calls the functions placed last:

function add_obj(room, name, liftable, held, visible, child_of, contain)
    local id_short = g_nextObjectID
    local id_long = get_ID_format(id_short)
    g_objData[id_long] = {
        room = room,
        name = name,
        child = child_of,
        carry = liftable,
        held = held,
        visible = visible,
        container = contain
        }
    g_nextObjectID += 1 -- increase ID for next object
end

function get_ID_format(id_short) -- Returns a long string ID
    local maxlength = 6
    local num = tostring(id_short)
    local zeros = string.rep("0", maxlength - #num)
    return "ID" .. zeros .. num
end

g_objData = {} -- initializes 'g_objData'
g_nextObjectID = 1 -- assigns ID 1 to the first object

add_obj(1, "box", 1, 0, 1, "", 10)

local id_long = "ID000001"
print(g_objData[id_long].name)

Above, the function add_obj() is called with a few parameters that can be used for creating a simple box object. It has a property that tells us it can be carried, though the object is not yet held by anyone. It is visible and have a container property of 10, which could be used to define weight capacity, volume or a certain number of items.

Every time the add_obj() function finishes, it increments the global variable g_nextObjectID with one so that whenever the function is called, the next object will have a unique ID.

After the function add_obj() is called, the global object property table g_objData will be filled like this:

g_objData.ID000001.room = 1 -- Object room location
g_objData.ID000001.name = "box" -- Object name
g_objData.ID000001.child = "" -- Child of another object
g_objData.ID000001.carry = 1 -- The object can be carried
g_objData.ID000001.held = 0 -- Player holding the object
g_objData.ID000001.visible = 1 -- Object visibility
g_objData.ID000001.container = 10 -- Container capacity

This table could also be shown as such:

local id_long = "ID000001"

g_objData[id_long]["room"] = 1
g_objData[id_long]["name"] = "box"
g_objData[id_long]["child"] = ""
g_objData[id_long]["carry"] = 1
g_objData[id_long]["held"] = 0
g_objData[id_long]["visible"] = 1
g_objData[id_long]["container"] = 10

print(g_objData[id_long].name)

The last line in the above example would print out “box” in the console window, provided that the table g_objData[id_long] has been filled using the above function add_obj(), or a similar function.

Next, I would like to access the object data in the game through at least two functions;

        1. reading the data
        2. setting the data

Let’s create two functions for that:

        ‘get_obj_property()’
        ‘set_obj_property()’

Below is an example of a function returning the object property data:

function get_obj_property(id_long, type)
    local data = g_objData -- 'data' points to table g_objData
    if id_long and type and data then
        if id_long == "" then
            return 0
        else
            local data_id = data[id_long]
            if type == "name" then
                return data_id.name
            elseif type == "room" then
                return data_id.room
            elseif type == "held" or type == "carried" then
                return data_id.held
            elseif type == "liftable" then
                return data_id.carry
            elseif type == "visible" then
                return data_id.visible
            elseif type == "container" then
                return data_id.container
            elseif type == "child" then
                return data_id.child
            else
                print("Error. No '"..type.."' in '"..id_long.."'.")
                return 0
            end
        end
    else
        return 0
    end
end

print(g_objData[id_long].name)
print(get_obj_property(id_long, "name"))

The function above is called with two arguments; first the long ID string, then the string type, here providing the object property key that have already been defined in function add_obj().

First the function checks to make sure that three variables are not nil; id_long, type and data, since variables that hold a nil property will throw an error when they are accessed. If any of them are nil then a zero value will be returned. The main part of the function returns the object properties of g_objData[id_long][type] by using the local pointers.

Notice that there is only one reference to the table g_objData at the start; the rest of the function uses local pointers. The local table data points to the global table g_objData and local variable data_id points to g_objData[id_long]

Using a few central functions gives more flexibility than asking for

        g_objData[id_long].name
        g_objData[id_long].held
        g_objData[id_long].child
        g_objData[id_long].container

from numerous other functions or places in the code. Instead, you just call your designated function/s and let it handle the method of accessing the data you need, without burdening the rest of the program to bother about the exact details involved or which table is used to achieve the result.

 A few thoughts

I created the “child” property in order to place objects inside or upon other objects. The child property is intended to hold the ID of the object which it is a child of, i.e. parented to.

When I designed my room descriptions I decided to not mention objects that are on top of, or inside, other objects; I want the player to look at objects in order to find out what they contain.

If the player wants to see objects on a desk for example, they will have to examine the desk first. When the player inspects an object, a function checks which objects in the room have a child property matching the ID of the object the player is looking at. Those object names are then listed in a string after which another function is called for grammar correction before the description is shown to the player.

———

In later posts I will talk about room arrays, inventory handling, room layout, portals between rooms, player input and analysis, functions for grammar correction, placing room prefabs and adding new regions that can be traversed between.

Each new region will come with its own region-specific tables of data for rooms, portals, objects, room descriptions, illustrations, and so on. By changing pointers at a later stage, the data from one region can easily be swapped out by pointing to the data set of another region.