@ -1,148 +1,141 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
// Globs for non-ui resources
|
// Globs for non-ui resources
|
||||||
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||||
|
|
||||||
// Globs for ui resources
|
// Globs for ui resources
|
||||||
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
|
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
|
||||||
|
|
||||||
function gulptasksImageResources($, gulp, buildFolder) {
|
function gulptasksImageResources($, gulp, buildFolder) {
|
||||||
// Lossless options
|
// Lossless options
|
||||||
const minifyImagesOptsLossless = () => [
|
const minifyImagesOptsLossless = () => [
|
||||||
$.imageminJpegtran({
|
$.imageminJpegtran({
|
||||||
progressive: true,
|
progressive: true,
|
||||||
}),
|
}),
|
||||||
$.imagemin.svgo({}),
|
$.imagemin.svgo({}),
|
||||||
$.imagemin.optipng({
|
$.imagemin.optipng({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
}),
|
}),
|
||||||
$.imageminGifsicle({
|
$.imageminGifsicle({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
colors: 128,
|
colors: 128,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Lossy options
|
// Lossy options
|
||||||
const minifyImagesOpts = () => [
|
const minifyImagesOpts = () => [
|
||||||
$.imagemin.mozjpeg({
|
$.imagemin.mozjpeg({
|
||||||
quality: 80,
|
quality: 80,
|
||||||
maxMemory: 1024 * 1024 * 8,
|
maxMemory: 1024 * 1024 * 8,
|
||||||
}),
|
}),
|
||||||
$.imagemin.svgo({}),
|
$.imagemin.svgo({}),
|
||||||
$.imageminPngquant({
|
$.imageminPngquant({
|
||||||
speed: 1,
|
speed: 1,
|
||||||
strip: true,
|
strip: true,
|
||||||
quality: [0.65, 0.9],
|
quality: [0.65, 0.9],
|
||||||
dithering: false,
|
dithering: false,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
}),
|
}),
|
||||||
$.imagemin.optipng({
|
$.imagemin.optipng({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
}),
|
}),
|
||||||
$.imageminGifsicle({
|
$.imageminGifsicle({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
colors: 128,
|
colors: 128,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Where the resources folder are
|
// Where the resources folder are
|
||||||
const resourcesDestFolder = path.join(buildFolder, "res");
|
const resourcesDestFolder = path.join(buildFolder, "res");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if an atlas must use lossless compression
|
* Determines if an atlas must use lossless compression
|
||||||
* @param {string} fname
|
* @param {string} fname
|
||||||
*/
|
*/
|
||||||
function fileMustBeLossless(fname) {
|
function fileMustBeLossless(fname) {
|
||||||
return fname.indexOf("lossless") >= 0;
|
return fname.indexOf("lossless") >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////// ATLAS /////////////////////
|
/////////////// ATLAS /////////////////////
|
||||||
|
|
||||||
// Copies the atlas to the final destination
|
// Copies the atlas to the final destination
|
||||||
gulp.task("imgres.atlas", () => {
|
gulp.task("imgres.atlas", () => {
|
||||||
return gulp
|
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
||||||
.src(["../res_built/atlas/*.png"])
|
});
|
||||||
.pipe($.cached("imgres.atlas"))
|
|
||||||
.pipe(gulp.dest(resourcesDestFolder));
|
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
||||||
});
|
gulp.task("imgres.atlasOptimized", () => {
|
||||||
|
return gulp
|
||||||
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
.src(["../res_built/atlas/*.png"])
|
||||||
gulp.task("imgres.atlasOptimized", () => {
|
.pipe(
|
||||||
return gulp
|
$.if(
|
||||||
.src(["../res_built/atlas/*.png"])
|
fname => fileMustBeLossless(fname.history[0]),
|
||||||
.pipe($.cached("imgres.atlasOptimized"))
|
$.imagemin(minifyImagesOptsLossless()),
|
||||||
.pipe(
|
$.imagemin(minifyImagesOpts())
|
||||||
$.if(
|
)
|
||||||
fname => fileMustBeLossless(fname.history[0]),
|
)
|
||||||
$.imagemin(minifyImagesOptsLossless()),
|
.pipe(gulp.dest(resourcesDestFolder));
|
||||||
$.imagemin(minifyImagesOpts())
|
});
|
||||||
)
|
|
||||||
)
|
//////////////////// RESOURCES //////////////////////
|
||||||
.pipe(gulp.dest(resourcesDestFolder));
|
|
||||||
});
|
// Copies all resources which are no ui resources
|
||||||
|
gulp.task("imgres.copyNonImageResources", () => {
|
||||||
//////////////////// RESOURCES //////////////////////
|
return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder));
|
||||||
|
});
|
||||||
// Copies all resources which are no ui resources
|
|
||||||
gulp.task("imgres.copyNonImageResources", () => {
|
// Copies all ui resources
|
||||||
return gulp
|
gulp.task("imgres.copyImageResources", () => {
|
||||||
.src(nonImageResourcesGlobs)
|
return gulp
|
||||||
.pipe($.cached("imgres.copyNonImageResources"))
|
.src(imageResourcesGlobs)
|
||||||
.pipe(gulp.dest(resourcesDestFolder));
|
|
||||||
});
|
.pipe($.cached("imgres.copyImageResources"))
|
||||||
|
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||||
// Copies all ui resources
|
});
|
||||||
gulp.task("imgres.copyImageResources", () => {
|
|
||||||
return gulp
|
// Copies all ui resources and optimizes them
|
||||||
.src(imageResourcesGlobs)
|
gulp.task("imgres.copyImageResourcesOptimized", () => {
|
||||||
.pipe($.cached("copyImageResources"))
|
return gulp
|
||||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
.src(imageResourcesGlobs)
|
||||||
});
|
.pipe(
|
||||||
|
$.if(
|
||||||
// Copies all ui resources and optimizes them
|
fname => fileMustBeLossless(fname.history[0]),
|
||||||
gulp.task("imgres.copyImageResourcesOptimized", () => {
|
$.imagemin(minifyImagesOptsLossless()),
|
||||||
return gulp
|
$.imagemin(minifyImagesOpts())
|
||||||
.src(imageResourcesGlobs)
|
)
|
||||||
.pipe($.cached("imgres.copyImageResourcesOptimized"))
|
)
|
||||||
.pipe(
|
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||||
$.if(
|
});
|
||||||
fname => fileMustBeLossless(fname.history[0]),
|
|
||||||
$.imagemin(minifyImagesOptsLossless()),
|
// Copies all resources and optimizes them
|
||||||
$.imagemin(minifyImagesOpts())
|
gulp.task(
|
||||||
)
|
"imgres.allOptimized",
|
||||||
)
|
gulp.parallel(
|
||||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
"imgres.atlasOptimized",
|
||||||
});
|
"imgres.copyNonImageResources",
|
||||||
|
"imgres.copyImageResourcesOptimized"
|
||||||
// Copies all resources and optimizes them
|
)
|
||||||
gulp.task(
|
);
|
||||||
"imgres.allOptimized",
|
|
||||||
gulp.parallel(
|
// Cleans up unused images which are instead inline into the css
|
||||||
"imgres.atlasOptimized",
|
gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
|
||||||
"imgres.copyNonImageResources",
|
return gulp
|
||||||
"imgres.copyImageResourcesOptimized"
|
.src(
|
||||||
)
|
[
|
||||||
);
|
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||||
|
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||||
// Cleans up unused images which are instead inline into the css
|
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||||
gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
|
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||||
return gulp
|
],
|
||||||
.src(
|
{ read: false }
|
||||||
[
|
)
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
.pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true })));
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
});
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
}
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
|
||||||
],
|
module.exports = {
|
||||||
{ read: false }
|
nonImageResourcesGlobs,
|
||||||
)
|
imageResourcesGlobs,
|
||||||
.pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true })));
|
gulptasksImageResources,
|
||||||
});
|
};
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
nonImageResourcesGlobs,
|
|
||||||
imageResourcesGlobs,
|
|
||||||
gulptasksImageResources,
|
|
||||||
};
|
|
||||||
|
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 233 KiB |
After Width: | Height: | Size: 281 KiB |
After Width: | Height: | Size: 287 KiB |
After Width: | Height: | Size: 283 KiB |
After Width: | Height: | Size: 286 KiB |
After Width: | Height: | Size: 260 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 279 KiB |
Before Width: | Height: | Size: 701 KiB After Width: | Height: | Size: 703 KiB |
@ -1,226 +1,213 @@
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Run `yarn global add canvas` first
|
* Run `yarn global add canvas` first
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { createCanvas } = require("canvas");
|
const { createCanvas } = require("canvas");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const outputFolder = path.join(__dirname, "..", "wires", "sets");
|
const outputFolder = path.join(__dirname, "..", "wires", "sets");
|
||||||
|
|
||||||
const dimensions = 192;
|
const dimensions = 192;
|
||||||
const lineSize = 12;
|
const lineSize = 14;
|
||||||
const lowerLineSize = 20;
|
const lowerLineSize = 32;
|
||||||
|
|
||||||
function hexToRGB(h) {
|
const variants = {
|
||||||
let r = 0,
|
first: "#61ef6f",
|
||||||
g = 0,
|
second: "#f0bd65",
|
||||||
b = 0;
|
third: "#5fb2f1",
|
||||||
|
conflict: "#f74c4c",
|
||||||
// 3 digits
|
};
|
||||||
if (h.length == 4) {
|
|
||||||
r = "0x" + h[1] + h[1];
|
function hexToRGB(h) {
|
||||||
g = "0x" + h[2] + h[2];
|
let r = 0,
|
||||||
b = "0x" + h[3] + h[3];
|
g = 0,
|
||||||
|
b = 0;
|
||||||
// 6 digits
|
|
||||||
} else if (h.length == 7) {
|
// 3 digits
|
||||||
r = "0x" + h[1] + h[2];
|
if (h.length == 4) {
|
||||||
g = "0x" + h[3] + h[4];
|
r = "0x" + h[1] + h[1];
|
||||||
b = "0x" + h[5] + h[6];
|
g = "0x" + h[2] + h[2];
|
||||||
}
|
b = "0x" + h[3] + h[3];
|
||||||
|
|
||||||
return [+r, +g, +b];
|
// 6 digits
|
||||||
}
|
} else if (h.length == 7) {
|
||||||
|
r = "0x" + h[1] + h[2];
|
||||||
function RGBToHSL(r, g, b) {
|
g = "0x" + h[3] + h[4];
|
||||||
// Make r, g, and b fractions of 1
|
b = "0x" + h[5] + h[6];
|
||||||
r /= 255;
|
}
|
||||||
g /= 255;
|
|
||||||
b /= 255;
|
return [+r, +g, +b];
|
||||||
|
}
|
||||||
// Find greatest and smallest channel values
|
|
||||||
let cmin = Math.min(r, g, b),
|
function RGBToHSL(r, g, b) {
|
||||||
cmax = Math.max(r, g, b),
|
// Make r, g, and b fractions of 1
|
||||||
delta = cmax - cmin,
|
r /= 255;
|
||||||
h = 0,
|
g /= 255;
|
||||||
s = 0,
|
b /= 255;
|
||||||
l = 0;
|
|
||||||
// Calculate hue
|
// Find greatest and smallest channel values
|
||||||
// No difference
|
let cmin = Math.min(r, g, b),
|
||||||
if (delta == 0) h = 0;
|
cmax = Math.max(r, g, b),
|
||||||
// Red is max
|
delta = cmax - cmin,
|
||||||
else if (cmax == r) h = ((g - b) / delta) % 6;
|
h = 0,
|
||||||
// Green is max
|
s = 0,
|
||||||
else if (cmax == g) h = (b - r) / delta + 2;
|
l = 0;
|
||||||
// Blue is max
|
// Calculate hue
|
||||||
else h = (r - g) / delta + 4;
|
// No difference
|
||||||
|
if (delta == 0) h = 0;
|
||||||
h = Math.round(h * 60);
|
// Red is max
|
||||||
|
else if (cmax == r) h = ((g - b) / delta) % 6;
|
||||||
// Make negative hues positive behind 360°
|
// Green is max
|
||||||
if (h < 0) h += 360;
|
else if (cmax == g) h = (b - r) / delta + 2;
|
||||||
|
// Blue is max
|
||||||
// Calculate lightness
|
else h = (r - g) / delta + 4;
|
||||||
l = (cmax + cmin) / 2;
|
|
||||||
|
h = Math.round(h * 60);
|
||||||
// Calculate saturation
|
|
||||||
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
// Make negative hues positive behind 360°
|
||||||
|
if (h < 0) h += 360;
|
||||||
// Multiply l and s by 100
|
|
||||||
s = +(s * 100).toFixed(1);
|
// Calculate lightness
|
||||||
l = +(l * 100).toFixed(1);
|
l = (cmax + cmin) / 2;
|
||||||
|
|
||||||
return [h, s, l];
|
// Calculate saturation
|
||||||
}
|
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
||||||
|
|
||||||
function HSLToRGB(h, s, l) {
|
// Multiply l and s by 100
|
||||||
// Must be fractions of 1
|
s = +(s * 100).toFixed(1);
|
||||||
s /= 100;
|
l = +(l * 100).toFixed(1);
|
||||||
l /= 100;
|
|
||||||
|
return [h, s, l];
|
||||||
let c = (1 - Math.abs(2 * l - 1)) * s,
|
}
|
||||||
x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
|
|
||||||
m = l - c / 2,
|
function HSLToRGB(h, s, l) {
|
||||||
r = 0,
|
// Must be fractions of 1
|
||||||
g = 0,
|
s /= 100;
|
||||||
b = 0;
|
l /= 100;
|
||||||
|
|
||||||
if (0 <= h && h < 60) {
|
let c = (1 - Math.abs(2 * l - 1)) * s,
|
||||||
r = c;
|
x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
|
||||||
g = x;
|
m = l - c / 2,
|
||||||
b = 0;
|
r = 0,
|
||||||
} else if (60 <= h && h < 120) {
|
g = 0,
|
||||||
r = x;
|
b = 0;
|
||||||
g = c;
|
|
||||||
b = 0;
|
if (0 <= h && h < 60) {
|
||||||
} else if (120 <= h && h < 180) {
|
r = c;
|
||||||
r = 0;
|
g = x;
|
||||||
g = c;
|
b = 0;
|
||||||
b = x;
|
} else if (60 <= h && h < 120) {
|
||||||
} else if (180 <= h && h < 240) {
|
r = x;
|
||||||
r = 0;
|
g = c;
|
||||||
g = x;
|
b = 0;
|
||||||
b = c;
|
} else if (120 <= h && h < 180) {
|
||||||
} else if (240 <= h && h < 300) {
|
r = 0;
|
||||||
r = x;
|
g = c;
|
||||||
g = 0;
|
b = x;
|
||||||
b = c;
|
} else if (180 <= h && h < 240) {
|
||||||
} else if (300 <= h && h < 360) {
|
r = 0;
|
||||||
r = c;
|
g = x;
|
||||||
g = 0;
|
b = c;
|
||||||
b = x;
|
} else if (240 <= h && h < 300) {
|
||||||
}
|
r = x;
|
||||||
r = Math.round((r + m) * 255);
|
g = 0;
|
||||||
g = Math.round((g + m) * 255);
|
b = c;
|
||||||
b = Math.round((b + m) * 255);
|
} else if (300 <= h && h < 360) {
|
||||||
|
r = c;
|
||||||
return [r, g, b];
|
g = 0;
|
||||||
}
|
b = x;
|
||||||
|
}
|
||||||
async function run() {
|
r = Math.round((r + m) * 255);
|
||||||
console.log("Running");
|
g = Math.round((g + m) * 255);
|
||||||
|
b = Math.round((b + m) * 255);
|
||||||
const variants = {
|
|
||||||
regular: "#25fff2",
|
return [r, g, b];
|
||||||
color: "#eba458",
|
}
|
||||||
shape: "#8858eb",
|
|
||||||
conflict: "#ff3e3e",
|
async function run() {
|
||||||
};
|
console.log("Running");
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
for (const variantId in variants) {
|
for (const variantId in variants) {
|
||||||
const variantColor = variants[variantId];
|
const variantColor = variants[variantId];
|
||||||
const variantHSL = RGBToHSL(...hexToRGB(variantColor));
|
const variantHSL = RGBToHSL(...hexToRGB(variantColor));
|
||||||
const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20);
|
const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20);
|
||||||
const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")";
|
const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")";
|
||||||
|
|
||||||
console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor);
|
console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor);
|
||||||
|
|
||||||
const parts = {
|
const parts = {
|
||||||
forward: [[0.5, 0, 0.5, 1]],
|
forward: [[0.5, 0, 0.5, 1]],
|
||||||
turn: [
|
turn: [
|
||||||
[0.5, 0.5, 0.5, 1],
|
[0.5, 0.5, 0.5, 1],
|
||||||
[0.5, 0.5, 1, 0.5],
|
[0.5, 0.5, 1, 0.5],
|
||||||
],
|
],
|
||||||
split: [
|
split: [
|
||||||
[0.5, 0.5, 0.5, 1],
|
[0.5, 0.5, 0.5, 1],
|
||||||
[0, 0.5, 1, 0.5],
|
[0, 0.5, 1, 0.5],
|
||||||
],
|
],
|
||||||
cross: [
|
cross: [
|
||||||
[0, 0.5, 1, 0.5],
|
[0, 0.5, 1, 0.5],
|
||||||
[0.5, 0, 0.5, 1],
|
[0.5, 0, 0.5, 1],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const partId in parts) {
|
for (const partId in parts) {
|
||||||
const partLines = parts[partId];
|
const partLines = parts[partId];
|
||||||
|
|
||||||
const canvas = createCanvas(dimensions, dimensions);
|
const canvas = createCanvas(dimensions, dimensions);
|
||||||
const context = canvas.getContext("2d");
|
const context = canvas.getContext("2d");
|
||||||
context.quality = "best";
|
context.quality = "best";
|
||||||
context.clearRect(0, 0, dimensions, dimensions);
|
context.clearRect(0, 0, dimensions, dimensions);
|
||||||
|
|
||||||
context.strokeStyle = hexDarkenedColor;
|
const lineCanvas = createCanvas(dimensions, dimensions);
|
||||||
context.lineWidth = lowerLineSize;
|
const lineContext = lineCanvas.getContext("2d");
|
||||||
context.lineCap = "square";
|
lineContext.quality = "best";
|
||||||
context.imageSmoothingEnabled = false;
|
lineContext.clearRect(0, 0, dimensions, dimensions);
|
||||||
|
lineContext.strokeStyle = hexDarkenedColor;
|
||||||
// Draw lower lines
|
lineContext.lineWidth = lowerLineSize;
|
||||||
partLines.forEach(([x1, y1, x2, y2]) => {
|
lineContext.lineCap = "square";
|
||||||
context.beginPath();
|
lineContext.imageSmoothingEnabled = false;
|
||||||
context.moveTo(x1 * dimensions, y1 * dimensions);
|
|
||||||
context.lineTo(x2 * dimensions, y2 * dimensions);
|
// Draw lower lines
|
||||||
context.stroke();
|
partLines.forEach(([x1, y1, x2, y2]) => {
|
||||||
});
|
lineContext.beginPath();
|
||||||
|
lineContext.moveTo(x1 * dimensions, y1 * dimensions);
|
||||||
context.strokeStyle = variantColor;
|
lineContext.lineTo(x2 * dimensions, y2 * dimensions);
|
||||||
context.lineWidth = lineSize;
|
lineContext.stroke();
|
||||||
|
});
|
||||||
// Draw upper lines
|
|
||||||
partLines.forEach(([x1, y1, x2, y2]) => {
|
context.globalAlpha = 0.4;
|
||||||
context.beginPath();
|
context.drawImage(lineCanvas, 0, 0, dimensions, dimensions);
|
||||||
context.moveTo(x1 * dimensions, y1 * dimensions);
|
|
||||||
context.lineTo(x2 * dimensions, y2 * dimensions);
|
context.globalAlpha = 1;
|
||||||
context.stroke();
|
context.imageSmoothingEnabled = false;
|
||||||
});
|
context.lineCap = "square";
|
||||||
|
context.strokeStyle = variantColor;
|
||||||
const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
|
context.lineWidth = lineSize;
|
||||||
const stream = canvas.createPNGStream();
|
|
||||||
stream.pipe(out);
|
// Draw upper lines
|
||||||
promises.push(new Promise(resolve => stream.on("end", resolve)));
|
partLines.forEach(([x1, y1, x2, y2]) => {
|
||||||
}
|
context.beginPath();
|
||||||
}
|
context.moveTo(x1 * dimensions, y1 * dimensions);
|
||||||
|
context.lineTo(x2 * dimensions, y2 * dimensions);
|
||||||
console.log("Waiting for completion");
|
context.stroke();
|
||||||
await Promise.all(promises);
|
});
|
||||||
|
|
||||||
// Also wait a bit more
|
const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
const stream = canvas.createPNGStream();
|
||||||
|
stream.pipe(out);
|
||||||
console.log("Copying files to all locations");
|
promises.push(new Promise(resolve => stream.on("end", resolve)));
|
||||||
|
}
|
||||||
// // Copy other files
|
}
|
||||||
fs.copyFileSync(
|
|
||||||
path.join(outputFolder, "regular_forward.png"),
|
console.log("Waiting for completion");
|
||||||
path.join(__dirname, "..", "buildings", "wire.png")
|
await Promise.all(promises);
|
||||||
);
|
|
||||||
fs.copyFileSync(
|
console.log("Done!");
|
||||||
path.join(outputFolder, "regular_turn.png"),
|
}
|
||||||
path.join(__dirname, "..", "buildings", "wire-turn.png")
|
|
||||||
);
|
run();
|
||||||
fs.copyFileSync(
|
|
||||||
path.join(outputFolder, "regular_split.png"),
|
|
||||||
path.join(__dirname, "..", "buildings", "wire-split.png")
|
|
||||||
);
|
|
||||||
fs.copyFileSync(
|
|
||||||
path.join(outputFolder, "regular_cross.png"),
|
|
||||||
path.join(__dirname, "..", "buildings", "wire-cross.png")
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Done!");
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 957 B |
Before Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 676 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 503 B |
Before Width: | Height: | Size: 498 B |
Before Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 4.5 KiB |
@ -1,110 +1,92 @@
|
|||||||
# Requirements: numpy, scipy, Pillow,
|
# Requirements: numpy, scipy, Pillow,
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import ndimage
|
from scipy import ndimage
|
||||||
from PIL import Image, ImageFilter, ImageChops
|
from PIL import Image, ImageFilter, ImageChops
|
||||||
import math
|
import math
|
||||||
from os import listdir
|
from os import listdir
|
||||||
from os.path import isdir, isfile
|
from os.path import isdir, isfile
|
||||||
|
|
||||||
roberts_cross_v = np.array([[0, 0, 0],
|
generate_blueprint_sprite_v = np.array([[0, 0, 0],
|
||||||
[0, 1, 0],
|
[0, 1, 0],
|
||||||
[0, 0, -1]])
|
[0, 0, -1]])
|
||||||
|
|
||||||
roberts_cross_h = np.array([[0, 0, 0],
|
generate_blueprint_sprite_h = np.array([[0, 0, 0],
|
||||||
[0, 0, 1],
|
[0, 0, 1],
|
||||||
[0, -1, 0]])
|
[0, -1, 0]])
|
||||||
|
|
||||||
|
|
||||||
def rgb2gray(rgb):
|
def rgb2gray(rgb):
|
||||||
return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140])
|
return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140])
|
||||||
|
|
||||||
|
def process_image(data, outfilename, src_image):
|
||||||
|
img = Image.fromarray(np.asarray(
|
||||||
|
np.clip(data, 0, 255), dtype="uint8"), "L")
|
||||||
def save_image(data, outfilename, src_image):
|
dest = Image.new("RGBA", (img.width, img.height))
|
||||||
img = Image.fromarray(np.asarray(
|
src = img.load()
|
||||||
np.clip(data, 0, 255), dtype="uint8"), "L")
|
dst = dest.load()
|
||||||
dest = Image.new("RGBA", (img.width, img.height))
|
|
||||||
src = img.load()
|
realSrc = src_image.load()
|
||||||
dst = dest.load()
|
mask = src_image.filter(ImageFilter.GaussianBlur(10)).load()
|
||||||
|
orig = src_image.load()
|
||||||
realSrc = src_image.load()
|
|
||||||
mask = src_image.filter(ImageFilter.GaussianBlur(10)).load()
|
# isWire = "wire" in outfilename
|
||||||
orig = src_image.load()
|
isWire = False
|
||||||
|
|
||||||
|
targetR = 104
|
||||||
isWire = "wire" in outfilename
|
targetG = 200
|
||||||
|
targetB = 255
|
||||||
targetR = 104
|
|
||||||
targetG = 200
|
if isWire:
|
||||||
targetB = 255
|
targetR = 255
|
||||||
|
targetG = 104
|
||||||
if isWire:
|
targetB = 232
|
||||||
targetR = 255
|
|
||||||
targetG = 104
|
for x in range(img.width):
|
||||||
targetB = 232
|
for y in range(img.height):
|
||||||
|
realpixl = realSrc[x, y]
|
||||||
for x in range(img.width):
|
greyval = float(src[x, y])
|
||||||
for y in range(img.height):
|
greyval = min(255.0, greyval)
|
||||||
realpixl = realSrc[x, y]
|
greyval = math.pow(
|
||||||
greyval = float(src[x, y])
|
min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1
|
||||||
greyval = min(255.0, greyval)
|
greyval = max(0, greyval)
|
||||||
greyval = math.pow(
|
alpha = mask[x, y][3] / 255.0 * 1
|
||||||
min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1
|
|
||||||
greyval = max(0, greyval)
|
edgeFactor = src[x, y] / 255.0
|
||||||
alpha = mask[x, y][3] / 255.0 * 1
|
noEdge = 1 - edgeFactor
|
||||||
|
|
||||||
edgeFactor = src[x, y] / 255.0
|
shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor)
|
||||||
noEdge = 1 - edgeFactor
|
noShadow = 1 - shadow
|
||||||
|
|
||||||
shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor)
|
dst[x, y] = (
|
||||||
noShadow = 1 - shadow
|
min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)),
|
||||||
|
min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)),
|
||||||
dst[x, y] = (
|
min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)),
|
||||||
min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)),
|
min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor))))
|
||||||
min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)),
|
|
||||||
min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)),
|
|
||||||
min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor))))
|
dest.save(outfilename)
|
||||||
|
|
||||||
|
|
||||||
dest.save(outfilename)
|
def generate_blueprint_sprite(infilename, outfilename):
|
||||||
|
print("Processing", infilename)
|
||||||
|
img = Image.open(infilename)
|
||||||
def roberts_cross(infilename, outfilename):
|
img.load()
|
||||||
print("Processing", infilename)
|
img = img.filter(ImageFilter.GaussianBlur(0.5))
|
||||||
img = Image.open(infilename)
|
|
||||||
img.load()
|
image = rgb2gray(np.asarray(img, dtype="int32"))
|
||||||
img = img.filter(ImageFilter.GaussianBlur(0.5))
|
vertical = ndimage.convolve(image, generate_blueprint_sprite_v)
|
||||||
|
horizontal = ndimage.convolve(image, generate_blueprint_sprite_h)
|
||||||
image = rgb2gray(np.asarray(img, dtype="int32"))
|
output_image = np.sqrt(np.square(horizontal) + np.square(vertical))
|
||||||
vertical = ndimage.convolve(image, roberts_cross_v)
|
process_image(output_image, outfilename, img)
|
||||||
horizontal = ndimage.convolve(image, roberts_cross_h)
|
|
||||||
output_image = np.sqrt(np.square(horizontal) + np.square(vertical))
|
|
||||||
save_image(output_image, outfilename, img)
|
buildings = listdir("buildings")
|
||||||
|
|
||||||
|
for buildingId in buildings:
|
||||||
def generateUiPreview(srcPath, buildingId):
|
if "hub" in buildingId:
|
||||||
print(srcPath, buildingId)
|
continue
|
||||||
img = Image.open(srcPath)
|
if "wire-" in buildingId:
|
||||||
img.load()
|
continue
|
||||||
img.thumbnail((110, 110), Image.ANTIALIAS)
|
generate_blueprint_sprite("buildings/" + buildingId + "", "blueprints/" + buildingId + "")
|
||||||
img.save("../res/ui/hud/building_previews/" + buildingId + ".png")
|
|
||||||
|
|
||||||
img = img.convert("LA")
|
|
||||||
|
|
||||||
data = img.load()
|
|
||||||
for x in range(img.width):
|
|
||||||
for y in range(img.height):
|
|
||||||
data[x, y] = (data[x, y][0], int(data[x, y][1] * 0.5))
|
|
||||||
|
|
||||||
img.save("../res/ui/hud/building_previews/" + buildingId + "_disabled.png")
|
|
||||||
|
|
||||||
|
|
||||||
buildings = listdir("buildings")
|
|
||||||
|
|
||||||
for buildingId in buildings:
|
|
||||||
if "hub" in buildingId:
|
|
||||||
continue
|
|
||||||
roberts_cross("buildings/" + buildingId + "", "blueprints/" + buildingId + "")
|
|
||||||
|
Before Width: | Height: | Size: 701 B |
Before Width: | Height: | Size: 649 B |
Before Width: | Height: | Size: 502 B |
Before Width: | Height: | Size: 501 B |
Before Width: | Height: | Size: 690 B After Width: | Height: | Size: 703 B |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 647 B |
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 513 B |
After Width: | Height: | Size: 707 B |
After Width: | Height: | Size: 649 B |
After Width: | Height: | Size: 526 B |
After Width: | Height: | Size: 513 B |
Before Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 503 B |
Before Width: | Height: | Size: 498 B |
After Width: | Height: | Size: 705 B |
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 651 B |
After Width: | Height: | Size: 525 B |
After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 501 B |
Before Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 651 B |
After Width: | Height: | Size: 527 B |
After Width: | Height: | Size: 515 B |
@ -0,0 +1,79 @@
|
|||||||
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
|
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||||
|
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { MetaBuilding } from "../meta_building";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
|
const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]);
|
||||||
|
|
||||||
|
export class MetaAnalyzerBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("analyzer");
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#3a52bc";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
|
// @todo
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {"wires"} **/
|
||||||
|
getLayer() {
|
||||||
|
return "wires";
|
||||||
|
}
|
||||||
|
|
||||||
|
getDimensions() {
|
||||||
|
return new Vector(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenderPins() {
|
||||||
|
// We already have it included
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||||
|
return overlayMatrix[rotation];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new WiredPinsComponent({
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.left,
|
||||||
|
type: enumPinSlotType.logicalEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.right,
|
||||||
|
type: enumPinSlotType.logicalEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.bottom,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(
|
||||||
|
new LogicGateComponent({
|
||||||
|
type: enumLogicGateType.analyzer,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
|
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||||
|
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { MetaBuilding } from "../meta_building";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
|
export class MetaComparatorBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("comparator");
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#823cab";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
|
// @todo
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {"wires"} **/
|
||||||
|
getLayer() {
|
||||||
|
return "wires";
|
||||||
|
}
|
||||||
|
|
||||||
|
getDimensions() {
|
||||||
|
return new Vector(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenderPins() {
|
||||||
|
// We already have it included
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new WiredPinsComponent({
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.top,
|
||||||
|
type: enumPinSlotType.logicalEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.left,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.right,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(
|
||||||
|
new LogicGateComponent({
|
||||||
|
type: enumLogicGateType.compare,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,155 +1,151 @@
|
|||||||
import { enumDirection, Vector } from "../../core/vector";
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
|
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||||
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
/** @enum {string} */
|
|
||||||
export const enumLogicGateVariants = {
|
/** @enum {string} */
|
||||||
not: "not",
|
export const enumLogicGateVariants = {
|
||||||
xor: "xor",
|
not: "not",
|
||||||
or: "or",
|
xor: "xor",
|
||||||
transistor: "transistor",
|
or: "or",
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @enum {string} */
|
/** @enum {string} */
|
||||||
export const enumVariantToGate = {
|
export const enumVariantToGate = {
|
||||||
[defaultBuildingVariant]: enumLogicGateType.and,
|
[defaultBuildingVariant]: enumLogicGateType.and,
|
||||||
[enumLogicGateVariants.not]: enumLogicGateType.not,
|
[enumLogicGateVariants.not]: enumLogicGateType.not,
|
||||||
[enumLogicGateVariants.xor]: enumLogicGateType.xor,
|
[enumLogicGateVariants.xor]: enumLogicGateType.xor,
|
||||||
[enumLogicGateVariants.or]: enumLogicGateType.or,
|
[enumLogicGateVariants.or]: enumLogicGateType.or,
|
||||||
[enumLogicGateVariants.transistor]: enumLogicGateType.transistor,
|
};
|
||||||
};
|
|
||||||
|
const overlayMatrices = {
|
||||||
export class MetaLogicGateBuilding extends MetaBuilding {
|
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
|
||||||
constructor() {
|
[enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
|
||||||
super("logic_gate");
|
[enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
|
||||||
}
|
[enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
|
||||||
|
};
|
||||||
getSilhouetteColor() {
|
|
||||||
return "#89dc60";
|
const colors = {
|
||||||
}
|
[defaultBuildingVariant]: "#f48d41",
|
||||||
|
[enumLogicGateVariants.xor]: "#f4a241",
|
||||||
/**
|
[enumLogicGateVariants.or]: "#f4d041",
|
||||||
* @param {GameRoot} root
|
[enumLogicGateVariants.not]: "#f44184",
|
||||||
*/
|
};
|
||||||
getIsUnlocked(root) {
|
|
||||||
// @todo
|
export class MetaLogicGateBuilding extends MetaBuilding {
|
||||||
return true;
|
constructor() {
|
||||||
}
|
super("logic_gate");
|
||||||
|
}
|
||||||
/** @returns {"wires"} **/
|
|
||||||
getLayer() {
|
getSilhouetteColor(variant) {
|
||||||
return "wires";
|
return colors[variant];
|
||||||
}
|
}
|
||||||
|
|
||||||
getDimensions() {
|
/**
|
||||||
return new Vector(1, 1);
|
* @param {GameRoot} root
|
||||||
}
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
getAvailableVariants() {
|
// @todo
|
||||||
return [
|
return true;
|
||||||
defaultBuildingVariant,
|
}
|
||||||
enumLogicGateVariants.not,
|
|
||||||
enumLogicGateVariants.xor,
|
/** @returns {"wires"} **/
|
||||||
enumLogicGateVariants.or,
|
getLayer() {
|
||||||
enumLogicGateVariants.transistor,
|
return "wires";
|
||||||
];
|
}
|
||||||
}
|
|
||||||
|
getDimensions() {
|
||||||
getRenderPins() {
|
return new Vector(1, 1);
|
||||||
// We already have it included
|
}
|
||||||
return false;
|
|
||||||
}
|
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||||
|
return overlayMatrices[variant][rotation];
|
||||||
/**
|
}
|
||||||
*
|
|
||||||
* @param {Entity} entity
|
getAvailableVariants() {
|
||||||
* @param {number} rotationVariant
|
return [
|
||||||
*/
|
defaultBuildingVariant,
|
||||||
updateVariants(entity, rotationVariant, variant) {
|
enumLogicGateVariants.or,
|
||||||
const gateType = enumVariantToGate[variant];
|
enumLogicGateVariants.not,
|
||||||
entity.components.LogicGate.type = gateType;
|
enumLogicGateVariants.xor,
|
||||||
|
];
|
||||||
const pinComp = entity.components.WiredPins;
|
}
|
||||||
|
|
||||||
switch (gateType) {
|
getRenderPins() {
|
||||||
case enumLogicGateType.and:
|
// We already have it included
|
||||||
case enumLogicGateType.xor:
|
return false;
|
||||||
case enumLogicGateType.or: {
|
}
|
||||||
pinComp.setSlots([
|
|
||||||
{
|
/**
|
||||||
pos: new Vector(0, 0),
|
*
|
||||||
direction: enumDirection.top,
|
* @param {Entity} entity
|
||||||
type: enumPinSlotType.logicalEjector,
|
* @param {number} rotationVariant
|
||||||
},
|
*/
|
||||||
{
|
updateVariants(entity, rotationVariant, variant) {
|
||||||
pos: new Vector(0, 0),
|
const gateType = enumVariantToGate[variant];
|
||||||
direction: enumDirection.left,
|
entity.components.LogicGate.type = gateType;
|
||||||
type: enumPinSlotType.logicalAcceptor,
|
|
||||||
},
|
const pinComp = entity.components.WiredPins;
|
||||||
{
|
|
||||||
pos: new Vector(0, 0),
|
switch (gateType) {
|
||||||
direction: enumDirection.right,
|
case enumLogicGateType.and:
|
||||||
type: enumPinSlotType.logicalAcceptor,
|
case enumLogicGateType.xor:
|
||||||
},
|
case enumLogicGateType.or: {
|
||||||
]);
|
pinComp.setSlots([
|
||||||
break;
|
{
|
||||||
}
|
pos: new Vector(0, 0),
|
||||||
case enumLogicGateType.transistor: {
|
direction: enumDirection.top,
|
||||||
pinComp.setSlots([
|
type: enumPinSlotType.logicalEjector,
|
||||||
{
|
},
|
||||||
pos: new Vector(0, 0),
|
{
|
||||||
direction: enumDirection.top,
|
pos: new Vector(0, 0),
|
||||||
type: enumPinSlotType.logicalEjector,
|
direction: enumDirection.left,
|
||||||
},
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
{
|
},
|
||||||
pos: new Vector(0, 0),
|
{
|
||||||
direction: enumDirection.left,
|
pos: new Vector(0, 0),
|
||||||
type: enumPinSlotType.logicalAcceptor,
|
direction: enumDirection.right,
|
||||||
},
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
{
|
},
|
||||||
pos: new Vector(0, 0),
|
]);
|
||||||
direction: enumDirection.bottom,
|
break;
|
||||||
type: enumPinSlotType.logicalAcceptor,
|
}
|
||||||
},
|
|
||||||
]);
|
case enumLogicGateType.not: {
|
||||||
break;
|
pinComp.setSlots([
|
||||||
}
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
case enumLogicGateType.not: {
|
direction: enumDirection.top,
|
||||||
pinComp.setSlots([
|
type: enumPinSlotType.logicalEjector,
|
||||||
{
|
},
|
||||||
pos: new Vector(0, 0),
|
{
|
||||||
direction: enumDirection.top,
|
pos: new Vector(0, 0),
|
||||||
type: enumPinSlotType.logicalEjector,
|
direction: enumDirection.bottom,
|
||||||
},
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
{
|
},
|
||||||
pos: new Vector(0, 0),
|
]);
|
||||||
direction: enumDirection.bottom,
|
break;
|
||||||
type: enumPinSlotType.logicalAcceptor,
|
}
|
||||||
},
|
|
||||||
]);
|
default:
|
||||||
break;
|
assertAlways("unknown logic gate type: " + gateType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default:
|
|
||||||
assertAlways("unknown logic gate type: " + gateType);
|
/**
|
||||||
}
|
* Creates the entity at the given location
|
||||||
}
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
/**
|
setupEntityComponents(entity) {
|
||||||
* Creates the entity at the given location
|
entity.addComponent(
|
||||||
* @param {Entity} entity
|
new WiredPinsComponent({
|
||||||
*/
|
slots: [],
|
||||||
setupEntityComponents(entity) {
|
})
|
||||||
entity.addComponent(
|
);
|
||||||
new WiredPinsComponent({
|
|
||||||
slots: [],
|
entity.addComponent(new LogicGateComponent({}));
|
||||||
})
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
entity.addComponent(new LogicGateComponent({}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
|
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||||
|
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumTransistorVariants = {
|
||||||
|
mirrored: "mirrored",
|
||||||
|
};
|
||||||
|
|
||||||
|
const overlayMatrices = {
|
||||||
|
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
|
||||||
|
[enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
|
||||||
|
};
|
||||||
|
|
||||||
|
export class MetaTransistorBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("transistor");
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#bc3a61";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
|
// @todo
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {"wires"} **/
|
||||||
|
getLayer() {
|
||||||
|
return "wires";
|
||||||
|
}
|
||||||
|
|
||||||
|
getDimensions() {
|
||||||
|
return new Vector(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAvailableVariants() {
|
||||||
|
return [defaultBuildingVariant, enumTransistorVariants.mirrored];
|
||||||
|
}
|
||||||
|
|
||||||
|
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||||
|
return overlayMatrices[variant][rotation];
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenderPins() {
|
||||||
|
// We already have it included
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Entity} entity
|
||||||
|
* @param {number} rotationVariant
|
||||||
|
*/
|
||||||
|
updateVariants(entity, rotationVariant, variant) {
|
||||||
|
entity.components.WiredPins.slots[1].direction =
|
||||||
|
variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new WiredPinsComponent({
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.top,
|
||||||
|
type: enumPinSlotType.logicalEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.left,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.bottom,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(
|
||||||
|
new LogicGateComponent({
|
||||||
|
type: enumLogicGateType.transistor,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,263 +1,272 @@
|
|||||||
import { Loader } from "../../core/loader";
|
import { Loader } from "../../core/loader";
|
||||||
import { generateMatrixRotations } from "../../core/utils";
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector";
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
import { SOUNDS } from "../../platform/sound";
|
import { SOUNDS } from "../../platform/sound";
|
||||||
import { enumWireType, WireComponent } from "../components/wire";
|
import { enumWireType, enumWireVariant, WireComponent } from "../components/wire";
|
||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { MetaBuilding } from "../meta_building";
|
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
export const arrayWireRotationVariantToType = [
|
export const arrayWireRotationVariantToType = [
|
||||||
enumWireType.regular,
|
enumWireType.forward,
|
||||||
enumWireType.turn,
|
enumWireType.turn,
|
||||||
enumWireType.split,
|
enumWireType.split,
|
||||||
enumWireType.cross,
|
enumWireType.cross,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const wireOverlayMatrices = {
|
export const wireOverlayMatrices = {
|
||||||
[enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
|
[enumWireType.forward]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
|
||||||
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
|
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
|
||||||
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
|
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
|
||||||
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
|
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
|
||||||
};
|
};
|
||||||
|
|
||||||
export class MetaWireBuilding extends MetaBuilding {
|
/** @enum {string} */
|
||||||
constructor() {
|
export const wireVariants = {
|
||||||
super("wire");
|
second: "second",
|
||||||
}
|
third: "third",
|
||||||
|
};
|
||||||
getHasDirectionLockAvailable() {
|
|
||||||
return true;
|
const enumWireVariantToVariant = {
|
||||||
}
|
[defaultBuildingVariant]: enumWireVariant.first,
|
||||||
|
[wireVariants.second]: enumWireVariant.second,
|
||||||
getSilhouetteColor() {
|
[wireVariants.third]: enumWireVariant.third,
|
||||||
return "#25fff2";
|
};
|
||||||
}
|
|
||||||
|
export class MetaWireBuilding extends MetaBuilding {
|
||||||
getDimensions() {
|
constructor() {
|
||||||
return new Vector(1, 1);
|
super("wire");
|
||||||
}
|
}
|
||||||
|
|
||||||
getStayInPlacementMode() {
|
getHasDirectionLockAvailable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlacementSound() {
|
getSilhouetteColor() {
|
||||||
return SOUNDS.placeBelt;
|
return "#61ef6f";
|
||||||
}
|
}
|
||||||
|
|
||||||
getRotateAutomaticallyWhilePlacing() {
|
getAvailableVariants() {
|
||||||
return true;
|
return [defaultBuildingVariant, wireVariants.second, wireVariants.third];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {"wires"} **/
|
getDimensions() {
|
||||||
getLayer() {
|
return new Vector(1, 1);
|
||||||
return "wires";
|
}
|
||||||
}
|
|
||||||
|
getStayInPlacementMode() {
|
||||||
getSprite() {
|
return true;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
getPlacementSound() {
|
||||||
getIsReplaceable() {
|
return SOUNDS.placeBelt;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
getRotateAutomaticallyWhilePlacing() {
|
||||||
/**
|
return true;
|
||||||
* @param {GameRoot} root
|
}
|
||||||
*/
|
|
||||||
getIsUnlocked(root) {
|
/** @returns {"wires"} **/
|
||||||
// @todo
|
getLayer() {
|
||||||
return true;
|
return "wires";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getSprite() {
|
||||||
* Creates the entity at the given location
|
return null;
|
||||||
* @param {Entity} entity
|
}
|
||||||
*/
|
|
||||||
setupEntityComponents(entity) {
|
getIsReplaceable() {
|
||||||
// @todo
|
return true;
|
||||||
entity.addComponent(new WireComponent({}));
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @param {GameRoot} root
|
||||||
*
|
*/
|
||||||
* @param {Entity} entity
|
getIsUnlocked(root) {
|
||||||
* @param {number} rotationVariant
|
// @todo
|
||||||
*/
|
return true;
|
||||||
updateVariants(entity, rotationVariant) {
|
}
|
||||||
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
|
|
||||||
}
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
/**
|
* @param {Entity} entity
|
||||||
*
|
*/
|
||||||
* @param {number} rotation
|
setupEntityComponents(entity) {
|
||||||
* @param {number} rotationVariant
|
entity.addComponent(new WireComponent({}));
|
||||||
* @param {string} variant
|
}
|
||||||
* @param {Entity} entity
|
|
||||||
*/
|
/**
|
||||||
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
|
*
|
||||||
return wireOverlayMatrices[entity.components.Wire.type][rotation];
|
* @param {Entity} entity
|
||||||
}
|
* @param {number} rotationVariant
|
||||||
|
* @param {string} variant
|
||||||
getPreviewSprite(rotationVariant) {
|
*/
|
||||||
switch (arrayWireRotationVariantToType[rotationVariant]) {
|
updateVariants(entity, rotationVariant, variant) {
|
||||||
case enumWireType.regular: {
|
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
|
||||||
return Loader.getSprite("sprites/buildings/wire.png");
|
entity.components.Wire.variant = enumWireVariantToVariant[variant];
|
||||||
}
|
}
|
||||||
case enumWireType.turn: {
|
|
||||||
return Loader.getSprite("sprites/buildings/wire-turn.png");
|
/**
|
||||||
}
|
*
|
||||||
case enumWireType.split: {
|
* @param {number} rotation
|
||||||
return Loader.getSprite("sprites/buildings/wire-split.png");
|
* @param {number} rotationVariant
|
||||||
}
|
* @param {string} variant
|
||||||
case enumWireType.cross: {
|
* @param {Entity} entity
|
||||||
return Loader.getSprite("sprites/buildings/wire-cross.png");
|
*/
|
||||||
}
|
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
|
||||||
default: {
|
return wireOverlayMatrices[entity.components.Wire.type][rotation];
|
||||||
assertAlways(false, "Invalid wire rotation variant");
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
}
|
*
|
||||||
|
* @param {number} rotationVariant
|
||||||
getBlueprintSprite(rotationVariant) {
|
* @param {string} variant
|
||||||
switch (arrayWireRotationVariantToType[rotationVariant]) {
|
* @returns {import("../../core/draw_utils").AtlasSprite}
|
||||||
case enumWireType.regular: {
|
*/
|
||||||
return Loader.getSprite("sprites/blueprints/wire.png");
|
getPreviewSprite(rotationVariant, variant) {
|
||||||
}
|
const wireVariant = enumWireVariantToVariant[variant];
|
||||||
case enumWireType.turn: {
|
switch (arrayWireRotationVariantToType[rotationVariant]) {
|
||||||
return Loader.getSprite("sprites/blueprints/wire-turn.png");
|
case enumWireType.forward: {
|
||||||
}
|
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png");
|
||||||
case enumWireType.split: {
|
}
|
||||||
return Loader.getSprite("sprites/blueprints/wire-split.png");
|
case enumWireType.turn: {
|
||||||
}
|
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_turn.png");
|
||||||
case enumWireType.cross: {
|
}
|
||||||
return Loader.getSprite("sprites/blueprints/wire-cross.png");
|
case enumWireType.split: {
|
||||||
}
|
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_split.png");
|
||||||
default: {
|
}
|
||||||
assertAlways(false, "Invalid wire rotation variant");
|
case enumWireType.cross: {
|
||||||
}
|
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_cross.png");
|
||||||
}
|
}
|
||||||
}
|
default: {
|
||||||
|
assertAlways(false, "Invalid wire rotation variant");
|
||||||
/**
|
}
|
||||||
* Should compute the optimal rotation variant on the given tile
|
}
|
||||||
* @param {object} param0
|
}
|
||||||
* @param {GameRoot} param0.root
|
|
||||||
* @param {Vector} param0.tile
|
getBlueprintSprite(rotationVariant, variant) {
|
||||||
* @param {number} param0.rotation
|
return this.getPreviewSprite(rotationVariant, variant);
|
||||||
* @param {string} param0.variant
|
}
|
||||||
* @param {string} param0.layer
|
|
||||||
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
|
/**
|
||||||
*/
|
* Should compute the optimal rotation variant on the given tile
|
||||||
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
|
* @param {object} param0
|
||||||
const connections = {
|
* @param {GameRoot} param0.root
|
||||||
top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }),
|
* @param {Vector} param0.tile
|
||||||
right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }),
|
* @param {number} param0.rotation
|
||||||
bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }),
|
* @param {string} param0.variant
|
||||||
left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }),
|
* @param {string} param0.layer
|
||||||
};
|
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
|
||||||
|
*/
|
||||||
let flag = 0;
|
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
|
||||||
flag |= connections.top ? 0x1000 : 0;
|
const wireVariant = enumWireVariantToVariant[variant];
|
||||||
flag |= connections.right ? 0x100 : 0;
|
const connections = {
|
||||||
flag |= connections.bottom ? 0x10 : 0;
|
top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }),
|
||||||
flag |= connections.left ? 0x1 : 0;
|
right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }),
|
||||||
|
bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }),
|
||||||
let targetType = enumWireType.regular;
|
left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }),
|
||||||
|
};
|
||||||
// First, reset rotation
|
|
||||||
rotation = 0;
|
let flag = 0;
|
||||||
|
flag |= connections.top ? 0x1000 : 0;
|
||||||
switch (flag) {
|
flag |= connections.right ? 0x100 : 0;
|
||||||
case 0x0000:
|
flag |= connections.bottom ? 0x10 : 0;
|
||||||
// Nothing
|
flag |= connections.left ? 0x1 : 0;
|
||||||
break;
|
|
||||||
|
let targetType = enumWireType.forward;
|
||||||
case 0x0001:
|
|
||||||
// Left
|
// First, reset rotation
|
||||||
rotation += 90;
|
rotation = 0;
|
||||||
break;
|
|
||||||
|
switch (flag) {
|
||||||
case 0x0010:
|
case 0x0000:
|
||||||
// Bottom
|
// Nothing
|
||||||
// END
|
break;
|
||||||
break;
|
|
||||||
|
case 0x0001:
|
||||||
case 0x0011:
|
// Left
|
||||||
// Bottom | Left
|
rotation += 90;
|
||||||
targetType = enumWireType.turn;
|
break;
|
||||||
rotation += 90;
|
|
||||||
break;
|
case 0x0010:
|
||||||
|
// Bottom
|
||||||
case 0x0100:
|
// END
|
||||||
// Right
|
break;
|
||||||
rotation += 90;
|
|
||||||
break;
|
case 0x0011:
|
||||||
|
// Bottom | Left
|
||||||
case 0x0101:
|
targetType = enumWireType.turn;
|
||||||
// Right | Left
|
rotation += 90;
|
||||||
rotation += 90;
|
break;
|
||||||
break;
|
|
||||||
|
case 0x0100:
|
||||||
case 0x0110:
|
// Right
|
||||||
// Right | Bottom
|
rotation += 90;
|
||||||
targetType = enumWireType.turn;
|
break;
|
||||||
break;
|
|
||||||
|
case 0x0101:
|
||||||
case 0x0111:
|
// Right | Left
|
||||||
// Right | Bottom | Left
|
rotation += 90;
|
||||||
targetType = enumWireType.split;
|
break;
|
||||||
break;
|
|
||||||
|
case 0x0110:
|
||||||
case 0x1000:
|
// Right | Bottom
|
||||||
// Top
|
targetType = enumWireType.turn;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1001:
|
case 0x0111:
|
||||||
// Top | Left
|
// Right | Bottom | Left
|
||||||
targetType = enumWireType.turn;
|
targetType = enumWireType.split;
|
||||||
rotation += 180;
|
break;
|
||||||
break;
|
|
||||||
|
case 0x1000:
|
||||||
case 0x1010:
|
// Top
|
||||||
// Top | Bottom
|
break;
|
||||||
break;
|
|
||||||
|
case 0x1001:
|
||||||
case 0x1011:
|
// Top | Left
|
||||||
// Top | Bottom | Left
|
targetType = enumWireType.turn;
|
||||||
targetType = enumWireType.split;
|
rotation += 180;
|
||||||
rotation += 90;
|
break;
|
||||||
break;
|
|
||||||
|
case 0x1010:
|
||||||
case 0x1100:
|
// Top | Bottom
|
||||||
// Top | Right
|
break;
|
||||||
targetType = enumWireType.turn;
|
|
||||||
rotation -= 90;
|
case 0x1011:
|
||||||
break;
|
// Top | Bottom | Left
|
||||||
|
targetType = enumWireType.split;
|
||||||
case 0x1101:
|
rotation += 90;
|
||||||
// Top | Right | Left
|
break;
|
||||||
targetType = enumWireType.split;
|
|
||||||
rotation += 180;
|
case 0x1100:
|
||||||
break;
|
// Top | Right
|
||||||
|
targetType = enumWireType.turn;
|
||||||
case 0x1110:
|
rotation -= 90;
|
||||||
// Top | Right | Bottom
|
break;
|
||||||
targetType = enumWireType.split;
|
|
||||||
rotation -= 90;
|
case 0x1101:
|
||||||
break;
|
// Top | Right | Left
|
||||||
|
targetType = enumWireType.split;
|
||||||
case 0x1111:
|
rotation += 180;
|
||||||
// Top | Right | Bottom | Left
|
break;
|
||||||
targetType = enumWireType.cross;
|
|
||||||
break;
|
case 0x1110:
|
||||||
}
|
// Top | Right | Bottom
|
||||||
|
targetType = enumWireType.split;
|
||||||
return {
|
rotation -= 90;
|
||||||
// Clamp rotation
|
break;
|
||||||
rotation: (rotation + 360 * 10) % 360,
|
|
||||||
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType),
|
case 0x1111:
|
||||||
};
|
// Top | Right | Bottom | Left
|
||||||
}
|
targetType = enumWireType.cross;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Clamp rotation
|
||||||
|
rotation: (rotation + 360 * 10) % 360,
|
||||||
|
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,87 +1,58 @@
|
|||||||
import { Vector } from "../../core/vector";
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
import { Entity } from "../entity";
|
import { Vector } from "../../core/vector";
|
||||||
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
|
import { WireTunnelComponent } from "../components/wire_tunnel";
|
||||||
import { GameRoot } from "../root";
|
import { Entity } from "../entity";
|
||||||
import { WireTunnelComponent } from "../components/wire_tunnel";
|
import { MetaBuilding } from "../meta_building";
|
||||||
import { generateMatrixRotations } from "../../core/utils";
|
import { GameRoot } from "../root";
|
||||||
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
/** @enum {string} */
|
|
||||||
export const enumWireTunnelVariants = {
|
const wireTunnelOverlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]);
|
||||||
coating: "coating",
|
|
||||||
};
|
export class MetaWireTunnelBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
const wireTunnelOverlayMatrices = {
|
super("wire_tunnel");
|
||||||
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
|
}
|
||||||
[enumWireTunnelVariants.coating]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
|
|
||||||
};
|
getSilhouetteColor() {
|
||||||
|
return "#777a86";
|
||||||
export class MetaWireTunnelBuilding extends MetaBuilding {
|
}
|
||||||
constructor() {
|
|
||||||
super("wire_tunnel");
|
/**
|
||||||
}
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
getSilhouetteColor() {
|
getIsUnlocked(root) {
|
||||||
return "#777a86";
|
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {GameRoot} root
|
*
|
||||||
*/
|
* @param {number} rotation
|
||||||
getIsUnlocked(root) {
|
* @param {number} rotationVariant
|
||||||
// @todo
|
* @param {string} variant
|
||||||
return true;
|
* @param {Entity} entity
|
||||||
}
|
*/
|
||||||
|
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
|
||||||
/**
|
return wireTunnelOverlayMatrix[rotation];
|
||||||
*
|
}
|
||||||
* @param {number} rotation
|
|
||||||
* @param {number} rotationVariant
|
getIsRotateable() {
|
||||||
* @param {string} variant
|
return false;
|
||||||
* @param {Entity} entity
|
}
|
||||||
*/
|
|
||||||
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
|
getDimensions() {
|
||||||
return wireTunnelOverlayMatrices[variant][rotation];
|
return new Vector(1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIsRotateable(variant) {
|
/** @returns {"wires"} **/
|
||||||
return variant !== defaultBuildingVariant;
|
getLayer() {
|
||||||
}
|
return "wires";
|
||||||
|
}
|
||||||
getDimensions() {
|
|
||||||
return new Vector(1, 1);
|
/**
|
||||||
}
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
getAvailableVariants() {
|
*/
|
||||||
return [defaultBuildingVariant, enumWireTunnelVariants.coating];
|
setupEntityComponents(entity) {
|
||||||
}
|
entity.addComponent(new WireTunnelComponent({}));
|
||||||
|
}
|
||||||
/** @returns {"wires"} **/
|
}
|
||||||
getLayer() {
|
|
||||||
return "wires";
|
|
||||||
}
|
|
||||||
|
|
||||||
getRotateAutomaticallyWhilePlacing() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStayInPlacementMode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the entity at the given location
|
|
||||||
* @param {Entity} entity
|
|
||||||
*/
|
|
||||||
setupEntityComponents(entity) {
|
|
||||||
entity.addComponent(new WireTunnelComponent({}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Entity} entity
|
|
||||||
* @param {number} rotationVariant
|
|
||||||
* @param {string} variant
|
|
||||||
*/
|
|
||||||
updateVariants(entity, rotationVariant, variant) {
|
|
||||||
entity.components.WireTunnel.multipleDirections = variant === defaultBuildingVariant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|