Merge branch 'master' into master
22
README.md
@ -92,6 +92,28 @@ This project is based on ES5. Some ES2015 features are used but most of them are
|
|||||||
4. Add the system in `src/js/game/game_system_manager.js` (To `this.systems` and also call `add` in the `internalInitSystems()` method)
|
4. Add the system in `src/js/game/game_system_manager.js` (To `this.systems` and also call `add` in the `internalInitSystems()` method)
|
||||||
5. If your system should draw stuff, this is a bit more complicated. Have a look at existing systems on how they do it.
|
5. If your system should draw stuff, this is a bit more complicated. Have a look at existing systems on how they do it.
|
||||||
|
|
||||||
|
#### Checklist for a new building / testing it
|
||||||
|
|
||||||
|
This is a quick checklist, if a new building is added this points should be fulfilled:
|
||||||
|
|
||||||
|
2. The translation for all variants is done and finalized
|
||||||
|
3. The artwork (regular sprite) is finalized
|
||||||
|
4. The blueprint sprite has been generated and is up to date
|
||||||
|
5. The building has been added to the appropriate toolbar
|
||||||
|
6. The building has a keybinding which makes sense
|
||||||
|
7. The building has a reward assigned and is unlocked at a meaningful point
|
||||||
|
8. The reward for the building has a proper translation
|
||||||
|
9. The reward for the building has a proper image
|
||||||
|
10. The building has a proper tutorial image assigned
|
||||||
|
11. The buliding has a proper toolbar icon
|
||||||
|
12. The reward requires a proper shape
|
||||||
|
13. The building has a proper silhouette color
|
||||||
|
14. The building has a proper matrix for being rendered on the minimap
|
||||||
|
15. The building has proper statistics in the dialog
|
||||||
|
16. The building properly contributes to the shapes produced analytics
|
||||||
|
17. The building is properly persisted in the savegame
|
||||||
|
18. The building is explained properly, ideally via an interactive tutorial
|
||||||
|
|
||||||
### Assets
|
### Assets
|
||||||
|
|
||||||
For most assets I use Adobe Photoshop, you can find them in `assets/`.
|
For most assets I use Adobe Photoshop, you can find them in `assets/`.
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
// Converts the atlas description to a JSON file
|
|
||||||
|
|
||||||
String.prototype.replaceAll = function (search, replacement) {
|
|
||||||
var target = this;
|
|
||||||
return target.split(search).join(replacement);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
const folder = path.join(__dirname, "res_built", "atlas");
|
|
||||||
const files = fs.readdirSync(folder);
|
|
||||||
|
|
||||||
const metadata = [];
|
|
||||||
|
|
||||||
files.forEach(filename => {
|
|
||||||
if (filename.endsWith(".atlas")) {
|
|
||||||
// Read content
|
|
||||||
|
|
||||||
const content = fs.readFileSync(path.join(folder, filename), "ascii");
|
|
||||||
|
|
||||||
const lines = content.replaceAll("\r", "").replaceAll("\t", "").split("\n");
|
|
||||||
|
|
||||||
const readLine = () => lines.splice(0, 1)[0];
|
|
||||||
const readValue = () => readLine().replaceAll(" ", "").split(":")[1];
|
|
||||||
const readVector = () =>
|
|
||||||
readValue()
|
|
||||||
.split(",")
|
|
||||||
.map(d => parseInt(d, 10));
|
|
||||||
|
|
||||||
let maxAtlas = 100;
|
|
||||||
|
|
||||||
atlasLoop: while (maxAtlas-- > 0 && lines.length >= 7) {
|
|
||||||
const result = {
|
|
||||||
entries: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extract header
|
|
||||||
const header_fileStart = readLine();
|
|
||||||
const header_fileName = readLine();
|
|
||||||
const header_size = readVector();
|
|
||||||
const header_format = readLine();
|
|
||||||
const header_filter = readLine();
|
|
||||||
const header_repeat = readLine();
|
|
||||||
const baseAtlasName = header_fileName.replace(".png", "");
|
|
||||||
|
|
||||||
// Store size
|
|
||||||
result.size = header_size;
|
|
||||||
|
|
||||||
lineLoop: while (lines.length >= 7) {
|
|
||||||
const entryResult = {};
|
|
||||||
|
|
||||||
const nextLine = lines[0];
|
|
||||||
if (nextLine.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const entry_fileName = readLine() + ".png";
|
|
||||||
|
|
||||||
const entry_rotate = readValue();
|
|
||||||
const entry_xy = readVector();
|
|
||||||
const entry_size = readVector();
|
|
||||||
const entry_orig = readVector();
|
|
||||||
const entry_offset = readVector();
|
|
||||||
const entry_index = readValue();
|
|
||||||
|
|
||||||
entryResult.filename = entry_fileName;
|
|
||||||
entryResult.xy = entry_xy;
|
|
||||||
entryResult.size = entry_size;
|
|
||||||
// entryResult.offset = entry_offset;
|
|
||||||
|
|
||||||
entryResult.origSize = entry_orig;
|
|
||||||
|
|
||||||
let offset = [0, 0];
|
|
||||||
|
|
||||||
// GDX Atlas packer uses 1 - y coordinates. This sucks, and we have to convert it
|
|
||||||
offset[0] = entry_offset[0];
|
|
||||||
offset[1] = entry_orig[1] - entry_offset[1] - entry_size[1];
|
|
||||||
|
|
||||||
entryResult.offset = offset;
|
|
||||||
|
|
||||||
result.entries.push(entryResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[Atlas]", "'" + baseAtlasName + "'", "has", result.entries.length, "entries");
|
|
||||||
// fs.writeFileSync(path.join(folder, baseAtlasName + ".gen.json"), JSON.stringify(result));
|
|
||||||
|
|
||||||
metadata.push({
|
|
||||||
filename: baseAtlasName + ".png",
|
|
||||||
entries: result,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(path.join(folder, "meta.gen.json"), JSON.stringify(metadata, null, 4));
|
|
@ -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,
|
|
||||||
};
|
|
||||||
|
@ -18,7 +18,7 @@ function gulptasksSounds($, gulp, buildFolder) {
|
|||||||
|
|
||||||
function getFileCacheValue(file) {
|
function getFileCacheValue(file) {
|
||||||
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
|
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
|
||||||
const encodedContents = Buffer.from(contents).toString('base64');
|
const encodedContents = Buffer.from(contents).toString("base64");
|
||||||
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
|
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,6 @@ function gulptasksSounds($, gulp, buildFolder) {
|
|||||||
return gulp
|
return gulp
|
||||||
.src(path.join(builtSoundsDir, "**", "*.mp3"))
|
.src(path.join(builtSoundsDir, "**", "*.mp3"))
|
||||||
.pipe($.plumber())
|
.pipe($.plumber())
|
||||||
.pipe($.cached("sounds.copy"))
|
|
||||||
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
|
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
BIN
res/ui/building_icons/analyzer.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
res/ui/building_icons/comparator.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 6.8 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 |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
BIN
res/ui/building_icons/transistor.png
Normal file
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 |
BIN
res/ui/building_tutorials/analyzer.png
Normal file
After Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 157 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 36 KiB |
BIN
res/ui/building_tutorials/logic_gate-and.png
Normal file
After Width: | Height: | Size: 281 KiB |
BIN
res/ui/building_tutorials/logic_gate-not.png
Normal file
After Width: | Height: | Size: 287 KiB |
BIN
res/ui/building_tutorials/logic_gate-or.png
Normal file
After Width: | Height: | Size: 283 KiB |
BIN
res/ui/building_tutorials/logic_gate-xor.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
res/ui/building_tutorials/painter-mirrored.png
Normal file
After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 165 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 40 KiB |
BIN
res/ui/building_tutorials/transistor.png
Normal file
After Width: | Height: | Size: 260 KiB |
BIN
res/ui/building_tutorials/virtual_processor-cutter.png
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
res/ui/building_tutorials/virtual_processor-painter.png
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
res/ui/building_tutorials/virtual_processor-rotater.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
res/ui/building_tutorials/virtual_processor-stacker.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
res/ui/building_tutorials/virtual_processor-unstacker.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
res/ui/building_tutorials/wire-second.png
Normal file
After Width: | Height: | Size: 114 KiB |
BIN
res/ui/building_tutorials/wire.png
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
res/ui/building_tutorials/wire_tunnel.png
Normal file
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: 700 KiB |
@ -104,7 +104,7 @@
|
|||||||
</struct>
|
</struct>
|
||||||
</struct>
|
</struct>
|
||||||
<key>shapePadding</key>
|
<key>shapePadding</key>
|
||||||
<uint>0</uint>
|
<uint>2</uint>
|
||||||
<key>jpgQuality</key>
|
<key>jpgQuality</key>
|
||||||
<uint>80</uint>
|
<uint>80</uint>
|
||||||
<key>pngOptimizationLevel</key>
|
<key>pngOptimizationLevel</key>
|
||||||
@ -118,7 +118,7 @@
|
|||||||
<key>textureFormat</key>
|
<key>textureFormat</key>
|
||||||
<enum type="SettingsBase::TextureFormat">png</enum>
|
<enum type="SettingsBase::TextureFormat">png</enum>
|
||||||
<key>borderPadding</key>
|
<key>borderPadding</key>
|
||||||
<uint>1</uint>
|
<uint>3</uint>
|
||||||
<key>maxTextureSize</key>
|
<key>maxTextureSize</key>
|
||||||
<QSize>
|
<QSize>
|
||||||
<key>width</key>
|
<key>width</key>
|
||||||
@ -197,7 +197,7 @@
|
|||||||
<key>scaleMode</key>
|
<key>scaleMode</key>
|
||||||
<enum type="ScaleMode">Smooth</enum>
|
<enum type="ScaleMode">Smooth</enum>
|
||||||
<key>extrude</key>
|
<key>extrude</key>
|
||||||
<uint>3</uint>
|
<uint>2</uint>
|
||||||
<key>trimThreshold</key>
|
<key>trimThreshold</key>
|
||||||
<uint>2</uint>
|
<uint>2</uint>
|
||||||
<key>trimMargin</key>
|
<key>trimMargin</key>
|
||||||
@ -257,16 +257,20 @@
|
|||||||
<key type="filename">sprites/belt/built/right_7.png</key>
|
<key type="filename">sprites/belt/built/right_7.png</key>
|
||||||
<key type="filename">sprites/belt/built/right_8.png</key>
|
<key type="filename">sprites/belt/built/right_8.png</key>
|
||||||
<key type="filename">sprites/belt/built/right_9.png</key>
|
<key type="filename">sprites/belt/built/right_9.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/analyzer.png</key>
|
||||||
<key type="filename">sprites/blueprints/balancer-merger-inverse.png</key>
|
<key type="filename">sprites/blueprints/balancer-merger-inverse.png</key>
|
||||||
<key type="filename">sprites/blueprints/balancer-merger.png</key>
|
<key type="filename">sprites/blueprints/balancer-merger.png</key>
|
||||||
<key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key>
|
<key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key>
|
||||||
<key type="filename">sprites/blueprints/balancer-splitter.png</key>
|
<key type="filename">sprites/blueprints/balancer-splitter.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/belt_left.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/belt_right.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/belt_top.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/comparator.png</key>
|
||||||
<key type="filename">sprites/blueprints/constant_signal.png</key>
|
<key type="filename">sprites/blueprints/constant_signal.png</key>
|
||||||
<key type="filename">sprites/blueprints/display.png</key>
|
<key type="filename">sprites/blueprints/display.png</key>
|
||||||
<key type="filename">sprites/blueprints/lever.png</key>
|
<key type="filename">sprites/blueprints/lever.png</key>
|
||||||
<key type="filename">sprites/blueprints/logic_gate-not.png</key>
|
<key type="filename">sprites/blueprints/logic_gate-not.png</key>
|
||||||
<key type="filename">sprites/blueprints/logic_gate-or.png</key>
|
<key type="filename">sprites/blueprints/logic_gate-or.png</key>
|
||||||
<key type="filename">sprites/blueprints/logic_gate-transistor.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/logic_gate-xor.png</key>
|
<key type="filename">sprites/blueprints/logic_gate-xor.png</key>
|
||||||
<key type="filename">sprites/blueprints/logic_gate.png</key>
|
<key type="filename">sprites/blueprints/logic_gate.png</key>
|
||||||
<key type="filename">sprites/blueprints/miner-chainable.png</key>
|
<key type="filename">sprites/blueprints/miner-chainable.png</key>
|
||||||
@ -275,67 +279,62 @@
|
|||||||
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
|
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
|
||||||
<key type="filename">sprites/blueprints/rotater-rotate180.png</key>
|
<key type="filename">sprites/blueprints/rotater-rotate180.png</key>
|
||||||
<key type="filename">sprites/blueprints/rotater.png</key>
|
<key type="filename">sprites/blueprints/rotater.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/transistor-mirrored.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/transistor.png</key>
|
||||||
<key type="filename">sprites/blueprints/trash.png</key>
|
<key type="filename">sprites/blueprints/trash.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-analyzer.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-painter.png</key>
|
<key type="filename">sprites/blueprints/virtual_processor-painter.png</key>
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
|
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-shapecompare.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-stacker.png</key>
|
<key type="filename">sprites/blueprints/virtual_processor-stacker.png</key>
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
|
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
|
||||||
<key type="filename">sprites/blueprints/virtual_processor.png</key>
|
<key type="filename">sprites/blueprints/virtual_processor.png</key>
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
||||||
|
<key type="filename">sprites/buildings/analyzer.png</key>
|
||||||
<key type="filename">sprites/buildings/balancer-merger-inverse.png</key>
|
<key type="filename">sprites/buildings/balancer-merger-inverse.png</key>
|
||||||
<key type="filename">sprites/buildings/balancer-merger.png</key>
|
<key type="filename">sprites/buildings/balancer-merger.png</key>
|
||||||
<key type="filename">sprites/buildings/balancer-splitter-inverse.png</key>
|
<key type="filename">sprites/buildings/balancer-splitter-inverse.png</key>
|
||||||
<key type="filename">sprites/buildings/balancer-splitter.png</key>
|
<key type="filename">sprites/buildings/balancer-splitter.png</key>
|
||||||
|
<key type="filename">sprites/buildings/comparator.png</key>
|
||||||
<key type="filename">sprites/buildings/constant_signal.png</key>
|
<key type="filename">sprites/buildings/constant_signal.png</key>
|
||||||
<key type="filename">sprites/buildings/display.png</key>
|
<key type="filename">sprites/buildings/display.png</key>
|
||||||
<key type="filename">sprites/buildings/lever.png</key>
|
<key type="filename">sprites/buildings/lever.png</key>
|
||||||
<key type="filename">sprites/buildings/logic_gate-not.png</key>
|
<key type="filename">sprites/buildings/logic_gate-not.png</key>
|
||||||
<key type="filename">sprites/buildings/logic_gate-or.png</key>
|
<key type="filename">sprites/buildings/logic_gate-or.png</key>
|
||||||
<key type="filename">sprites/buildings/logic_gate-transistor.png</key>
|
|
||||||
<key type="filename">sprites/buildings/logic_gate-xor.png</key>
|
<key type="filename">sprites/buildings/logic_gate-xor.png</key>
|
||||||
<key type="filename">sprites/buildings/logic_gate.png</key>
|
<key type="filename">sprites/buildings/logic_gate.png</key>
|
||||||
<key type="filename">sprites/buildings/miner-chainable.png</key>
|
<key type="filename">sprites/buildings/miner-chainable.png</key>
|
||||||
<key type="filename">sprites/buildings/reader.png</key>
|
<key type="filename">sprites/buildings/reader.png</key>
|
||||||
<key type="filename">sprites/buildings/rotater-ccw.png</key>
|
<key type="filename">sprites/buildings/rotater-ccw.png</key>
|
||||||
<key type="filename">sprites/buildings/rotater-rotate180.png</key>
|
<key type="filename">sprites/buildings/rotater-rotate180.png</key>
|
||||||
|
<key type="filename">sprites/buildings/transistor-mirrored.png</key>
|
||||||
|
<key type="filename">sprites/buildings/transistor.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key>
|
<key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_entry.png</key>
|
<key type="filename">sprites/buildings/underground_belt_entry.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
||||||
<key type="filename">sprites/buildings/virtual_processor-analyzer.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-painter.png</key>
|
<key type="filename">sprites/buildings/virtual_processor-painter.png</key>
|
||||||
<key type="filename">sprites/buildings/virtual_processor-rotater.png</key>
|
<key type="filename">sprites/buildings/virtual_processor-rotater.png</key>
|
||||||
<key type="filename">sprites/buildings/virtual_processor-shapecompare.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-stacker.png</key>
|
<key type="filename">sprites/buildings/virtual_processor-stacker.png</key>
|
||||||
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
|
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
|
||||||
<key type="filename">sprites/buildings/virtual_processor.png</key>
|
<key type="filename">sprites/buildings/virtual_processor.png</key>
|
||||||
<key type="filename">sprites/buildings/wire_tunnel-coating.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire_tunnel.png</key>
|
<key type="filename">sprites/buildings/wire_tunnel.png</key>
|
||||||
<key type="filename">sprites/misc/reader_overlay.png</key>
|
<key type="filename">sprites/misc/reader_overlay.png</key>
|
||||||
<key type="filename">sprites/wires/lever_on.png</key>
|
<key type="filename">sprites/wires/lever_on.png</key>
|
||||||
<key type="filename">sprites/wires/sets/color_cross.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/color_forward.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/color_split.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/color_turn.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/conflict_cross.png</key>
|
<key type="filename">sprites/wires/sets/conflict_cross.png</key>
|
||||||
<key type="filename">sprites/wires/sets/conflict_forward.png</key>
|
<key type="filename">sprites/wires/sets/conflict_forward.png</key>
|
||||||
<key type="filename">sprites/wires/sets/conflict_split.png</key>
|
<key type="filename">sprites/wires/sets/conflict_split.png</key>
|
||||||
<key type="filename">sprites/wires/sets/conflict_turn.png</key>
|
<key type="filename">sprites/wires/sets/conflict_turn.png</key>
|
||||||
<key type="filename">sprites/wires/sets/regular_cross.png</key>
|
<key type="filename">sprites/wires/sets/first_cross.png</key>
|
||||||
<key type="filename">sprites/wires/sets/regular_forward.png</key>
|
<key type="filename">sprites/wires/sets/first_forward.png</key>
|
||||||
<key type="filename">sprites/wires/sets/regular_split.png</key>
|
<key type="filename">sprites/wires/sets/first_split.png</key>
|
||||||
<key type="filename">sprites/wires/sets/regular_turn.png</key>
|
<key type="filename">sprites/wires/sets/first_turn.png</key>
|
||||||
<key type="filename">sprites/wires/sets/shape_cross.png</key>
|
<key type="filename">sprites/wires/sets/second_cross.png</key>
|
||||||
<key type="filename">sprites/wires/sets/shape_forward.png</key>
|
<key type="filename">sprites/wires/sets/second_forward.png</key>
|
||||||
<key type="filename">sprites/wires/sets/shape_split.png</key>
|
<key type="filename">sprites/wires/sets/second_split.png</key>
|
||||||
<key type="filename">sprites/wires/sets/shape_turn.png</key>
|
<key type="filename">sprites/wires/sets/second_turn.png</key>
|
||||||
<struct type="IndividualSpriteSettings">
|
<struct type="IndividualSpriteSettings">
|
||||||
<key>pivotPoint</key>
|
<key>pivotPoint</key>
|
||||||
<point_f>0.5,0.5</point_f>
|
<point_f>0.5,0.5</point_f>
|
||||||
@ -374,34 +373,6 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
<key type="filename">sprites/blueprints/belt_left.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/belt_right.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/belt_top.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire-cross.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire-split.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire-turn.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire.png</key>
|
|
||||||
<key type="filename">sprites/buildings/belt_left.png</key>
|
|
||||||
<key type="filename">sprites/buildings/belt_right.png</key>
|
|
||||||
<key type="filename">sprites/buildings/belt_top.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire-cross.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire-split.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire-turn.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>32,32,63,63</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>32,32,63,63</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/blueprints/cutter-quad.png</key>
|
<key type="filename">sprites/blueprints/cutter-quad.png</key>
|
||||||
<key type="filename">sprites/blueprints/painter-quad.png</key>
|
<key type="filename">sprites/blueprints/painter-quad.png</key>
|
||||||
<key type="filename">sprites/buildings/cutter-quad.png</key>
|
<key type="filename">sprites/buildings/cutter-quad.png</key>
|
||||||
@ -421,8 +392,9 @@
|
|||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
<key type="filename">sprites/blueprints/painter-double.png</key>
|
<key type="filename">sprites/blueprints/painter-double.png</key>
|
||||||
<key type="filename">sprites/blueprints/trash-storage.png</key>
|
<key type="filename">sprites/blueprints/storage.png</key>
|
||||||
<key type="filename">sprites/buildings/painter-double.png</key>
|
<key type="filename">sprites/buildings/painter-double.png</key>
|
||||||
|
<key type="filename">sprites/buildings/storage.png</key>
|
||||||
<struct type="IndividualSpriteSettings">
|
<struct type="IndividualSpriteSettings">
|
||||||
<key>pivotPoint</key>
|
<key>pivotPoint</key>
|
||||||
<point_f>0.5,0.5</point_f>
|
<point_f>0.5,0.5</point_f>
|
||||||
@ -437,6 +409,23 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
|
<key type="filename">sprites/buildings/belt_left.png</key>
|
||||||
|
<key type="filename">sprites/buildings/belt_right.png</key>
|
||||||
|
<key type="filename">sprites/buildings/belt_top.png</key>
|
||||||
|
<struct type="IndividualSpriteSettings">
|
||||||
|
<key>pivotPoint</key>
|
||||||
|
<point_f>0.5,0.5</point_f>
|
||||||
|
<key>spriteScale</key>
|
||||||
|
<double>1</double>
|
||||||
|
<key>scale9Enabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>scale9Borders</key>
|
||||||
|
<rect>32,32,63,63</rect>
|
||||||
|
<key>scale9Paddings</key>
|
||||||
|
<rect>32,32,63,63</rect>
|
||||||
|
<key>scale9FromFile</key>
|
||||||
|
<false/>
|
||||||
|
</struct>
|
||||||
<key type="filename">sprites/buildings/cutter.png</key>
|
<key type="filename">sprites/buildings/cutter.png</key>
|
||||||
<key type="filename">sprites/buildings/mixer.png</key>
|
<key type="filename">sprites/buildings/mixer.png</key>
|
||||||
<key type="filename">sprites/buildings/painter.png</key>
|
<key type="filename">sprites/buildings/painter.png</key>
|
||||||
@ -492,21 +481,6 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
<key type="filename">sprites/buildings/trash-storage.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>144,144,288,288</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>144,144,288,288</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/colors/blue.png</key>
|
<key type="filename">sprites/colors/blue.png</key>
|
||||||
<key type="filename">sprites/colors/cyan.png</key>
|
<key type="filename">sprites/colors/cyan.png</key>
|
||||||
<key type="filename">sprites/colors/green.png</key>
|
<key type="filename">sprites/colors/green.png</key>
|
||||||
|
@ -1,226 +1,212 @@
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 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: "#5fb2f1",
|
||||||
b = 0;
|
conflict: "#f74c4c",
|
||||||
|
};
|
||||||
// 3 digits
|
|
||||||
if (h.length == 4) {
|
function hexToRGB(h) {
|
||||||
r = "0x" + h[1] + h[1];
|
let r = 0,
|
||||||
g = "0x" + h[2] + h[2];
|
g = 0,
|
||||||
b = "0x" + h[3] + h[3];
|
b = 0;
|
||||||
|
|
||||||
// 6 digits
|
// 3 digits
|
||||||
} else if (h.length == 7) {
|
if (h.length == 4) {
|
||||||
r = "0x" + h[1] + h[2];
|
r = "0x" + h[1] + h[1];
|
||||||
g = "0x" + h[3] + h[4];
|
g = "0x" + h[2] + h[2];
|
||||||
b = "0x" + h[5] + h[6];
|
b = "0x" + h[3] + h[3];
|
||||||
}
|
|
||||||
|
// 6 digits
|
||||||
return [+r, +g, +b];
|
} else if (h.length == 7) {
|
||||||
}
|
r = "0x" + h[1] + h[2];
|
||||||
|
g = "0x" + h[3] + h[4];
|
||||||
function RGBToHSL(r, g, b) {
|
b = "0x" + h[5] + h[6];
|
||||||
// Make r, g, and b fractions of 1
|
}
|
||||||
r /= 255;
|
|
||||||
g /= 255;
|
return [+r, +g, +b];
|
||||||
b /= 255;
|
}
|
||||||
|
|
||||||
// Find greatest and smallest channel values
|
function RGBToHSL(r, g, b) {
|
||||||
let cmin = Math.min(r, g, b),
|
// Make r, g, and b fractions of 1
|
||||||
cmax = Math.max(r, g, b),
|
r /= 255;
|
||||||
delta = cmax - cmin,
|
g /= 255;
|
||||||
h = 0,
|
b /= 255;
|
||||||
s = 0,
|
|
||||||
l = 0;
|
// Find greatest and smallest channel values
|
||||||
// Calculate hue
|
let cmin = Math.min(r, g, b),
|
||||||
// No difference
|
cmax = Math.max(r, g, b),
|
||||||
if (delta == 0) h = 0;
|
delta = cmax - cmin,
|
||||||
// Red is max
|
h = 0,
|
||||||
else if (cmax == r) h = ((g - b) / delta) % 6;
|
s = 0,
|
||||||
// Green is max
|
l = 0;
|
||||||
else if (cmax == g) h = (b - r) / delta + 2;
|
// Calculate hue
|
||||||
// Blue is max
|
// No difference
|
||||||
else h = (r - g) / delta + 4;
|
if (delta == 0) h = 0;
|
||||||
|
// Red is max
|
||||||
h = Math.round(h * 60);
|
else if (cmax == r) h = ((g - b) / delta) % 6;
|
||||||
|
// Green is max
|
||||||
// Make negative hues positive behind 360°
|
else if (cmax == g) h = (b - r) / delta + 2;
|
||||||
if (h < 0) h += 360;
|
// Blue is max
|
||||||
|
else h = (r - g) / delta + 4;
|
||||||
// Calculate lightness
|
|
||||||
l = (cmax + cmin) / 2;
|
h = Math.round(h * 60);
|
||||||
|
|
||||||
// Calculate saturation
|
// Make negative hues positive behind 360°
|
||||||
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
if (h < 0) h += 360;
|
||||||
|
|
||||||
// Multiply l and s by 100
|
// Calculate lightness
|
||||||
s = +(s * 100).toFixed(1);
|
l = (cmax + cmin) / 2;
|
||||||
l = +(l * 100).toFixed(1);
|
|
||||||
|
// Calculate saturation
|
||||||
return [h, s, l];
|
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
||||||
}
|
|
||||||
|
// Multiply l and s by 100
|
||||||
function HSLToRGB(h, s, l) {
|
s = +(s * 100).toFixed(1);
|
||||||
// Must be fractions of 1
|
l = +(l * 100).toFixed(1);
|
||||||
s /= 100;
|
|
||||||
l /= 100;
|
return [h, s, l];
|
||||||
|
}
|
||||||
let c = (1 - Math.abs(2 * l - 1)) * s,
|
|
||||||
x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
|
function HSLToRGB(h, s, l) {
|
||||||
m = l - c / 2,
|
// Must be fractions of 1
|
||||||
r = 0,
|
s /= 100;
|
||||||
g = 0,
|
l /= 100;
|
||||||
b = 0;
|
|
||||||
|
let c = (1 - Math.abs(2 * l - 1)) * s,
|
||||||
if (0 <= h && h < 60) {
|
x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
|
||||||
r = c;
|
m = l - c / 2,
|
||||||
g = x;
|
r = 0,
|
||||||
b = 0;
|
g = 0,
|
||||||
} else if (60 <= h && h < 120) {
|
b = 0;
|
||||||
r = x;
|
|
||||||
g = c;
|
if (0 <= h && h < 60) {
|
||||||
b = 0;
|
r = c;
|
||||||
} else if (120 <= h && h < 180) {
|
g = x;
|
||||||
r = 0;
|
b = 0;
|
||||||
g = c;
|
} else if (60 <= h && h < 120) {
|
||||||
b = x;
|
r = x;
|
||||||
} else if (180 <= h && h < 240) {
|
g = c;
|
||||||
r = 0;
|
b = 0;
|
||||||
g = x;
|
} else if (120 <= h && h < 180) {
|
||||||
b = c;
|
r = 0;
|
||||||
} else if (240 <= h && h < 300) {
|
g = c;
|
||||||
r = x;
|
b = x;
|
||||||
g = 0;
|
} else if (180 <= h && h < 240) {
|
||||||
b = c;
|
r = 0;
|
||||||
} else if (300 <= h && h < 360) {
|
g = x;
|
||||||
r = c;
|
b = c;
|
||||||
g = 0;
|
} else if (240 <= h && h < 300) {
|
||||||
b = x;
|
r = x;
|
||||||
}
|
g = 0;
|
||||||
r = Math.round((r + m) * 255);
|
b = c;
|
||||||
g = Math.round((g + m) * 255);
|
} else if (300 <= h && h < 360) {
|
||||||
b = Math.round((b + m) * 255);
|
r = c;
|
||||||
|
g = 0;
|
||||||
return [r, g, b];
|
b = x;
|
||||||
}
|
}
|
||||||
|
r = Math.round((r + m) * 255);
|
||||||
async function run() {
|
g = Math.round((g + m) * 255);
|
||||||
console.log("Running");
|
b = Math.round((b + m) * 255);
|
||||||
|
|
||||||
const variants = {
|
return [r, g, b];
|
||||||
regular: "#25fff2",
|
}
|
||||||
color: "#eba458",
|
|
||||||
shape: "#8858eb",
|
async function run() {
|
||||||
conflict: "#ff3e3e",
|
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);
|
|
||||||
|
const lineCanvas = createCanvas(dimensions, dimensions);
|
||||||
context.strokeStyle = hexDarkenedColor;
|
const lineContext = lineCanvas.getContext("2d");
|
||||||
context.lineWidth = lowerLineSize;
|
lineContext.quality = "best";
|
||||||
context.lineCap = "square";
|
lineContext.clearRect(0, 0, dimensions, dimensions);
|
||||||
context.imageSmoothingEnabled = false;
|
lineContext.strokeStyle = hexDarkenedColor;
|
||||||
|
lineContext.lineWidth = lowerLineSize;
|
||||||
// Draw lower lines
|
lineContext.lineCap = "square";
|
||||||
partLines.forEach(([x1, y1, x2, y2]) => {
|
lineContext.imageSmoothingEnabled = false;
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(x1 * dimensions, y1 * dimensions);
|
// Draw lower lines
|
||||||
context.lineTo(x2 * dimensions, y2 * dimensions);
|
partLines.forEach(([x1, y1, x2, y2]) => {
|
||||||
context.stroke();
|
lineContext.beginPath();
|
||||||
});
|
lineContext.moveTo(x1 * dimensions, y1 * dimensions);
|
||||||
|
lineContext.lineTo(x2 * dimensions, y2 * dimensions);
|
||||||
context.strokeStyle = variantColor;
|
lineContext.stroke();
|
||||||
context.lineWidth = lineSize;
|
});
|
||||||
|
|
||||||
// Draw upper lines
|
context.globalAlpha = 0.4;
|
||||||
partLines.forEach(([x1, y1, x2, y2]) => {
|
context.drawImage(lineCanvas, 0, 0, dimensions, dimensions);
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(x1 * dimensions, y1 * dimensions);
|
context.globalAlpha = 1;
|
||||||
context.lineTo(x2 * dimensions, y2 * dimensions);
|
context.imageSmoothingEnabled = false;
|
||||||
context.stroke();
|
context.lineCap = "square";
|
||||||
});
|
context.strokeStyle = variantColor;
|
||||||
|
context.lineWidth = lineSize;
|
||||||
const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
|
|
||||||
const stream = canvas.createPNGStream();
|
// Draw upper lines
|
||||||
stream.pipe(out);
|
partLines.forEach(([x1, y1, x2, y2]) => {
|
||||||
promises.push(new Promise(resolve => stream.on("end", resolve)));
|
context.beginPath();
|
||||||
}
|
context.moveTo(x1 * dimensions, y1 * dimensions);
|
||||||
}
|
context.lineTo(x2 * dimensions, y2 * dimensions);
|
||||||
|
context.stroke();
|
||||||
console.log("Waiting for completion");
|
});
|
||||||
await Promise.all(promises);
|
|
||||||
|
const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
|
||||||
// Also wait a bit more
|
const stream = canvas.createPNGStream();
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
stream.pipe(out);
|
||||||
|
promises.push(new Promise(resolve => stream.on("end", resolve)));
|
||||||
console.log("Copying files to all locations");
|
}
|
||||||
|
}
|
||||||
// // Copy other files
|
|
||||||
fs.copyFileSync(
|
console.log("Waiting for completion");
|
||||||
path.join(outputFolder, "regular_forward.png"),
|
await Promise.all(promises);
|
||||||
path.join(__dirname, "..", "buildings", "wire.png")
|
|
||||||
);
|
console.log("Done!");
|
||||||
fs.copyFileSync(
|
}
|
||||||
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 |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 25 KiB |
BIN
res_raw/sprites/blueprints/transistor-mirrored.png
Normal file
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 |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
BIN
res_raw/sprites/buildings/transistor-mirrored.png
Normal file
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 |
BIN
res_raw/sprites/wires/sets/first_cross.png
Normal file
After Width: | Height: | Size: 707 B |
BIN
res_raw/sprites/wires/sets/first_forward.png
Normal file
After Width: | Height: | Size: 649 B |
BIN
res_raw/sprites/wires/sets/first_split.png
Normal file
After Width: | Height: | Size: 526 B |
BIN
res_raw/sprites/wires/sets/first_turn.png
Normal file
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 |
BIN
res_raw/sprites/wires/sets/second_cross.png
Normal file
After Width: | Height: | Size: 706 B |
BIN
res_raw/sprites/wires/sets/second_forward.png
Normal file
After Width: | Height: | Size: 651 B |
BIN
res_raw/sprites/wires/sets/second_split.png
Normal file
After Width: | Height: | Size: 527 B |
BIN
res_raw/sprites/wires/sets/second_turn.png
Normal file
After Width: | Height: | Size: 515 B |
Before Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 648 B |
Before Width: | Height: | Size: 501 B |
Before Width: | Height: | Size: 500 B |
@ -1,5 +1,6 @@
|
|||||||
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
|
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
|
||||||
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage, portable_hub;
|
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
|
||||||
|
transistor, analyzer, comparator, portable_hub;
|
||||||
|
|
||||||
@each $building in $buildings {
|
@each $building in $buildings {
|
||||||
[data-icon="building_icons/#{$building}.png"] {
|
[data-icon="building_icons/#{$building}.png"] {
|
||||||
@ -8,10 +9,12 @@ $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, tra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, underground_belt,
|
$buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2, miner, miner-chainable,
|
||||||
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer,
|
cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
|
||||||
painter, painter-double, painter-quad, trash, storage, reader, rotater-rotate180, lever, display,
|
reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
|
||||||
constant_signal, portable_hub;
|
logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker,
|
||||||
|
virtual_processor-stacker, virtual_processor-painter, wire-second, painter, painter-mirrored, portable_hub;
|
||||||
|
|
||||||
@each $building in $buildingsAndVariants {
|
@each $building in $buildingsAndVariants {
|
||||||
[data-icon="building_tutorials/#{$building}.png"] {
|
[data-icon="building_tutorials/#{$building}.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
@ -19,26 +22,43 @@ $buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, under
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: New buildings (balancer, wires, etc)
|
[data-icon="building_tutorials/balancer-merger.png"],
|
||||||
|
|
||||||
// Special cases for mirrored vairants
|
|
||||||
[data-icon="building_tutorials/painter-mirrored.png"] {
|
|
||||||
/* @load-async */
|
|
||||||
background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
|
|
||||||
}
|
|
||||||
[data-icon="building_tutorials/balancer-merger-inverse.png"] {
|
[data-icon="building_tutorials/balancer-merger-inverse.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-icon="building_tutorials/balancer-splitter.png"],
|
||||||
[data-icon="building_tutorials/balancer-splitter-inverse.png"] {
|
[data-icon="building_tutorials/balancer-splitter-inverse.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important;
|
||||||
}
|
}
|
||||||
[data-icon="building_tutorials/filter.png"] {
|
|
||||||
|
[data-icon="building_tutorials/transistor.png"],
|
||||||
|
[data-icon="building_tutorials/transistor-mirrored.png"] {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/building_tutorials/transistor.png") !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter and lever share tutorials
|
||||||
|
[data-icon="building_tutorials/filter.png"],
|
||||||
|
[data-icon="building_tutorials/lever.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
background-image: uiResource("res/ui/building_tutorials/lever.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/lever.png") !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logic gate
|
||||||
|
[data-icon="building_tutorials/logic_gate.png"] {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/building_tutorials/logic_gate-and.png") !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtual processor
|
||||||
|
[data-icon="building_tutorials/virtual_processor.png"] {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/building_tutorials/virtual_processor-cutter.png") !important;
|
||||||
|
}
|
||||||
|
|
||||||
$icons: notification_saved, notification_success, notification_upgrade;
|
$icons: notification_saved, notification_success, notification_upgrade;
|
||||||
@each $icon in $icons {
|
@each $icon in $icons {
|
||||||
[data-icon="icons/#{$icon}.png"] {
|
[data-icon="icons/#{$icon}.png"] {
|
||||||
|
@ -65,7 +65,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
buildingSpeeds: {
|
buildingSpeeds: {
|
||||||
cutter: 1 / 4,
|
cutter: 1 / 4,
|
||||||
cutterQuad: 1 / 3,
|
cutterQuad: 1 / 4,
|
||||||
rotater: 1 / 1,
|
rotater: 1 / 1,
|
||||||
rotaterCCW: 1 / 1,
|
rotaterCCW: 1 / 1,
|
||||||
rotater180: 1 / 1,
|
rotater180: 1 / 1,
|
||||||
@ -73,7 +73,7 @@ export const globalConfig = {
|
|||||||
painterDouble: 1 / 8,
|
painterDouble: 1 / 8,
|
||||||
painterQuad: 1 / 2,
|
painterQuad: 1 / 2,
|
||||||
mixer: 1 / 5,
|
mixer: 1 / 5,
|
||||||
stacker: 1 / 6,
|
stacker: 1 / 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Zooming
|
// Zooming
|
||||||
|
@ -26,9 +26,6 @@ export default {
|
|||||||
// Allow to zoom freely without limits
|
// Allow to zoom freely without limits
|
||||||
// disableZoomLimits: true,
|
// disableZoomLimits: true,
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// Shows a border arround every chunk
|
|
||||||
// showChunkBorders: true,
|
|
||||||
// -----------------------------------------------------------------------------------
|
|
||||||
// All rewards can be unlocked by passing just 1 of any shape
|
// All rewards can be unlocked by passing just 1 of any shape
|
||||||
// rewardsInstant: true,
|
// rewardsInstant: true,
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
@ -110,5 +107,8 @@ export default {
|
|||||||
// Allows manual ticking
|
// Allows manual ticking
|
||||||
// manualTickOnly: true,
|
// manualTickOnly: true,
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
|
// Disables slow asserts, useful for debugging performance
|
||||||
|
// disableSlowAsserts: true,
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
/* dev:end */
|
/* dev:end */
|
||||||
};
|
};
|
||||||
|
79
src/js/game/buildings/analyzer.js
Normal file
@ -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,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
72
src/js/game/buildings/comparator.js
Normal file
@ -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,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,10 @@ import { Entity } from "../entity";
|
|||||||
import { MetaBuilding } from "../meta_building";
|
import { MetaBuilding } from "../meta_building";
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
import { ConstantSignalComponent } from "../components/constant_signal";
|
import { ConstantSignalComponent } from "../components/constant_signal";
|
||||||
|
import { generateMatrixRotations } from "../../core/utils";
|
||||||
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
|
|
||||||
|
const overlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]);
|
||||||
|
|
||||||
export class MetaConstantSignalBuilding extends MetaBuilding {
|
export class MetaConstantSignalBuilding extends MetaBuilding {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -11,15 +15,14 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSilhouetteColor() {
|
getSilhouetteColor() {
|
||||||
return "#2bafda";
|
return "#2b84fd";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
*/
|
*/
|
||||||
getIsUnlocked(root) {
|
getIsUnlocked(root) {
|
||||||
// @todo
|
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_constant_signal);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {"wires"} **/
|
/** @returns {"wires"} **/
|
||||||
@ -35,6 +38,10 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSpecialOverlayRenderMatrix(rotation) {
|
||||||
|
return overlayMatrix[rotation];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the entity at the given location
|
* Creates the entity at the given location
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
|