153 lines
3 KiB
JavaScript
153 lines
3 KiB
JavaScript
const BIASES = {
|
|
0xc8ff50: 1,
|
|
0x46aafa: 0.5,
|
|
0xff0000: 0.75,
|
|
0x0000ff: 0.4,
|
|
};
|
|
|
|
function validXY(x, y) {
|
|
if (x < 0 || x >= 3200) return false;
|
|
if (y < 0 || y >= 1600) return false;
|
|
return true;
|
|
}
|
|
|
|
function getRGBA(data, i, out) {
|
|
for (let j = i * 4; j < i * 4 + 4; j++) {
|
|
out[j - i*4] = data[j];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function setRGBA(data, i, input) {
|
|
for (let j = i * 4; j < i * 4 + 4; j++) {
|
|
data[j] = input[j - i * 4];
|
|
}
|
|
}
|
|
|
|
function isLand(data) {
|
|
if (data[0] == 255 && data[1] == 255 && data[2] == 255 && data[3] == 255) return false;
|
|
return true;
|
|
}
|
|
|
|
function Game(baseMap) {
|
|
this.img = new Image();
|
|
this.baseMap = baseMap;
|
|
}
|
|
|
|
Game.prototype.main = function() {
|
|
var {biomes, ctx, colonized} = this;
|
|
var dat = ctx.getImageData(0,0,3200,1600);
|
|
var data = dat.data;
|
|
var out = new Uint8Array(4);
|
|
|
|
for (let k = 0; k < 3200*1600/10; k++) {
|
|
let i = Math.floor(Math.random() * biomes.data.length / 4);
|
|
if (!colonized[i]) continue;
|
|
|
|
var x = i % 3200;
|
|
var y = Math.floor(i / 3200);
|
|
|
|
let rgba = getRGBA(biomes.data,i,out);
|
|
|
|
if (isLand(rgba))
|
|
setRGBA(data,i,[255,128,128,255]);
|
|
|
|
let weight = 10;
|
|
|
|
let broken = false;
|
|
|
|
for (let dx = -1; dx <= 1; dx++) {
|
|
for (let dy = -1; dy <= 1; dy++ ) {
|
|
weight--;
|
|
let x2 = x + dx;
|
|
let y2 = y + dy;
|
|
|
|
let i = x2 + y2 * 3200;
|
|
|
|
if (!validXY(x2,y2)) continue;
|
|
let rgba = getRGBA(biomes.data,i,out);
|
|
let rgbaH = rgba[0] * 0x10000 + rgba[1] * 0x100 + rgba[2];
|
|
|
|
if (Math.random() > ((rgbaH in BIASES) ? BIASES[rgbaH] : 0.2) / weight) {
|
|
continue;
|
|
}
|
|
if (colonized[y2 * 3200 + x2] == 1) {
|
|
continue;
|
|
}
|
|
|
|
colonized[y2 * 3200 + x2] = 1;
|
|
broken = true;
|
|
break;
|
|
}
|
|
if (broken) break;
|
|
}
|
|
}
|
|
|
|
ctx.putImageData(dat,0,0,0,0,3200,1600);
|
|
}
|
|
|
|
Game.prototype.map = function() {
|
|
var {biomes, ctx} = this;
|
|
var dat = ctx.getImageData(0,0,3200,1600);
|
|
var data = dat.data;
|
|
|
|
var out = new Uint8Array(4);
|
|
for (let i = 0; i < biomes.data.length; i++) {
|
|
let rgba = getRGBA(biomes.data,i, out);
|
|
|
|
if (!isLand(rgba,i)) {
|
|
setRGBA(data,i,[255,255,255,255])
|
|
} else {
|
|
setRGBA(data,i,[0,0,0,255]);
|
|
}
|
|
}
|
|
|
|
ctx.putImageData(dat,0,0,0,0,3200,1600);
|
|
}
|
|
|
|
Game.prototype.place = function() {
|
|
var {biomes,ctx,colonized} = this;
|
|
var out = new Uint8Array(4);
|
|
|
|
let i = 0;
|
|
|
|
while (true) {
|
|
i = Math.floor(Math.random() * biomes.data.length / 4);
|
|
|
|
let rgba = getRGBA(biomes.data,i,out);
|
|
|
|
if (isLand(rgba)) break;
|
|
}
|
|
colonized[i] = 1;
|
|
}
|
|
|
|
Game.prototype.loop = function() {
|
|
let that = this;
|
|
setInterval(function() { that.main() } ,1000 / 60);
|
|
}
|
|
|
|
Game.prototype.startGame = function() {
|
|
var canvas = document.querySelector("#canvas");
|
|
var ctx = canvas.getContext("2d",{ willReadFrequently: true });
|
|
|
|
this.ctx = ctx;
|
|
|
|
ctx.drawImage(this.img,0, 0,3200,1600);
|
|
|
|
var dat = ctx.getImageData(0,0,3200,1600);
|
|
this.biomes = dat;
|
|
|
|
this.colonized = new Uint8Array(3200*1600);
|
|
|
|
this.map();
|
|
this.place();
|
|
this.loop();
|
|
}
|
|
|
|
Game.prototype.init = function() {
|
|
let that = this;
|
|
this.img.src = this.baseMap;
|
|
this.img.onload = function() { that.startGame() };
|
|
}
|
|
|
|
new Game("base.png").init();
|