Skip to content

Instantly share code, notes, and snippets.

@Xanmia
Created March 10, 2016 13:33
Show Gist options
  • Save Xanmia/8fe5a80ec37e9494b198 to your computer and use it in GitHub Desktop.
Save Xanmia/8fe5a80ec37e9494b198 to your computer and use it in GitHub Desktop.
Create an Island

Create an Island

Mouse down to draw an island. Click the export button to save your design. Drag and drop file on canvas to load previous island. My JS1k for 2016 with added items I couldn't fit in.

A Pen by Xanmia on CodePen.

License.

<canvas id="backCanvas" ></canvas>
<canvas id="foreCanvas" ></canvas>
<div id="options">
<button id='save' onclick='save();'>Save</button>
<button id='clear' onclick='Clear();'>Clear</button>
</div>
r = [0, -2, 2, 2, -4, 6, 8, -6, 4, 12, -6, 6, 18, -4, 4, 22, -2, 3]; ///land shading pattern
z = ['#f4edc4', '#73defc', '#5fcafc', '#aba234', '#4ac2fc', '#aba234', '#36bdfc', '#dfd995']; ///land + water colors
clouds = [];
drawing = 0;
var defaultMap = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
];
var backCanvas = document.getElementById('backCanvas');
var foreCanvas = document.getElementById('foreCanvas');
var w = foreCanvas.width = backCanvas.width = window.innerWidth;
var h = foreCanvas.height = backCanvas.height = window.innerHeight;
foreCTX = foreCanvas.getContext('2d');
backCTX = backCanvas.getContext('2d');
/////////////save & load
function save() {
arr = [];
for (var i = 0; i < h; i += 25) {
arr[i / 25] = [];
for (var p = 0; p < w; p += 25) {
arr[i / 25][p / 25] = backCTX.getImageData(p + 12, i + 12, 1, 1).data[2] == 252 ? 0 : 1;
}
}
open('data:text/json;,' + JSON.stringify(arr));
}
window.addEventListener('drop', function(e) {
e.preventDefault();
f = e.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = (function(filein) {
return function(e) {
LoadFromData(JSON.parse(e.target.result));
};
})(f);
reader.readAsText(f);
});
window.addEventListener('dragover', function(e) {
e.preventDefault();
});
function LoadFromData(result) {
tOBJ = result;
for (var i = 0; i < h; i += 25) {
for (var p = 0; p < w; p += 25) {
if (tOBJ[i / 25][p / 25]) landShading(0, {
x: p,
y: i
}, 1);
}
}
}
/////////////////////
function loop() {
requestAnimationFrame(loop);
foreCTX.clearRect(0, 0, w, h);
if (Math.random() * 25 < .06) clouds.push(new cloud());
t = clouds.length;
while (t--) {
clouds[t].update();
clouds[t].render();
if (clouds[t].position.x < -500) {
clouds.splice(t, 1);
}
}
}
function landShading(recursion, s, recur) {
if (recursion == 4) return;
backCTX.save();
backCTX.translate(s.x, s.y);
if (!recursion) {
backCTX.fillStyle = z[7];
backCTX.fillRect(0, 0, 25, 25);
} else {
if (recursion == 1) backCTX.translate(25, 0); //right ///clean up
if (recursion == 2) backCTX.translate(25, 25); //bottom //// clean up
if (recursion == 3) backCTX.translate(0, 25); //left ////clean up
backCTX.rotate((3.14 * (recursion * .5)));
}
po = 3.14 * (1.5 + (recursion * .5)); //angle
var Mx = (s.x + 12) + 25 * Math.cos(po);
var My = (s.y + 12) + 25 * Math.sin(po);
var check = backCTX.getImageData(Mx, My, 1, 1).data[2] == 252; ///check neighbor for water
backCTX.fillStyle = z[0]; ///sand
backCTX.fillRect(Math.random() * 20, Math.random() * 20, 2, 2); ///sand
m = 0;
while (m < (recursion == 2 ? 4 : 3)) { //how much shading
backCTX.translate(0, 2);
backCTX.fillStyle = z[m];
n = 0
while (n < r.length) {
if (check) {
backCTX.fillRect(r[n], r[n + 1], r[n + 2], 2);
}
n += 3;
}
m++;
}
backCTX.restore();
landShading(recursion + 1, s, recur); ///continue recursion on current for all sides
if (!check && recur) {
landShading(0, {
x: Math.floor(Mx / 25) * 25,
y: Math.floor(My / 25) * 25
}, 0)
} ///recur for neighbor tile
}
window.addEventListener('mousedown', function(e) {
drawing = 1;
landShading(0, {
x: Math.floor(e.pageX / 25) * 25,
y: Math.floor(e.pageY / 25) * 25
}, 1);
});
window.addEventListener('mouseup', function(e) {
drawing = 0;
});
///draw
window.addEventListener('mousemove', function(e) {
if (drawing) {
landShading(0, {
x: Math.floor(e.pageX / 25) * 25,
y: Math.floor(e.pageY / 25) * 25
}, 1);
}
});
var cloud = function(X, Y) {
this.position = {
x: X || w + 200,
y: Y || Math.random() * h - 100
};
this.velocity = {
x: Math.random() * 1,
y: Math.random() * 1
};
this.cloudClumps = [];
totalClumps = Math.round(Math.random() * 10); //total clouds in a "clump"
while (totalClumps--) {
this.cloudClumps.push({
x: Math.random() * 200,
y: Math.random() * 200,
s: (Math.random() * 150) + 20
});
}
}
cloud.prototype.update = function() {
this.position.x -= this.velocity.x; ///clouds only move left to right
//this.position.y += this.velocity.y;
}
cloud.prototype.render = function() {
var totClouds = this.cloudClumps.length;
while (totClouds--) {
var thisClump = this.cloudClumps[totClouds];
var grad = foreCTX.createRadialGradient(this.position.x + thisClump.x, this.position.y + thisClump.y, 0, this.position.x + thisClump.x, this.position.y + thisClump.y, thisClump.s + 10);
grad.addColorStop(0, 'rgba(252, 252, 252, .5)');
grad.addColorStop(1, 'rgba(252, 252, 252, 0)');
foreCTX.fillStyle = grad;
foreCTX.beginPath();
foreCTX.arc(this.position.x + thisClump.x, this.position.y + thisClump.y, thisClump.s + 10, 0, Math.PI * 2, true);
foreCTX.fill();
foreCTX.closePath();
}
}
function Clear() {
//clear
backCTX.fillStyle = z[6];
backCTX.fillRect(0, 0, w, h);
///
////create static waves
for (i = 0; i < h; i += 10) {
s = 1;
for (t = 0; t < w; t += 10) {
backCTX.fillStyle = z[2];
backCTX.fillRect(t, (s == 1 ? i : i - 2), 10, 2);
backCTX.fillStyle = Math.random() * 25 < .3 ? z[1] : z[4];
backCTX.fillRect(t, (s == 1 ? i - 2 : i - 4), 10, 2);
s *= -1;
}
}
}
window.addEventListener('load', function() {
Clear();
///start with some clouds
clouds.push(new cloud(Math.random() * w, Math.random() * h - 100))
clouds.push(new cloud(Math.random() * w, Math.random() * h - 100))
clouds.push(new cloud(Math.random() * w, Math.random() * h - 100))
loop();
//////
LoadFromData(defaultMap);
});
body,html{margin:0;padding:0;border:0;width:100%;height:100%}
canvas{position:absolute;}
button{ color:white;background-color:silver;padding: 5px 15px;border-radius: 15px; font: 400 15px 'Open Sans', sans-serif;}
#options{position:fixed;bottom:15px;left:15px;}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment