Improve wire auto-connect

This commit is contained in:
tobspr 2020-08-12 20:11:24 +02:00
parent f16ab2389a
commit f65b3728ed
34 changed files with 1051 additions and 804 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1001 KiB

After

Width:  |  Height:  |  Size: 1003 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 205 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 KiB

After

Width:  |  Height:  |  Size: 492 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 945 KiB

After

Width:  |  Height:  |  Size: 956 KiB

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e6959df75e915fb1a8d55e3d0ab750349b27276788ded63178f2a117c2edcf5
size 79441572

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -12,7 +12,7 @@ export const CHANGELOG = [
"Fix rare crash regarding the buildings toolbar (by isaisstillalive)",
"Fixed some phrases (by EnderDoom77)",
"Zoom towards mouse cursor (by Dimava)",
"Updated the soundtrack again, it is now 20 minutes in total!",
"Updated the soundtrack again, it is now 40 minutes in total!",
"Updated and added new translations (Thanks to all contributors!)",
"Allow editing waypoints (by isaisstillalive)",
"Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)",

View File

@ -1,35 +1,24 @@
import { Loader } from "../../core/loader";
import { rotateDirectionalObject } from "../../core/utils";
import { Vector } from "../../core/vector";
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector";
import { SOUNDS } from "../../platform/sound";
import { enumWireType, WireComponent } from "../components/wire";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { enumLayer, GameRoot } from "../root";
export const arrayWireRotationVariantToType = [enumWireType.regular, enumWireType.turn, enumWireType.split];
export const arrayWireRotationVariantToType = [
enumWireType.regular,
enumWireType.turn,
enumWireType.split,
enumWireType.cross,
];
export const wireOverlayMatrices = {
[enumWireType.regular]: {
0: [0, 1, 0, 0, 1, 0, 0, 1, 0],
90: [0, 0, 0, 1, 1, 1, 0, 0, 0],
180: [0, 1, 0, 0, 1, 0, 0, 1, 0],
270: [0, 0, 0, 1, 1, 1, 0, 0, 0],
},
[enumWireType.split]: {
0: [0, 0, 0, 1, 1, 1, 0, 1, 0],
90: [0, 1, 0, 1, 1, 0, 0, 1, 0],
180: [0, 1, 0, 1, 1, 1, 0, 0, 0],
270: [0, 1, 0, 0, 1, 1, 0, 1, 0],
},
[enumWireType.turn]: {
0: [0, 0, 0, 0, 1, 1, 0, 1, 0],
90: [0, 0, 0, 1, 1, 0, 0, 1, 0],
180: [0, 1, 0, 1, 1, 0, 0, 0, 0],
270: [0, 1, 0, 0, 1, 1, 0, 0, 0],
},
[enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
};
export class MetaWireBuilding extends MetaBuilding {
@ -121,8 +110,11 @@ export class MetaWireBuilding extends MetaBuilding {
case enumWireType.split: {
return Loader.getSprite("sprites/buildings/wire-split.png");
}
case enumWireType.cross: {
return Loader.getSprite("sprites/buildings/wire-cross.png");
}
default: {
assertAlways(false, "Invalid belt rotation variant");
assertAlways(false, "Invalid wire rotation variant");
}
}
}
@ -138,8 +130,11 @@ export class MetaWireBuilding extends MetaBuilding {
case enumWireType.split: {
return Loader.getSprite("sprites/blueprints/wire-split.png");
}
case enumWireType.cross: {
return Loader.getSprite("sprites/blueprints/wire-cross.png");
}
default: {
assertAlways(false, "Invalid belt rotation variant");
assertAlways(false, "Invalid wire rotation variant");
}
}
}
@ -155,21 +150,24 @@ export class MetaWireBuilding extends MetaBuilding {
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
*/
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
const connections = root.logic.getLocalWireConnectionsAtTile(tile);
const d = rotateDirectionalObject(connections, rotation);
// "Sticky" bottom
connections.bottom = true;
const connections = {
top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }),
right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }),
bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }),
left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }),
};
let flag = 0;
flag |= d.top ? 0x1000 : 0;
flag |= d.right ? 0x100 : 0;
flag |= d.bottom ? 0x10 : 0;
flag |= d.left ? 0x1 : 0;
flag |= connections.top ? 0x1000 : 0;
flag |= connections.right ? 0x100 : 0;
flag |= connections.bottom ? 0x10 : 0;
flag |= connections.left ? 0x1 : 0;
let targetType = enumWireType.regular;
// First, reset rotation
rotation = 0;
switch (flag) {
case 0x0000:
// Nothing
@ -177,12 +175,12 @@ export class MetaWireBuilding extends MetaBuilding {
case 0x0001:
// Left
targetType = enumWireType.turn;
rotation += 90;
break;
case 0x0010:
// Bottom
// END
break;
case 0x0011:
@ -193,12 +191,11 @@ export class MetaWireBuilding extends MetaBuilding {
case 0x0100:
// Right
targetType = enumWireType.turn;
rotation += 90;
break;
case 0x0101:
// Right | Left
// @todo: Might want to do rotation += 90 here
rotation += 90;
break;
@ -252,7 +249,7 @@ export class MetaWireBuilding extends MetaBuilding {
case 0x1111:
// Top | Right | Bottom | Left
// @todo: Crossing
targetType = enumWireType.cross;
break;
}

View File

@ -4,9 +4,8 @@ import { Rectangle } from "../../core/rectangle";
import { AtlasSprite } from "../../core/sprites";
import { enumDirection, Vector } from "../../core/vector";
import { types } from "../../savegame/serialization";
import { Component } from "../component";
import { getBuildingDataFromCode } from "../building_codes";
import { MetaBuilding } from "../meta_building";
import { Component } from "../component";
export class StaticMapEntityComponent extends Component {
static getId() {
@ -58,7 +57,7 @@ export class StaticMapEntityComponent extends Component {
/**
* Returns the meta building
* @returns {MetaBuilding}
* @returns {import("../meta_building").MetaBuilding}
*/
getMetaBuilding() {
return getBuildingDataFromCode(this.code).metaInstance;

View File

@ -5,6 +5,7 @@ export const enumWireType = {
regular: "regular",
turn: "turn",
split: "split",
cross: "cross",
};
export class WireComponent extends Component {
@ -30,31 +31,38 @@ export class WireComponent extends Component {
* @returns {import("../../core/utils").DirectionalObject}
*/
getLocalConnections() {
switch (this.type) {
case enumWireType.regular:
return {
top: true,
right: false,
bottom: true,
left: false,
};
case enumWireType.turn:
return {
top: false,
right: true,
bottom: true,
left: false,
};
case enumWireType.split:
return {
top: false,
right: true,
bottom: true,
left: true,
};
return {
top: true,
right: false,
bottom: true,
left: false,
};
default:
assertAlways(false, "Invalid wire type: " + this.type);
}
// switch (this.type) {
// case enumWireType.regular:
// return {
// top: true,
// right: false,
// bottom: true,
// left: false,
// };
// case enumWireType.turn:
// return {
// top: false,
// right: true,
// bottom: true,
// left: false,
// };
// case enumWireType.split:
// return {
// top: false,
// right: true,
// bottom: true,
// left: true,
// };
// default:
// assertAlways(false, "Invalid wire type: " + this.type);
// }
}
}

View File

@ -1,6 +1,6 @@
import { enumDirection, Vector } from "../../core/vector";
import { BaseItem } from "../base_item";
import { Component } from "../component";
import { Vector, enumDirection } from "../../core/vector";
import { types } from "../../savegame/serialization";
/** @enum {string} */
export const enumPinSlotType = {
@ -17,7 +17,8 @@ export const enumPinSlotType = {
/** @typedef {{
* pos: Vector,
* type: enumPinSlotType,
* direction: enumDirection
* direction: enumDirection,
* value: BaseItem
* }} WirePinSlot */
export class WiredPinsComponent extends Component {
@ -63,6 +64,7 @@ export class WiredPinsComponent extends Component {
pos: slotData.pos,
type: slotData.type,
direction: slotData.direction,
value: null,
});
}
}

View File

@ -1,6 +1,12 @@
import { createLogger } from "../core/logging";
import { round2Digits, rotateDirectionalObject } from "../core/utils";
import { enumDirection, enumDirectionToVector, Vector } from "../core/vector";
import {
enumDirection,
enumDirectionToVector,
Vector,
enumDirectionToAngle,
enumInvertedDirections,
} from "../core/vector";
import { Entity } from "./entity";
import { MetaBuilding } from "./meta_building";
import { GameRoot, enumLayer } from "./root";
@ -8,6 +14,13 @@ import { STOP_PROPAGATION } from "../core/signal";
const logger = createLogger("ingame/logic");
/** @enum {number} */
export const enumWireEdgeFlag = {
empty: 0,
filled: 1,
connected: 2,
};
/**
* Typing helper
* @typedef {Array<{
@ -214,11 +227,111 @@ export class GameLogic {
const wiresComp = contents.components.Wire;
if (wiresComp) {
const connections = wiresComp.getLocalConnections();
return rotateDirectionalObject(connections, staticComp.rotation);
return rotateDirectionalObject(connections, staticComp.originalRotation);
}
return result;
}
/**
*
* Computes the flag for a given tile
* @param {object} param0
* @param {Vector} param0.tile The tile to check at
* @param {enumDirection} param0.edge The edge to check for
* @param {number} param0.rotation The local tiles base rotation
*/
computeWireEdgeStatus({ tile, edge, rotation }) {
const offset = enumDirectionToVector[edge];
const refTile = tile.add(offset);
const angle = enumDirectionToAngle[edge];
// // First, check if this edge can be connected from locally
// const canConnectLocally = rotation === angle || (rotation + 180) % 360 === angle;
const neighbourStatus = this.getWireEdgeFlag(refTile, edge);
if (neighbourStatus === enumWireEdgeFlag.empty) {
// It's empty, no point in connecting
return false;
}
if (neighbourStatus === enumWireEdgeFlag.filled) {
return true;
}
if (neighbourStatus === enumWireEdgeFlag.connected) {
return true;
}
}
/**
* Gets the flag at the given tile
* @param {Vector} tile
* @param {enumDirection} edge
* @returns {enumWireEdgeFlag}
*/
getWireEdgeFlag(tile, edge) {
// Search for relevant pins
const pinEntities = this.root.map.getLayersContentsMultipleXY(tile.x, tile.y);
// Go over all entities which could have a pin
for (let i = 0; i < pinEntities.length; ++i) {
const pinEntity = pinEntities[i];
const pinComp = pinEntity.components.WiredPins;
const staticComp = pinEntity.components.StaticMapEntity;
// Skip those who don't have pins
if (!pinComp) {
continue;
}
// Go over all pins
const pins = pinComp.slots;
for (let k = 0; k < pinComp.slots.length; ++k) {
const pinSlot = pins[k];
const pinLocation = staticComp.localTileToWorld(pinSlot.pos);
// Check if the pin has the right location
if (!pinLocation.equals(tile)) {
continue;
}
// Check if the pin has the right direction
if (pinSlot.direction !== enumInvertedDirections[edge]) {
continue;
}
// Found a pin!
return enumWireEdgeFlag.connected;
}
}
// Now check if there's a connectable wire
const targetEntity = this.root.map.getTileContent(tile, enumLayer.wires);
if (!targetEntity) {
return enumWireEdgeFlag.empty;
}
// Check if its a wire
const wiresComp = targetEntity.components.Wire;
if (!wiresComp) {
return enumWireEdgeFlag.empty;
}
const refAngle = enumDirectionToAngle[edge];
const refRotation = targetEntity.components.StaticMapEntity.originalRotation;
const canConnectRemotely = refRotation === refAngle || (refRotation + 180) % 360 === refAngle;
// Check if the wire points towards the right direction
if (!canConnectRemotely) {
// Seems its not the right direction - well, still its filled
return enumWireEdgeFlag.filled;
}
// Actually connected
return enumWireEdgeFlag.connected;
}
/**
* Returns the acceptors and ejectors which affect the current tile
* @param {Vector} tile

View File

@ -84,6 +84,7 @@ export function initMetaBuildingRegistry() {
registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0);
registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1);
registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2);
registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3);
// Propagate instances
for (const key in gBuildingVariants) {

View File

@ -5,6 +5,7 @@ import { Entity } from "../entity";
import { formatBigNumber } from "../../core/utils";
import { Loader } from "../../core/loader";
import { T } from "../../translations";
import { ShapeItem } from "../items/shape_item";
export class HubSystem extends GameSystemWithFilter {
constructor(root) {
@ -17,7 +18,14 @@ export class HubSystem extends GameSystemWithFilter {
this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this));
}
update() {}
update() {
for (let i = 0; i < this.allEntities.length; ++i) {
// Set hub goal
const entity = this.allEntities[i];
const pinsComp = entity.components.WiredPins;
pinsComp.slots[0].value = new ShapeItem(this.root.hubGoals.currentGoal.definition);
}
}
/**
* @param {DrawParameters} parameters

View File

@ -17,6 +17,7 @@ export class WireSystem extends GameSystemWithFilter {
[enumWireType.regular]: Loader.getSprite("sprites/buildings/wire.png"),
[enumWireType.turn]: Loader.getSprite("sprites/buildings/wire-turn.png"),
[enumWireType.split]: Loader.getSprite("sprites/buildings/wire-split.png"),
[enumWireType.cross]: Loader.getSprite("sprites/buildings/wire-cross.png"),
};
this.root.signals.entityDestroyed.add(this.updateSurroundingWirePlacement, this);
@ -36,7 +37,36 @@ export class WireSystem extends GameSystemWithFilter {
if (entity && entity.components.Wire) {
const wireType = entity.components.Wire.type;
const sprite = this.wireSprites[wireType];
entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds(parameters, sprite, 0);
assert(sprite, "Unknown wire type: " + wireType);
const staticComp = entity.components.StaticMapEntity;
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0);
if (G_IS_DEV && globalConfig.debug.renderWireRotations) {
parameters.context.fillStyle = "red";
parameters.context.font = "5px Tahoma";
parameters.context.fillText(
"" + staticComp.originalRotation,
staticComp.origin.x * globalConfig.tileSize,
staticComp.origin.y * globalConfig.tileSize + 5
);
parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)";
if (staticComp.originalRotation % 180 === 0) {
parameters.context.fillRect(
(staticComp.origin.x + 0.5) * globalConfig.tileSize,
staticComp.origin.y * globalConfig.tileSize,
3,
globalConfig.tileSize
);
} else {
parameters.context.fillRect(
staticComp.origin.x * globalConfig.tileSize,
(staticComp.origin.y + 0.5) * globalConfig.tileSize,
globalConfig.tileSize,
3
);
}
}
}
}
}

View File

@ -179,6 +179,12 @@ export class WiredPinsSystem extends GameSystemWithFilter {
offsetX: 0,
offsetY: 0,
});
// Draw contained item to visualize whats emitted
const value = slot.value;
if (value) {
value.draw(worldPos.x, worldPos.y, parameters, 12);
}
}
}
}

View File

@ -28,7 +28,7 @@ export const SOUNDS = {
};
export const MUSIC = {
theme: "theme",
theme: G_IS_STANDALONE ? "theme-full" : "theme-short",
menu: "menu",
};