
Tinyswords Tilemap
- 60 installs
- 38 repo stars
- Updated January 16, 2026
- chongdashu/phaserjs-tinyswords
Build layered tilemaps with the Tiny Swords asset pack, handling 64x64 grids, elevation, shadows, and animated water foam.
About
Creates depth-layered tilemaps from the Tiny Swords tileset using elevation, shadow positioning, and staggered water animation. Used when a developer renders game terrain or levels with this asset pack.
- Elevation and shadow layering for depth
- Animated water foam and terrain color variants
Tinyswords Tilemap by the numbers
- 60 all-time installs (skills.sh)
- Ranked #145 of 247 Game Development skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/chongdashu/phaserjs-tinyswords --skill tinyswords-tilemapAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 60 |
|---|---|
| repo stars | ★ 38 |
| Last updated | January 16, 2026 |
| Repository | chongdashu/phaserjs-tinyswords ↗ |
What it does
Build layered tilemaps with the Tiny Swords asset pack, handling 64x64 grids, elevation, shadows, and animated water foam.
Files
Tiny Swords Tilemap
Create beautiful, layered tilemaps using the Tiny Swords asset pack with proper elevation, shadows, and animated water effects.
Philosophy: Elevation as Visual Storytelling
Tilemaps are not just grids of images—they are layered compositions that create depth and dimensionality. The Tiny Swords tileset uses a clever layering system where shadows and elevation work together to create the illusion of 3D terrain on a 2D plane.
Before placing tiles, ask:
- What elevation levels does this area need?
- Where will the player's eye be drawn?
- How do shadows reinforce the sense of height?
- Does the water feel alive with staggered foam animations?
Core principles:
1. Layers create depth: Every elevation level adds Shadow + Elevated Ground layers. The stack builds visual height. 2. Shadows anchor elevation: A shadow one tile below the walkable surface makes cliffs feel real. 3. Animation breaks uniformity: Water foam sprites starting at different frames prevent the "wallpaper effect." 4. Color distinguishes levels: Using different terrain colors for each elevation helps players parse the map instantly.
Tile Specifications
| Element | Size | Notes |
|---|---|---|
| Standard tile | 64x64 px | Base grid unit for all terrain |
| Shadow sprite | 128x128 px | Placed on 64x64 grid, overlaps adjacent tiles |
| Animation frame | 64x64 px | Water foam frames in sprite sheets |
The Six Terrain Components
1. BG Color - Water background fill (bottommost layer) 2. Water Foam - Animated waves where terrain meets water 3. Flat Ground - Lowest walkable terrain adjacent to water 4. Shadows - Depth sprites placed below elevated areas 5. Elevated Ground - Raised terrain with cliff edges 6. Stairs - Connectors between elevation levels
Layer Ordering (Bottom to Top)
┌─────────────────────────────────────────┐
│ Elevated Ground (Level N) │ ← Repeat for each
│ Shadow (Level N) │ elevation level
├─────────────────────────────────────────┤
│ Elevated Ground (Level 2) │
│ Shadow (Level 2) │
├─────────────────────────────────────────┤
│ Elevated Ground (Level 1) │
│ Shadow (Level 1) │
├─────────────────────────────────────────┤
│ Flat Ground │
│ Water Foam (animated) │
│ BG Color (water background) │
└─────────────────────────────────────────┘Shadow Positioning
Shadows create the illusion of height. Position each shadow sprite one 64x64 tile below the walkable elevated ground it belongs to.
Grid visualization:
┌────┬────┬────┐
│ │WALK│ │ ← Elevated walkable area
├────┼────┼────┤
│ │SHAD│ │ ← Shadow positioned here (one tile down)
└────┴────┴────┘The 128x128 shadow sprite is placed on the 64x64 grid, allowing it to overlap and create soft depth transitions.
Water Foam Animation
Water foam is animated and requires staggered frame starts to look natural.
Implementation pattern:
// Each foam sprite instance starts at a random/offset frame
foamSprites.forEach((sprite, index) => {
sprite.animationOffset = index % totalFrames;
// OR
sprite.animationOffset = Math.floor(Math.random() * totalFrames);
});This prevents the synchronized "breathing" effect where all water animates in lockstep.
Stair Configurations
Stairs connect elevation levels with two configurations based on adjacent terrain:
| Adjacent Terrain | Stair Pieces | Description |
|---|---|---|
| Walkable ground | Single center piece | Minimal connection |
| Cliff edges | Two pieces (top + bottom) | Full stair with cliff transitions |
Terrain Color Variants
Five terrain colors are available (Tilemap_color1.png through Tilemap_color5.png). Use different colors for different elevation levels to enhance visual distinction:
Level 3: color5 (purple/dark)
Level 2: color3 (brown)
Level 1: color1 (green)
Flat: color2 (sand/beach)Mix colors intentionally—there's no required order, but contrast between adjacent levels improves readability.
Anti-Patterns to Avoid
Flat layering: Placing all terrain on a single layer
- Why bad: Loses depth, looks like a flat texture
- Better: Use the full layer stack with shadows
Synchronized water animation: All foam sprites on the same frame
- Why bad: Creates artificial "pulsing" effect
- Better: Stagger animation start frames
Shadow misalignment: Shadows directly under or beside elevated ground
- Why bad: Breaks the height illusion
- Better: Shadow exactly one tile below walkable surface
Monotone elevation: Same terrain color for all levels
- Why bad: Hard to visually parse map depth
- Better: Distinct colors per elevation level
Ignoring cliff types: Using wrong cliff edge for context
- Why bad: Visual discontinuity at terrain boundaries
- Better: Use water-facing cliffs near water, terrain-facing cliffs near lower ground
Variation Guidance
Maps should vary based on context:
- Island maps: More water foam, fewer elevation levels
- Mountain maps: Multiple elevation levels, less water
- Mixed terrain: Blend all elements with color variety
Avoid converging on:
- Always using color1 for everything
- Exactly 2 elevation levels every time
- Identical stair placement patterns
- Uniform shadow density
Asset Paths Reference
See references/asset-paths.md for complete file paths in this project.
Remember
The Tiny Swords tileset is designed for layered depth. Every shadow, every foam animation offset, every color choice contributes to a map that feels alive and dimensional. Trust the layer system—it's engineered to create beautiful results when used correctly.
Asset Paths
Complete file paths for Tiny Swords tilemap assets in this project.
Base Path
All assets are located under:
public/assets/tinyswords/Tileset Assets
Core Tilemap Files
Terrain/Tileset/
├── Tilemap_color1.png # Green grass variant
├── Tilemap_color2.png # Sand/beach variant
├── Tilemap_color3.png # Brown earth variant
├── Tilemap_color4.png # Gray stone variant
├── Tilemap_color5.png # Dark/purple variant
├── Shadow.png # 128x128 elevation shadow
├── Water Foam.png # Animated water edge (sprite sheet)
├── Water Foam.aseprite # Source file for water animation
└── Water Background color.png # Water fill colorFull Paths for Import
// ES Module imports (if using bundler)
import tilemap1 from '/assets/tinyswords/Terrain/Tileset/Tilemap_color1.png';
import tilemap2 from '/assets/tinyswords/Terrain/Tileset/Tilemap_color2.png';
import tilemap3 from '/assets/tinyswords/Terrain/Tileset/Tilemap_color3.png';
import tilemap4 from '/assets/tinyswords/Terrain/Tileset/Tilemap_color4.png';
import tilemap5 from '/assets/tinyswords/Terrain/Tileset/Tilemap_color5.png';
import shadow from '/assets/tinyswords/Terrain/Tileset/Shadow.png';
import waterFoam from '/assets/tinyswords/Terrain/Tileset/Water Foam.png';
import waterBg from '/assets/tinyswords/Terrain/Tileset/Water Background color.png';// Runtime loading (browser)
const ASSET_BASE = '/assets/tinyswords/Terrain/Tileset/';
const TILESET_PATHS = {
tilemap: [
`${ASSET_BASE}Tilemap_color1.png`,
`${ASSET_BASE}Tilemap_color2.png`,
`${ASSET_BASE}Tilemap_color3.png`,
`${ASSET_BASE}Tilemap_color4.png`,
`${ASSET_BASE}Tilemap_color5.png`,
],
shadow: `${ASSET_BASE}Shadow.png`,
waterFoam: `${ASSET_BASE}Water Foam.png`,
waterBackground: `${ASSET_BASE}Water Background color.png`,
};Decoration Assets
Rocks
Terrain/Decorations/Rocks/
├── Rock1.png
├── Rock2.png
├── Rock3.png
└── Rock4.pngBushes
Terrain/Decorations/Bushes/
├── Bushe1.png
├── Bushe2.png
├── Bushe3.png
├── Bushe4.png
└── Bushes.asepriteClouds
Terrain/Decorations/Clouds/
├── Clouds_01.png
├── Clouds_02.png
├── Clouds_03.png
├── Clouds_04.png
├── Clouds_05.png
├── Clouds_06.png
├── Clouds_07.png
├── Clouds_08.png
└── Clouds.asepriteWater Rocks
Terrain/Decorations/Rocks in the Water/
├── Water Rocks_01.png
├── Water Rocks_01.aseprite
├── Water Rocks_02.png
├── Water Rocks_02.aseprite
├── Water Rocks_03.png
├── Water Rocks_03.aseprite
├── Water Rocks_04.png
└── Water Rocks_04.asepriteRubber Duck (Easter Egg)
Terrain/Decorations/Rubber Duck/
├── Rubber duck.png
└── Rubber Duck.asepriteResource Assets
Trees
Terrain/Resources/Wood/Trees/
├── Tree1.png
├── Tree2.png
├── Tree3.png
├── Tree4.png
├── Stump 1.png
├── Stump 2.png
├── Stump 3.png
├── Stump 4.png
└── Trees.asepriteGold
Terrain/Resources/Gold/Gold Stones/
├── Gold Stone 1.png
├── Gold Stone 1_Highlight.png
├── Gold Stone 2.png
├── Gold Stone 2_Highlight.png
├── Gold Stone 3.png
├── Gold Stone 3_Highlight.png
├── Gold Stone 4.png
├── Gold Stone 4_Highlight.png
├── Gold Stone 5.png
├── Gold Stone 5_Highlight.png
├── Gold Stone 6.png
├── Gold Stone 6_Highlight.png
└── Gold Stones.aseprite
Terrain/Resources/Gold/Gold Resource/
├── Gold_Resource.png
├── Gold_Resource_Highlight.png
└── Gold Resource.asepriteWood Resource
Terrain/Resources/Wood/Wood Resource/
└── Wood Resource.pngMeat
Terrain/Resources/Meat/Meat Resource/
└── Meat Resource.png
Terrain/Resources/Meat/Sheep/
├── Sheep_Idle.png
├── Sheep_Grass.png
├── Sheep_Move.png
└── Sheep.asepriteTools
Terrain/Resources/Tools/
├── Tool_01.png
├── Tool_02.png
├── Tool_03.png
└── Tool_04.pngBuilding Assets
Buildings are available in 5 team colors: Blue, Red, Yellow, Black, Purple
Buildings/{Color} Buildings/
├── Castle.png
├── Tower.png
├── House1.png
├── House2.png
└── House3.pngExample paths:
const BUILDING_COLORS = ['Blue', 'Red', 'Yellow', 'Black', 'Purple'];
function getBuildingPath(color, building) {
return `/assets/tinyswords/Buildings/${color} Buildings/${building}.png`;
}
// Usage
getBuildingPath('Blue', 'Castle'); // '/assets/tinyswords/Buildings/Blue Buildings/Castle.png'Unit Assets
Units are available in 5 team colors with multiple animation states.
Units/{Color} Units/{UnitType}/
└── {UnitType}_{Animation}.pngUnit Types and Animations
| Unit | Animations |
|---|---|
| Warrior | Idle, Run, Attack1, Attack2, Guard |
| Archer | Idle, Run, Shoot + Arrow.png |
| Lancer | Idle, Run, + 8-directional Attack/Defence |
Example path:
function getUnitPath(color, unitType, animation) {
return `/assets/tinyswords/Units/${color} Units/${unitType}/${unitType}_${animation}.png`;
}
// Usage
getUnitPath('Blue', 'Warrior', 'Idle'); // '/assets/tinyswords/Units/Blue Units/Warrior/Warrior_Idle.png'Asset Loading Helper
class TinySwordsAssets {
constructor(basePath = '/assets/tinyswords') {
this.basePath = basePath;
this.cache = new Map();
}
async loadImage(path) {
if (this.cache.has(path)) {
return this.cache.get(path);
}
const img = new Image();
img.src = `${this.basePath}/${path}`;
await new Promise((resolve, reject) => {
img.onload = resolve;
img.onerror = reject;
});
this.cache.set(path, img);
return img;
}
async loadTileset(colorIndex = 1) {
return this.loadImage(`Terrain/Tileset/Tilemap_color${colorIndex}.png`);
}
async loadShadow() {
return this.loadImage('Terrain/Tileset/Shadow.png');
}
async loadWaterFoam() {
return this.loadImage('Terrain/Tileset/Water Foam.png');
}
async loadAllTilesets() {
return Promise.all([
this.loadTileset(1),
this.loadTileset(2),
this.loadTileset(3),
this.loadTileset(4),
this.loadTileset(5),
this.loadShadow(),
this.loadWaterFoam(),
]);
}
}Layer System
Comprehensive guide to the Tiny Swords tilemap layer architecture.
Layer Philosophy
The layer system creates pseudo-3D depth through careful ordering. Each layer serves a specific visual purpose, and skipping layers breaks the illusion.
Complete Layer Stack
From bottom (rendered first) to top (rendered last):
Layer Index | Layer Name | Purpose
------------|---------------------|----------------------------------
0 | BG Color | Water/void fill
1 | Water Foam | Animated water edge effect
2 | Flat Ground | Base walkable terrain
3 | Shadow (Level 1) | Depth for first elevation
4 | Elevated (Level 1) | First raised terrain
5 | Shadow (Level 2) | Depth for second elevation
6 | Elevated (Level 2) | Second raised terrain
... | ... | Pattern repeats for more levels
N | Decorations | Trees, rocks, buildings (optional)
N+1 | Units/Characters | Moving entities (optional)Layer Rendering Order
Critical: Layers MUST be rendered in order from lowest index to highest. Later layers occlude earlier layers.
// Correct rendering order
function renderMap(layers) {
// Sort by layer index ascending
layers.sort((a, b) => a.index - b.index);
for (const layer of layers) {
renderLayer(layer);
}
}Layer Types Explained
BG Color Layer (Index 0)
The bottommost layer fills empty space with water background color.
// Fill entire canvas with water background
ctx.fillStyle = '#3498db'; // Or use Water Background color.png
ctx.fillRect(0, 0, canvasWidth, canvasHeight);Water Foam Layer (Index 1)
Animated sprites at water/land boundaries.
Key requirements:
- Place along edges where Flat Ground meets water
- Stagger animation start frames
- Loop continuously
class FoamSprite {
constructor(x, y, totalFrames) {
this.x = x;
this.y = y;
this.currentFrame = Math.floor(Math.random() * totalFrames);
this.totalFrames = totalFrames;
}
update(deltaTime) {
// Advance frame based on time
this.currentFrame = (this.currentFrame + 1) % this.totalFrames;
}
}Flat Ground Layer (Index 2)
The lowest elevation walkable terrain. Directly adjacent to water.
Tile selection:
- Use edge tiles where adjacent to water
- Use fill tiles for interior
- Use corner tiles for diagonal water adjacency
Shadow Layers (Index 3, 5, 7, ...)
Shadow layers appear immediately before their corresponding elevated ground.
Positioning rule: Shadow at grid (x, y+1) for elevated ground at (x, y).
function addShadowForElevation(elevatedTileX, elevatedTileY, layerIndex) {
const shadowLayer = layerIndex - 1; // Shadow is always one layer below
const shadowY = elevatedTileY + 1; // Shadow is one tile below
placeShadow(elevatedTileX, shadowY, shadowLayer);
}Elevated Ground Layers (Index 4, 6, 8, ...)
Raised terrain with two cliff edge types:
1. Terrain-facing cliffs: Used when adjacent to lower walkable ground 2. Water-facing cliffs: Used when adjacent to water
function selectCliffType(tile, adjacentTile) {
if (adjacentTile.type === 'WATER') {
return 'water_cliff';
} else if (adjacentTile.elevation < tile.elevation) {
return 'terrain_cliff';
} else {
return 'fill'; // Same elevation, use center tile
}
}Multi-Elevation Example
A map with 3 elevation levels:
Level 0 (Water): BG Color
Level 1 (Beach): Water Foam + Flat Ground
Level 2 (Grass): Shadow + Elevated (color1)
Level 3 (Hill): Shadow + Elevated (color3)
Level 4 (Peak): Shadow + Elevated (color5)Total layers: 9 (BG, Foam, Flat, Shadow1, Elev1, Shadow2, Elev2, Shadow3, Elev3)
Layer Data Structure
const mapData = {
width: 20, // tiles
height: 15, // tiles
layers: [
{
index: 0,
name: 'background',
type: 'fill',
color: '#2980b9'
},
{
index: 1,
name: 'water_foam',
type: 'animated',
tiles: [
{ x: 0, y: 5, frameOffset: 0 },
{ x: 1, y: 5, frameOffset: 2 },
// ...
]
},
{
index: 2,
name: 'flat_ground',
type: 'static',
tileset: 'Tilemap_color2.png',
tiles: [
{ x: 0, y: 6, tileId: 'center' },
{ x: 1, y: 6, tileId: 'edge_north' },
// ...
]
},
// ... more layers
]
};Z-Index Considerations for Game Engines
When using game engines (Phaser, PixiJS, etc.), map layer indices to z-index values:
// Reserve z-index ranges for different purposes
const Z_INDEX = {
BACKGROUND: 0,
WATER_FOAM: 10,
FLAT_GROUND: 20,
SHADOWS_START: 30, // 30, 50, 70, ...
ELEVATION_START: 40, // 40, 60, 80, ...
DECORATIONS: 1000,
UNITS: 2000,
UI: 3000
};
function getElevationZIndex(level) {
return Z_INDEX.ELEVATION_START + (level - 1) * 20;
}
function getShadowZIndex(level) {
return Z_INDEX.SHADOWS_START + (level - 1) * 20;
}Performance Optimization
Static Layer Caching
Layers that don't animate can be pre-rendered to off-screen canvases:
// Cache static layers
const staticLayerCanvas = document.createElement('canvas');
const staticCtx = staticLayerCanvas.getContext('2d');
// Render BG, Flat Ground, Shadows, Elevated once
renderStaticLayers(staticCtx);
// In game loop, only re-render animated layers
function render() {
ctx.drawImage(staticLayerCanvas, 0, 0); // Cached static
renderWaterFoam(ctx); // Animated
renderUnits(ctx); // Dynamic
}Culling Off-Screen Tiles
Only render tiles visible in the viewport:
function getVisibleTiles(viewport, tileSize) {
const startX = Math.floor(viewport.x / tileSize);
const startY = Math.floor(viewport.y / tileSize);
const endX = Math.ceil((viewport.x + viewport.width) / tileSize);
const endY = Math.ceil((viewport.y + viewport.height) / tileSize);
return { startX, startY, endX, endY };
}Tile Specifications
Detailed technical specifications for Tiny Swords tilemap elements.
Grid System
The entire tilemap operates on a 64x64 pixel grid. All positioning, collision detection, and coordinate systems should use this as the base unit.
1 tile = 64px × 64px
Map coordinate (x, y) → pixel position (x * 64, y * 64)Tile Types and Dimensions
Standard Tiles (64x64)
| Tile Type | Dimensions | Sprite Sheet Layout |
|---|---|---|
| Flat Ground | 64x64 | Single tile per variant |
| Elevated Ground | 64x64 | Includes edge pieces |
| Stairs | 64x64 | Top, center, bottom variants |
| Water Foam | 64x64 | Animation frames horizontal |
| BG Color | 64x64 | Solid fill tile |
Oversized Sprites
| Sprite Type | Dimensions | Grid Placement |
|---|---|---|
| Shadow | 128x128 | Centered on 64x64 grid cell |
The 128x128 shadow sprite creates overlap effects. When placed at grid position (x, y), it visually extends into adjacent cells, creating soft shadow transitions.
Tilemap Color Variants
Each Tilemap_colorN.png contains the same tile arrangement in different color palettes:
| File | Suggested Use | Color Tone |
|---|---|---|
| Tilemap_color1.png | Grass, meadows | Green |
| Tilemap_color2.png | Sand, beaches | Tan/Yellow |
| Tilemap_color3.png | Dirt, earth | Brown |
| Tilemap_color4.png | Stone, rock | Gray |
| Tilemap_color5.png | Dark terrain | Purple/Dark |
Edge and Corner Pieces
Each tilemap spritesheet includes:
Flat Ground Edges
- 4 cardinal edges (N, S, E, W)
- 4 outer corners (NE, NW, SE, SW)
- 4 inner corners (for concave shapes)
- 1 center fill tile
Elevated Ground Edges
- Cliff edges (facing lower terrain): 4 cardinals + 4 corners
- Water edges (facing water): 4 cardinals + 4 corners
- Center fill tiles
Edge Selection Logic
IF adjacent_tile is WATER:
use water-facing cliff edge
ELSE IF adjacent_tile is LOWER_ELEVATION:
use terrain-facing cliff edge
ELSE IF adjacent_tile is SAME_ELEVATION:
use center fill or appropriate connectionWater Foam Sprite Sheet
The Water Foam.png sprite sheet contains animation frames arranged horizontally.
| Property | Value |
|---|---|
| Frame size | 64x64 |
| Animation type | Loop |
| Frame count | Check sprite sheet width ÷ 64 |
Frame Extraction
// Extract frame N from sprite sheet
const frameWidth = 64;
const frameHeight = 64;
const sourceX = frameIndex * frameWidth;
const sourceY = 0;
ctx.drawImage(
spriteSheet,
sourceX, sourceY, frameWidth, frameHeight, // source
destX, destY, frameWidth, frameHeight // destination
);Shadow Sprite
The Shadow.png is a single 128x128 sprite designed to be placed beneath elevated terrain.
Positioning Algorithm
// For elevated tile at grid position (gx, gy)
const shadowGridX = gx;
const shadowGridY = gy + 1; // One tile below
// Convert to pixel position (shadow is 128x128, centered on 64x64 cell)
const shadowPixelX = shadowGridX * 64 - 32; // Offset to center
const shadowPixelY = shadowGridY * 64 - 32;Coordinate Systems
Grid Coordinates
- Origin: Top-left of map
- X: Increases rightward
- Y: Increases downward
- Unit: Tiles (64px)
Pixel Coordinates
- Origin: Top-left of canvas
- X: Increases rightward
- Y: Increases downward
- Unit: Pixels
Conversion Functions
function gridToPixel(gridX, gridY) {
return {
x: gridX * 64,
y: gridY * 64
};
}
function pixelToGrid(pixelX, pixelY) {
return {
x: Math.floor(pixelX / 64),
y: Math.floor(pixelY / 64)
};
}