map-test/js/index.js
2024-09-02 14:26:20 -04:00

183 lines
3.8 KiB
JavaScript

const width = 2160;
const height = 1080;
const BIASES = {
0x000000: 1,
0x64ff50: 0.5,
0xc8ff50: 0.45,
0x46aafa: 0.4,
0x0078ff: 0.35,
0x0000ff: 0.3,
0xf5a500: 0.15,
0xff0000: 0.1,
0x666666: 0.01,
0xb2b2b2: 0.02
};
function validXY(x, y) {
if (x < 0 || x >= width) return false;
if (y < 0 || y >= height) 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;
if (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 255) return false;
return true;
}
function Game(baseMap) {
this.img = new Image();
this.baseMap = baseMap;
this.colors = {};
this.aggression = {};
this.strength = {};
}
Game.prototype.main = function() {
var {biomes, ctx, colonized} = this;
var dat = ctx.getImageData(0,0,width,height);
var data = dat.data;
var out = new Uint8Array(4);
for (let k = 0; k < width*height; k++) {
let i = k;
if (!colonized[i]) continue;
var x = i % width;
var y = Math.floor(i / width);
let rgba = getRGBA(biomes.data,i,out);
if (isLand(rgba))
setRGBA(data,i,this.colors[colonized[i]]);
let weight = 11;
let broken = false;
let i2 = i;
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 * width;
if (!validXY(x2,y2)) continue;
let rgba = getRGBA(biomes.data,i,out);
let rgbaH = rgba[0] * 0x10000 + rgba[1] * 0x100 + rgba[2];
let bias = ((rgbaH in BIASES) ? BIASES[rgbaH] : 0.2) / weight;
if (colonized[y2 * width + x2] != 0) {
bias *= this.aggression[colonized[i]];
}
if (Math.random() > bias) {
continue;
}
if (colonized[y2 * width + x2] == colonized[i2]) {
continue;
}
colonized[y2 * width + x2] = colonized[i2];
this.strength[colonized[i]]++;
broken = true;
break;
}
if (broken) break;
}
}
ctx.putImageData(dat,0,0,0,0,width,height);
}
Game.prototype.map = function() {
var {biomes, ctx} = this;
var dat = ctx.getImageData(0,0,width,height);
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,width,height);
}
Game.prototype.place = function() {
var {biomes,ctx,colonized} = this;
var out = new Uint8Array(4);
let i = 0;
for (let count = 1; count < 101; count++) {
while (true) {
i = Math.floor(Math.random() * biomes.data.length / 4);
let rgba = getRGBA(biomes.data,i,out);
if (isLand(rgba)) break;
}
colonized[i] = count;
this.aggression[count] = Math.random();
this.colors[count] = [Math.floor(Math.random() * 255),Math.floor(Math.random() * 255),Math.floor(Math.random() * 255),255];
this.strength[count] = 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.imageSmoothingEnabled = false;
ctx.drawImage(this.img,0, 0,width,height);
var dat = ctx.getImageData(0,0,width,height);
this.biomes = dat;
this.colonized = new Uint8Array(width*height);
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();