JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

choose portal: <select id='select-portal'></select>

<div id='mex-container'>
    
    <div id='mex-map'></div>
    
    <div id='mex-pets'></div>
    
    <div id='mex-controls'></div>
    
    <div id='mex-interact'></div>

</div>


<hr>

map editor, 4 image layers + interactive things in database.

<div id='editor-container'>
    
    <!-- Settings, new/load map, etc. -->
    <div id='editor-settings'>
        <span>
            <button id='create-map-btn'>New blank map</button>
        </span>
        <span>
            <select id='select-map'>[js populate]</select>
            <button id='load-map-btn'>Load map</button>
        </span>
        <span>
            Show grid? <input type='checkbox' id='toggle-grid' checked>
        </span>
        <span>
            Show all layers? <input type='checkbox' id='toggle-layers' checked>
        </span>
    </div>
    
    <!-- Switch between layers/tabs. -->
    <div id='layer-btns'>
        <div class='layer-btn' data-layer='1'>Terrain</div>
        <div class='layer-btn' data-layer='2'>Scenery</div>
        <div class='layer-btn' data-layer='3'>Scenery 2/Zones</div>
        <div class='layer-btn' data-layer='4'>Passability</div>
    </div>
    
    <!-- Spritesheet to click on, select. -->
    <div id='tileset-container'></div>
    
    <!-- Zoomed-in section of map. Tile canvas. -->
    <div id='tiles-container'></div>

    <!-- Pixel image, 600 x 300. -->
    <div id='map-container'></div>

</div>

CSS

div, img, canvas, button, input {
    box-sizing: border-box;
}

#mex-container {
    
    
}

#editor-container {
    width: 970px;
}

#editor-container canvas {
    cursor: pointer;
    margin: auto;
}

/*
* Grid of tiles being edited. Small chunk of map.
* Click a tile on canvas to paint it.
*/
#tiles-container {
    min-height: 200px;
    background-color: silver;
    margin: 20px 0;
}
#tiles-container canvas {
    box-shadow: 0 0 0 1px blue;
}

/*
* Contains one tileset canvas.
* The image just switches between tilesets.
*/
#tileset-container {
    height: 250px;
    overflow: auto;
    padding: 10px;
    background-color: silver;
}
#tileset-container canvas {
    margin: auto;
    box-shadow: 0 0 0 1px blue;
}

/*
* Contains 2 canvases. On bottom, the actual
* pixel map. On top, transparent except for
* red square that indicates chunk being edited.
*/
#map-container {
    height: 320px;
    padding: 10px;
    text-align: center;
    background-color: silver;
    position: relative;
}
#map-container canvas {
    position: absolute;
    top: 10px;
    left: 180px;
    box-shadow: 0 0 0 1px blue; 
}

JavaScript

const db = {
    
    /*
    * Actual tile data (terrain, passable, zone)
    * is stored in images. URL is "map{id}.png".
    * Later add restrictions: month, time, special event...
    */
    maps: [
        {
            id: 1, name: "Grass Continent", 
            type: "world", surround: 7
        },{
            id: 2, name: "Icy Continent", 
            type: "world", surround: 7
        },{
            id: 3, name: "Arid Continent", 
            type: "world", surround: 7
        },{
            id: 4, name: "Ocean Continent", 
            type: "world", surround: 7
        },{
            id: 5, name: "Forest Village", 
            type: "town", surround: 7
        },{
            id: 6, name: "Griffin City", 
            type: "town", surround: 7
        },{
            id: 7, name: "Fortress Ruins", 
            type: "town", surround: 7
        },{
            id: 8, name: "Dragon Shrine", 
            type: "town", surround: 7
        },
    ],
    
    /*
    * Special tiles placed on maps.
    * Pointing to somewhere else.
    * Can be one-way, or in matching pairs.
    */
    portals: [
        {
            id: 1, mapId: 1, mapX: 5, mapY: 5, 
            toMap: 2, toX: 8, toY: 8
        },{
            id: 2, mapId: 2, mapX: 8, mapY: 8, 
            toMap: 1, toX: 5, toY: 5
        },{
            id: 3, mapId: 1, mapX: 10, mapY: 10, 
            toMap: 3, toX: 8, toY: 8
        },{
            id: 4, mapId: 3, mapX: 8, mapY: 8, 
            toMap: 1, toX: 10, toY: 10
        }
    ],
    
    /*
    * Wildlife and other interactive things
    * that pop up while player moves around.
    */
    world_resources: [
        {
            id: 1, name: "", sprite: "",
            map: 1, zones: []
        }
    ],
    
    /*
    * Similar to above, but visible on map
    * and fixed (scattered when map's entered).
    * Extra data for positioning, passability.
    */
    town_resources: [
        {
            id: 1, name: "Farmer NPC", sprite: 6,
  ...