This is a map maker I began making for a game I was designing with a friend, that has since been put on hold while everyone is occupied with life/study. The Map Maker was designed to run smooth on touchscreen/Tablet (ipad in particular), and like the rest of the project, it was designed so we could all work on it anywhere.

It’s already functioning, but as I hadn’t decided on a map format there’s no method set up for exporting maps. The live map maker can be accessed here, I’ll copy it over to this server at some point, but it’s currently entangled with parts of the project and I can’t bring it across without taking the entire tileset database with it.

To set it up on your own server you’ll have to replace the load tile function with your own.

The maps have 8 layers and the tiles are already divided up by layer, there are 4 tools for building the map, pencil, rectangle placement, rubber and nine-tool.

The nine-tool works by selecting 9 tiles, 4 for the corners, 4 repeating tiles for the edges, and 1 repeating tile for the centre fill. Any of the 9 tiles can be activated and deactivated with a single click, handy for placing trees, walls, fence, roofs and more.
Placement works the same as a rectangle fill, first click the top left, and then the bottom right.

Placing a fence with the nine-tool.
The left and centre have been turned off.
Placing a fence with the nine-tool.
The centre, top,left, and top-left have been turned off.

Please ask permission before using in commercial projects. We do intend to continue with the game, as we’re probably 50% the way through developing an entirely new engine, reminiscent of retro gaming ostensibly straightforward, while hiding an enormous amount of complexity until advanced players choose to explore it.

Once again, The live Map Maker is available here.

Javascript

activeset=1;
tool="pencil";
rectangletopleft=[-1,-1];
ninetooltopleft=[-1,-1];
function pencil(){tool="pencil";hideninetool();}
function rectangle(){tool="rectangle"; rectangletopleft=[-1,-1];hideninetool();}
function ninetool(){tool="ninetool";showninetool(); ninetooltopleft=[-1,-1];}
function eraser(){tool="eraser";hideninetool();}

ninetooltoggles=[true,true,true,true,true,true,true,true,true];
ninetoolvalues=[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]
ninetoolpos=0;
function ninetool_toggle(n){
	ninetooltoggles[n-1]=ninetooltoggles[n-1]!=true;
	var img=document.getElementById("ninetooloverlay"+n);
	if (ninetooltoggles[n-1]){img.src="Images/Tick.png";} else {img.src="Images/Cross.png";}
	
}




TilesetCombobox="test";
TemplateCombobox="test";
	position="middle";
function MoveLeft()
	{
		if (position=="middle"){
		var map=document.getElementById("map");
		map.id="mapretracted";
		var tilesets=document.getElementById("tilesets");
		tilesets.id="tilesetsexpanded";
		var perspective=document.getElementById("perspective");
		perspective.id="perspectiveleft";
		}
		if (position=="right"){
		var map=document.getElementById("mapexpanded");
		map.id="mapretracted";
		var tilesets=document.getElementById("tilesetsretracted");
		tilesets.id="tilesetsexpanded";
		var perspective=document.getElementById("perspectiveright");
		perspective.id="perspectiveleft";
		}
		position="left";
	}
	
function MoveMiddle()
	{
		if (position=="left"){
		var map=document.getElementById("mapretracted");
		map.id="map";
		var tilesets=document.getElementById("tilesetsexpanded");
		tilesets.id="tilesets";
		var perspective=document.getElementById("perspectiveleft");
		perspective.id="perspective";
		}
		if (position=="right"){
		var map=document.getElementById("mapexpanded");
		map.id="map";
		var tilesets=document.getElementById("tilesetsretracted");
		tilesets.id="tilesets";
		var perspective=document.getElementById("perspectiveright");
		perspective.id="perspective";
		}
		position="middle";
	}

function isnuminner(chr){
	if (chr==="0"){return true;}
	if (chr==="1"){return true;}
	if (chr==="2"){return true;}
	if (chr==="3"){return true;}
	if (chr==="4"){return true;}
	if (chr==="5"){return true;}
	if (chr==="6"){return true;}
	if (chr==="7"){return true;}
	if (chr==="8"){return true;}
	if (chr==="9"){return true;}
	return false;
}

function isnum(a){
l=a.length;
for (i=0;i<l;i++){if (isnuminner(a[i])===false){return false;}}
return true;
}

function IniTiles(tilesetstr){
	
	tile=[[],[],[],[],[],[],[],[]];
	var posx=0;
	var posy=0;
	var set=0;
	for (set=0;set<8;set++){
		for (posy=0;posy<32;posy++){
			var col=[];
			for (posx=0;posx<16;posx++){
				var n=3*(posx+posy*16+set*16*32);
				var a=parseInt(tilesetstr[n],16);
				var b=parseInt(tilesetstr[n+1],16);
				var c=parseInt(tilesetstr[n+2],16);
				var tiley=a;
				var tilex=Math.floor(c/8)*16+b;
				var tileset=c%8;
				if (tilesetstr[n]+tilesetstr[n+1]+tilesetstr[n+2]=="FFF"){
				var src="";
				}
				else
				{
				var src="../GameTiles/Images/"+tileset+"/"+tilex+","+tiley+".png";}
				col[posx]=src;}
			tile[set][posy]=col;}}
		writetiles(1);
		var activetileimg=document.getElementById("selectedtile");
		activetileimg.src=selected_src;
}

function writetiles(set){
	var tilestr="";	
	if (position=="left"){
		var tilesets=document.getElementById("tilesetsexpanded");
		}
		if (position=="middle"){
		var tilesets=document.getElementById("tilesets");
		}
		if (position=="right"){
		var tilesets=document.getElementById("tilesetsretracted");
		}
		for (posy=0;posy<32;posy++){
			for (posx=0;posx<16;posx++){
			
			tilestr+="<img src=\""+tile[set][posy][posx]+"\" class=tile onclick=\"SelectTile(this,"+posy+","+posx+")\">";
		}	tilestr+="<br>";
		}
		tilesets.innerHTML=tilestr;
		selected_src=tile[set][0][0];
}

function changelayer(layer){
writetiles(layer);
activeset=layer;
DrawLayers();	
}

function LoadTiles(name){
	var filename="../GameTiles/Subsets/Sets/"+name;
	var client = new XMLHttpRequest();
	var str=""
	client.open('GET',filename)
	client.onreadystatechange= function(){
		if (client.readyState==4){
var tilesetstring=client.responseText;
IniTiles(tilesetstring);
MakeBlankMap();}}
client.send();
}
mapdata=[[],[],[],[],[],[],[],[]];

selected_x=4;
selected_y=0;
selected_src="";

function MakeBlankMap()
{
	width=document.getElementById("mapwidth").value;
	height=document.getElementById("mapheight").value;	
	if (isnum(width) && isnum(height)){
		for (set=0;set<8;set++){
		for (y=0;y<height;y++){
			mapdata[set][y]=[];
			for (x=0;x<width;x++){
				if (set==1){
				mapdata[1][y][x]=[0,0];		
			}
				else {mapdata[set][y][x]=[255,255];}
			}
		}}
		}
		DrawLayers();
}

function DrawLayers(){
		DrawLayer(0);
		DrawLayer(1);
		DrawLayer(2);
		DrawLayer(3);
		DrawLayer(4);
		DrawLayer(5);
		DrawLayer(6);
		DrawLayer(7);
	}
function drawrectangle(left,top,right,bottom){
	var width=right-left;
	var height=bottom-top;
	var set=activeset;
	for (x=left;x<=right;x++){
			for (y=top;y<=bottom;y++){
				mapdata[set][y][x][1]=selected_y;
				mapdata[set][y][x][0]=selected_x;
		}
	}
	DrawLayers();
	}
	
function drawninetool(left,top,right,bottom){
	var width=right-left;
	var height=bottom-top;
	var set=activeset;
	for (x=left;x<=right;x++){
			for (y=top;y<=bottom;y++){
				if (x===left){
					if (y===top){
						var n=0;
					}
					else if (y===bottom){
						var n=6;
					}
					else {
						var n=3;
					}
				}
				else if (x===right){
					if (y===top){var n=2;
					}
					else if (y===bottom){
						var n=8;
					}
					else {
						var n=5;
					}
				}
				else{
					if (y===top){
						var n=1;
					}
					else if (y===bottom){
						var n=7;
					}
					else {
						var n=4;
						
					}
				}
			if (ninetooltoggles[n]){
			mapdata[set][y][x][1]=ninetoolvalues[n][1];
			mapdata[set][y][x][0]=ninetoolvalues[n][0];}
			}
		}
	DrawLayers();
}

function mapclick(sender,y,x){
	if (tool=="pencil"){overwrite(sender,y,x);}
	if (tool=="rectangle"){if (rectangletopleft[0]===-1) {rectangletopleft=[x,y];}
	else {drawrectangle(rectangletopleft[0],rectangletopleft[1],x,y); rectangletopleft=[-1,-1];}
	}
	if (tool=="ninetool"){if (ninetooltopleft[0]===-1) {ninetooltopleft=[x,y];}
	else {drawninetool(ninetooltopleft[0],ninetooltopleft[1],x,y);ninetooltopleft=[-1,-1];}
	}
}

function overwrite(sender,y,x){
	var set=activeset;
	sender.src=selected_src;
	mapdata[set][y][x][1]=selected_y;
	mapdata[set][y][x][0]=selected_x;
	
	}
	
function SelectTile(sender,y,x){
	if (tool=="ninetool"){
		ninetoolvalues[ninetoolpos][1]=y;
		ninetoolvalues[ninetoolpos][0]=x;	
		var activetileimg=document.getElementById("ninetool"+(ninetoolpos+1));
		activetileimg.src=sender.src;
		ninetoolpos+=1;
		if (ninetoolpos==9){ninetoolpos=0;}
		}
	else
	{
		selected_y=y;
		selected_x=x;
		selected_src=sender.src;
		sender.class="tile,selected"
		var activetileimg=document.getElementById("selectedtile");
		activetileimg.src=selected_src;
	}
}
function DrawLayer(set){
	var canvas=document.getElementById("maptiles"+set);
	canvasinner="";
	for (y=0;y<height;y++){
			for (x=0;x<width;x++){
				if (mapdata[set][y][x][0]===255){
					canvasinner+="<img class=tile src=\"Images/Empty.png\" onclick=\"mapclick(this,"+y+","+x+")\">";
				}
				else
				{
					canvasinner+="<img class=tile onclick=\"mapclick(this,"+y+","+x+")\" src="+tile[set][mapdata[set][y][x][1]][mapdata[set][y][x][0]]+">";
				}
			}
			canvasinner+="<br>";
		}
		canvas.innerHTML=canvasinner;
}

function NewMap()
{	
	activeset=1;
	LoadTiles("Town");
	}

function MoveRight()
	{
		if (position=="left"){
		var map=document.getElementById("mapretracted");
		map.id="mapexpanded";
		var tilesets=document.getElementById("tilesetsexpanded");
		tilesets.id="tilesetsretracted";
		var perspective=document.getElementById("perspectiveleft");
		perspective.id="perspectiveright";
		}
		if (position=="middle"){
		var map=document.getElementById("map");
		map.id="mapexpanded";
		var tilesets=document.getElementById("tilesets");
		tilesets.id="tilesetsretracted";
		var perspective=document.getElementById("perspective");
		perspective.id="perspectiveright";
		}
		position="right";
	}
	
function ExpandOptions(){
	var optionsbox=document.getElementById("optionsboxcollapsed");
	optionsbox.id="optionsbox";
	optionsbox.innerHTML="<button id=collapsebutton onclick=\"CollapseOptions()\"></button>"+
	"<div class=bordered><div class=ilb><div class=heading>Map Width:</div><input name=mapwidth id=mapwidth class=small><br>"+
	"<div class=heading>Map Height:</div><input id=mapheight name=mapheight class=small><br>"+
	"<button onclick=\"NewMap()\">New Map</button></div>"+
	"<div class=ilb><div class=heading>Tileset:</div>"+TilesetCombobox+
	"<br><div class=heading>Template:</div>"+TemplateCombobox+
	"</div></div><div class=bordered>"+
	"<div class=ilb><div class=heading>Map Name:</div><input name=mapname id=mapname style=\"width:64px\"><br>"+
	"<br><textarea>description</textarea>"+
	"</div></div><br>";	
}

function CollapseOptions(){
	var optionsbox=document.getElementById("optionsbox");
	optionsbox.id="optionsboxcollapsed";
	optionsbox.innerHTML="<button id=expandbutton onclick=\"ExpandOptions()\"></button>";	
	
}

function showninetool(){
	var ninetool=document.getElementById("ninetoolhidden");
	if (ninetool===null){//skip
	}
	else
	{
	ninetool.id="ninetoolcontainer";}
	}
	
function hideninetool(){
	var ninetool=document.getElementById("ninetoolcontainer");
	if (ninetool===null){//skip
	}
	else
	{
	ninetool.id="ninetoolhidden";}
	}
	
</script>

CSS

img.selected{width:30px;height:30px;border:solid 1px #FF0000;}
img.tile{width:32px;height:32px;}
.small{width:32px;}
.heading{width:96px;display:inline-block;}
div.bordered{border:1px solid;display:inline-block;}
div.ilb{display:inline-block;}
#toolbar{position:absolute;bottom:0px;left:40%;width:161px;background:#FFF;border:1px solid;z-index:10;}
#ninetoolcontainer{position:absolute;bottom:33px;left:45%;width:97px;background:#FFF;border:1px solid;z-index:10;height:97px;}
#ninetool{position:absolute;bottom:0px;left:0px;;width:97px;background:#FFF;border:1px solid;z-index:10;height:97px;}
#ninetooloverlay{position:absolute;bottom:0px;left:0px;width:97px;border:1px solid;z-index:10;height:97px;}
#ninetoolhidden{position:absolute;bottom:33px;left:45%;width:0px; height:1px; overflow:hidden;background:#FFF;z-index:10;height:97px;}
#expandbutton{height:32px;width:32px;display:inline-block;}
#collapsebutton{height:32px;width:32px;display:inline-block;}
#optionsboxcollapsed{position:absolute;left:5%;top:0px;width:5%;height:5%;z-index:10;}
#optionsbox{position:absolute;left:5%;top:0px;width:50%;height:60%;border:1px solid; background:#FFF;z-index:10;}
button.layerselectbutton{width:12%;display:inline-block;z-index:10;}
#layerselect{position:absolute;height:5%;width:20%;left:40%;top:0px;border:solid 1px;z-index:10;}
#maptiles0{white-space:nowrap;position:absolute;top:0px;z-index:2;opacity:1;}
#maptiles1{white-space:nowrap;position:absolute;top:0px;z-index:3;opacity:1;}
#maptiles2{white-space:nowrap;position:absolute;top:0px;z-index:4;opacity:1;}
#maptiles3{white-space:nowrap;position:absolute;top:0px;z-index:5;opacity:1;}
#maptiles4{white-space:nowrap;position:absolute;top:0px;z-index:6;opacity:1;}
#maptiles5{white-space:nowrap;position:absolute;top:0px;z-index:7;opacity:1;}
#maptiles6{white-space:nowrap;position:absolute;top:0px;z-index:8;opacity:1;}
#maptiles7{white-space:nowrap;position:absolute;top:0px;z-index:9;opacity:1;}
#map{width:65%;height:100%;overflow:scroll;white-space:nowrap;position:relative;z-index:1;}
#mapexpanded{width:90%;height:100%;overflow:scroll;white-space:nowrap;position:relative;z-index:1;}
#mapretracted{width:40%;height:100%;overflow:scroll;white-space:nowrap;position:relative;z-index:1;}
#perspective{position:absolute;float:left;left:65%;height:100%;width:5%;background:#333;top:0px;}
#perspectiveleft{position:absolute;float:left;left:40%;height:100%;width:5%;background:#333;top:0px;}
#perspectiveright{position:absolute;float:left;left:90%;height:100%;width:5%;background:#333;top:0px;}
#tilesets{position:absolute;right:0px;width:25%;height:100%;top:0px;overflow:scroll;white-space:nowrap;}
#tilesetsexpanded{position:absolute;right:0px;width:50%;height:100%;top:0px;overflow:scroll;white-space:nowrap;}
#tilesetsretracted{position:absolute;right:0px;width:0%;height:100%;top:0px;overflow:scroll;white-space:nowrap;}
.tile{width:32px;height:32px;display: inline-block;}
button.move{width:100%;height:33.2%;}

HTML

<div id=perspective>
<button class=move onclick="MoveLeft()"><</button>
<button class=move onclick="MoveMiddle()">|</button>
<button class=move onclick="MoveRight()">></button></div>
<div id=layerselect><button class=layerselectbutton onclick="changelayer(0)">0</button><button class=layerselectbutton onclick="changelayer(1)">1</button><button class=layerselectbutton onclick="changelayer(2)">2</button><button class=layerselectbutton onclick="changelayer(3)">3</button><button class=layerselectbutton onclick="changelayer(4)">4</button><button class=layerselectbutton onclick="changelayer(5)">5</button><button class=layerselectbutton onclick="changelayer(6)">6</button><button class=layerselectbutton onclick="changelayer(7)">7</button></div>

<div id=optionsboxcollapsed><button id=expandbutton onclick="ExpandOptions()"></button></div>

<div id=map>
<div id=maptiles0><h1>NO MAP LOADED</h1></div>
<div id=maptiles1><h1>NO MAP LOADED</h1></div>
<div id=maptiles2><h1>NO MAP LOADED</h1></div>
<div id=maptiles3><h1>NO MAP LOADED</h1></div>
<div id=maptiles4><h1>NO MAP LOADED</h1></div>
<div id=maptiles5><h1>NO MAP LOADED</h1></div>
<div id=maptiles6><h1>NO MAP LOADED</h1></div>
<div id=maptiles7><h1>NO MAP LOADED</h1></div>


</div>

<div id=tilesets></div>

<div id=toolbar><img id=selectedtile class=tile src="Images/Empty.png"><img class=tile src="Images/Pencil.png" onclick="pencil()"><img class=tile src="Images/Rectangle.png" onclick="rectangle()"><img class=tile src="Images/NineTool.png" onclick="ninetool()"><img class=tile src="Images/Eraser.png" onclick="eraser()"></div>

<div id=ninetoolhidden>
<div id=ninetool>
<img id=ninetool1 class=tile src="Images/Border.png"><img id=ninetool2 class=tile src="Images/Border.png"><img id=ninetool3 class=tile src="Images/Border.png">
<img id=ninetool4 class=tile src="Images/Border.png"><img id=ninetool5 class=tile src="Images/Border.png"><img id=ninetool6 class=tile src="Images/Border.png">
<img id=ninetool7 class=tile src="Images/Border.png"><img id=ninetool8 class=tile src="Images/Border.png"><img id=ninetool9 class=tile src="Images/Border.png">
</div>
<div id=ninetooloverlay>
<img id=ninetooloverlay1 class=tile src="Images/Tick.png" onclick="ninetool_toggle(1);"><img id=ninetooloverlay2 class=tile src="Images/Tick.png" onclick="ninetool_toggle(2);"><img id=ninetooloverlay3 class=tile src="Images/Tick.png" onclick="ninetool_toggle(3);">
<img id=ninetooloverlay4 class=tile src="Images/Tick.png" onclick="ninetool_toggle(4);"><img id=ninetooloverlay5 class=tile src="Images/Tick.png" onclick="ninetool_toggle(5);"><img id=ninetooloverlay6 class=tile src="Images/Tick.png" onclick="ninetool_toggle(6);">
<img id=ninetooloverlay7 class=tile src="Images/Tick.png" onclick="ninetool_toggle(7);"><img id=ninetooloverlay8 class=tile src="Images/Tick.png" onclick="ninetool_toggle(8);"><img id=ninetooloverlay9 class=tile src="Images/Tick.png" onclick="ninetool_toggle(9);">
</div>
</div>
Back to top