1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Merge branch 'master' into master

This commit is contained in:
BaleineSanguine 2020-09-24 17:58:48 +02:00 committed by GitHub
commit 44ce264bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
128 changed files with 2425 additions and 2620 deletions

View File

@ -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/`.

View File

@ -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));

View File

@ -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,
};

View File

@ -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")));
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 279 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 KiB

After

Width:  |  Height:  |  Size: 700 KiB

View File

@ -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>

View File

@ -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();

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -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 + "")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 B

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

View File

@ -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"] {

View File

@ -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

View File

@ -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 */
}; };

View 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,
})
);
}
}

View 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,
})
);
}
}

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More