[FREE] Color Based Level Generator Release

Here’s the first version of a free level generator, which reads every pixel color from an image and generate Gameobjects based on each color.
This could be used for a lot of games such as:

  • Pacman and other maze games
  • Breakout
  • Top down shooters
  • Puzzle games

You make an image in Photoshop or anything similar, it have to be 8x8, 16x16, 32x32 and so on …
You can assign each color to instantiate different gameobjects, as an example you could have colors representing enemies, the player and walls.
Level design is suddenley a lot easier.

Also thanks to melmonkey for making a JS version, and giving excellent feedback

Note: When using it, make sure to use the same texture import settings as the example ones.

Please feel free to come with suggestions for the next version.

Download

Here’s a Pacman example:

Image used:

To generate:

1 Like

Hey everyone!

When I saw Mathias’s first post on this, I was intrigued. I talked with him, gave feedback, and converted his C# work, to JS, for all the JS people out there (like me).

While this is a very cool tool, in it’s current state, we would love to expand on it, and make it an amazing tool. With that in mind, please take a look, and try it out.

Post any and all feedback, as well as feature requests. We have a few in mind, but they are decidedly leaning to what I want to use the tool for.

Let us know what you want to see, and how you want to use it.

Thanks for trying it out.

Something fun I was considering was using a variant on this for some quick-n-dirty AI.

For instance, it could be what’s telling the AI where it should move, where an emergency hiding place is, a tactically important position, all while hiding it from the player, and using a deceptively simple script interface. Theoretically this isn’t so dissimilar from Waypoint technology…but this “Tactic Mapped” AI is theoretically every bit as powerful.

Hmmm. :smile:

One small thing: It needs modifications to work in Unity 2.6. Everyone is now warned.

Well, I’m stuck on mine. Since this is, at heart, your tech, I’ll share it.

It’s a two piece system so far - the “Map” program, which lives on your actual terrain, and the AI program which executes the AI. These were perhaps too simple tests; in hindsight, this might not be so great for pathfinding, but more of managing high-level objectives like defending a particular spot. Anyways, here they are:

TacticMappedAI.js:

class NodeAction
{
  var actionString : String;
  var nodeColor : Color;
}

var speed : float;
var aiActions : NodeAction[];

private var tacticMap : TacticMap;
private var mapWidth : int;
private var mapHeight : int;
private var moveDirection : Vector3;
private var mapLocation : Vector2;
private var oldIndex : int;
private var mapIndex : int;
private var aiCommand = new Array();

function Start()
{
  // Start by finding a tactic map.  Wring some
  // good info out of it.
  tacticMap = FindObjectOfType( TacticMap );
  mapWidth = tacticMap.map.width;
  mapHeight = tacticMap.map.height;
  
  // "Unfurl" the tactical map by converting the map's
  // pixel colors into an array of AI command strings.
  var mapColors : Color[] = tacticMap.map.GetPixels( 0 );
  
  for( var point : Color in mapColors )
  {
    // Read the color, then match it to an index
	// in the aiActions array.  If it matches,
	// assign the command to the AI array.
	for( var action : NodeAction in aiActions )
	{
	  if( point == action.nodeColor )
	  {
	    aiCommand.Add( action.actionString );
		break;
	  }
	}
  }
  
  // Pre-set the move direction, initialize the transition
  // recognition.
  moveDirection = Vector3.forward;
  CalculatePosition();
  mapIndex = ConvertPointToLinear( mapLocation, mapWidth );
  oldIndex = mapIndex;
  
  // That's all for preparation.  See you in FixedUpdate!
}

function FixedUpdate()
{
  CalculatePosition();
  mapIndex = ConvertPointToLinear( mapLocation, mapWidth );
  
  if( mapIndex != oldIndex )
  {
    InterpretAction( aiCommand[mapIndex] );
	oldIndex = mapIndex;
  }
  
  transform.Translate( moveDirection * speed * Time.deltaTime );
}

function InterpretAction( actionString : String ) : void
// There's nothing for it.  This function has to be
// hard-coded by the end-user or their programmer.
//
// In this example, InterpretAction() only handles
// the alteration to moveDirection.  In your game,
// you may want this to have links to firing weapons,
// changing pursuit targets, or other actions.
{
  //Debug.Log( "Acting on instruction: " + actionString );
  if( actionString == "Go Straight" )
  {
    transform.Rotate( 0,0,0 );
  }
  if( actionString == "Go Backward" )
  {
    transform.Rotate( 0,180,0 );
  }
  if( actionString == "Go Left" )
  {
    transform.Rotate( 0,90, 0 );
  }
  if( actionString == "Go Right" )
  {
    transform.Rotate( 0,-90, 0 );
  }
}

function CalculatePosition() : void
// We want to find (0,0), so we take the local dimensions, 
// and divide by the tactical map dimensions to derive a 
// coordinate system.
{
  var mapDims : Vector3 = tacticMap.transform.localScale;
  var mapCenter : Vector2 = tacticMap.CenterCoordinate();
  var mapX : int;
  var mapY : int;
  
  // Calculate the map position...
  mapX = transform.position.x - tacticMap.transform.position.x;
  mapX /= mapDims.x;
  mapX /= tacticMap.trueDimensions.x;
  mapX += mapCenter.x;
  
  mapY = transform.position.z - tacticMap.transform.position.z;
  mapY /= mapDims.y;
  mapX /= tacticMap.trueDimensions.y;
  mapY += mapCenter.y;
  
  mapLocation = Vector2( mapX,mapY );
  
  Debug.Log( "I am at (" + mapLocation.x + ", " + mapLocation.y + ")" );
}

function ConvertPointToLinear( coords : Vector2, width : int ) : int
{
  return coords.x + ( coords.y * width );
}

TacticMap.js:

var map : Texture2D;
var trueDimensions : Vector2;
var centerOrigin : boolean = true;
var debugMode : boolean = false;

private var mat : Material;
private var originCoord : Vector2;

function Start()
{
  // This just shows the tactical map on the mesh.
  if( debugMode )
  {
    mat = renderer.material;
    mat.mainTexture = map;
  }
  
  // Derive the real origin offset.  We do this by
  // looking at the width and height of the map
  // image.
  if( centerOrigin )
  {
    originCoord = Vector2( ( map.width / 2 ), ( map.height / 2 ) );
  }
  else
  {
    originCoord = Vector2.zero;
  }
}

function CenterCoordinate() : Vector2
{
  return originCoord;
}
1 Like

Hey that’s awesome, very nice use of it there.
I actually didn’t consider to use this for an AI of any sort.

Thanks for posting your code, I might try this out myself :slight_smile:

Well, my code has one serious issue: I have a hard time pinpointing a player’s exact position on a mesh. I’m sure my method in that code is not correct. If you can figure that part out, you have a Tactic Map AI solution, too.

If you get that working, give it back to me, and I’ll get started on an advanced version of this. Imagine multiple tactic maps running together, like one that tells AIs where they can move, another that gives higher-level directives (again, defend this, wait for allies, etc.), etc. Subsumptive Tactic Maps, as it were.

absolutely brilliant

This is a really really sweet idea :slight_smile: Nice toy to play with until I can think of something useful to do with it :slight_smile: Cheers!

Thanks for the replies :slight_smile:

Hi Mathias,

This looks really interesting, great work!!!

Yes, this does look really interesting. Great work so far.

Matt.

hey i would like to use this maze generator hope you still active , your link is down

I just updated the dead link upon request, and made some small improvements to the code :slight_smile:

Sorry for ressurecting an old thread like this - But I really wanted to thank you for releasing this! It’s helped me tremendously in my pursuit of finding a way of creating my level from an image. :slight_smile:
Played around with it a little, added some variables and randomrolls, and actually achieved what i wanted to do :slight_smile:
Heres a little image from my playing around with it:)

Everything is placed by color in a lvlimage:)

Hey I didn’t see your post before, but that is so cool… I’m glad you found it useful :smile:

This plugin is awesome. Anyone can reupload the plugin?