Jump to content

Recommended Posts

I had need of a way to make new decent looking defenses for anti-air and artillery sites on the fly.

So I wrote a little tile layer, called it CPG, and realized someone else might find this useful so here we are.

 

What does CPG do?

It takes a predefined set of tiles and lays them in an organic-looking pattern according to the connection rules of the tiles.

It provides functions for the mission maker to easily create and edit tilesets as well as spawn patterns made from those tilesets in both the 3DEN editor as well as during mission runtime.

The TL;DR is it makes this happen:

Spoiler

These are all generated using the same input tileset and parameters.

?imw=5000&imh=5000&ima=fit&impolicy=Lett

?imw=5000&imh=5000&ima=fit&impolicy=Lett

?imw=5000&imh=5000&ima=fit&impolicy=Lett

?imw=5000&imh=5000&ima=fit&impolicy=Lett

 

How does it work?

  • Tilesets are defined in the editor and exported to memory and/or .sqf-file.
  • Tiles come in a limited number of types related to how they may connect.
  • Each type can have multiple variants of which 1 is randomly selected on generation of each tile.
  • A funky hybrid of BFS and Wave Function Collapse algorithm generates a grid and places the tiles according to the connection rules.

 

How do I use it?
First see installation steps below.
Once installed you can activate the generator by calling CPG_fnc_generate (See below spoiler for examples).

The "generate" function differentiates between 3DEN and mission runtime and spawns the objects appropriately.

Spoiler

 


// Create a 3x3 pattern from the "SandbagFort" tileset-file at player position facing in the direction of the player
_return = [ "CPG\tilesets\SandbagFort.sqf", getPos player, getDir player, [3,3] ] call CPG_fnc_generate;

// Create a 5x3 pattern from a preloaded tileset at player position and direction
_return = [ tilesetHashMap, getPos player, getDir player, [5,3] ] call CPG_fnc_generate;

// Here's the full header and parameter list of the generate function
/*
	File: fn_generate.sqf
	Description: Generate a CP grid and construct a collapsed pattern from it using the given tileset
	Author: mrCurry - https://forums.bohemia.net/profile/759255-mrcurry/
	Date: 2023-04-03

	Parameter(s):
		0 - _tileset - Path to tileset or precompiled hashmap of tileset [HASHMAP or STRING]
		1 - _center - Center position or object [ARRAY or OBJECT]
		2 - _direction - Compass direction of grid North [NUMBER]
		3 - _gridSettings - Settings array containing the following six parameters [ARRAY]
			0 - _dimX - Grid X dimension [INTEGER]
			1 - _dimY - Grid Y dimension [INTEGER]
			2 - _cellSize - Grid cell side length in meters [NUMBER]
			3 - _startCoord - Starting grid coordinate, if "auto" center is used. Default: "auto" [POSITION or STRING]
			4 - _startTile - The tiletype of the first tile. If "random" then all execept "start" can be the first. Default: "start" [STRING]
			5 - _startRot - Starting internal rotation (0-3) of the first tile [NUMBER]
		4 - _preTileCreate - Eventhandler called for each tile prior to tile creation starts. The code is passed (coord, tiledata, gridmap, gridattributes) [CODE]
	
	Return: [_gridMap, _gridAttributes]
*/
gridMapAndAttributes = [tileset, center, dir, gridSettings, onPreTileCode] call CPG_fnc_generate;

 

 

 


Installation

Creating your own tileset

Here's a quick guide how to create your own tilesets for the generator:

Spoiler

 

All functions mentioned below are listed in comments in the demo mission as well for easy access.

The steps required to create your own tilesets are:
 

  1. First make sure you are in 3DEN editor. Creating tilesets is done in the editor only.
  2. Create tile frames (triggers) - Execute the function CPG_fnc_newTileset in the debug console with appropriate parameters. The debug console is found under Tools > Debug Console.
    
    // name = the name of the tileset, will be used later for export - Case-Sensitive
    // tilesize = Length of the side of each tile in meters
    // numVariants = The number of variants to prep. Prefer to add too many and if some aren't need delete the relevant layers.
    // startPos = (Optional) defaults to screen center, Note startPos is always aligned with the 32x32 grid of the Virtual Reality world.
    ["name",  tilesize, numVariants, (startPos)] call CPG_fnc_newTileset; 

     

  3. For each tile frame:
    1. Fill the tile with desired objects, the little blue arrows show where the tile will connect to other tiles.
      I recommend enabling the "Translation Grid" and "Rotation Grid" options in the editor cause it makes aligning things a lot easier.
    2. Select the trigger and all objects of the tile, be careful to only select the objects you want associated with that tile.
    3. Execute a transfer of objects to the variant in the debug console with the following code:
      
      call CPG_fnc_setObjectsAsVariant;

       

  4. Export the tileset to the log file by executing CPG_fnc_exportTileset:
    
    // To export to file
    ["name", true] call CPG_fnc_exportTileset;
    
    // To export to memory e.g. for testing
    tileset = ["name", false] call CPG_fnc_exportTileset;
  5. Copy the CPG export contents from the log file to an empty script file and save somewhere in your mission folder.
  6. When calling CPG_fnc_generate provide the path to the file and the generator will take care of the rest.

 

 

 

 

If you do create your own tilesets and feel like sharing please post them to this thread. 🙂

 

Old releases: 

v1.0 - https://www.dropbox.com/s/e8p4n46cvp5acb4/CPG_demo_v1_0.zip?dl=0

  • Like 8

Share this post


Link to post
Share on other sites

Wow, impressive! I love procedurally generated stuff

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, _foley said:

Wow, impressive! I love procedurally generated stuff

 

Same! I'm going to enjoy playing around with this later. Amazing work @mrcurry!

  • Like 1

Share this post


Link to post
Share on other sites

Cheers for the kind words @_foley@Harzach!

I too am a sucker for some good procgen. Combine it with geometry and I love working on this stuff. ^^

I am however starting to run out of ideas and ToDo-list so if you got any cool suggestions you'd like to see please share!

 

I've updated the first post to version 1.1 which brings support for diagonal connections and most importantly removes the requirement 1.0 had that all tile types needs to be present.

See the GoKartTrack tileset below as an example of what you can get with a limited set of tiles (only using tiles with 2 connections).

?imw=5000&imh=5000&ima=fit&impolicy=Lett

 

Note: To achieve the added flexibility connection data is now stored in the tileset-file which means old tilesets have to be reconstructed to match the new format.

  • Like 2

Share this post


Link to post
Share on other sites

A randomly generated compound or even a town would be cool.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×