1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

Start to rework the graphics for the wires layer, make wires cooler than belts

This commit is contained in:
tobspr
2020-06-30 12:38:20 +02:00
parent 18fb9cb04f
commit 722c8ef836
35 changed files with 684 additions and 606 deletions

View File

@@ -51,9 +51,15 @@ export const globalConfig = {
// Belt speeds
// NOTICE: Update webpack.production.config too!
beltSpeedItemsPerSecond: 2,
itemSpacingOnBelts: 0.63,
minerSpeedItemsPerSecond: 0, // COMPUTED
beltItemSpacingByLayer: {
regular: 0.63,
wires: 0.33,
},
wiresSpeedItemsPerSecond: 6,
undergroundBeltMaxTilesByTier: [5, 8],
buildingSpeeds: {

View File

@@ -90,7 +90,7 @@ export class BeltPath extends BasicSerializableObject {
* @param {boolean} computeSpacing Whether to also compute the spacing
*/
init(computeSpacing = true) {
// Find acceptor and ejector
this.onPathChanged();
this.totalLength = this.computeTotalLength();
@@ -108,8 +108,6 @@ export class BeltPath extends BasicSerializableObject {
for (let i = 0; i < this.entityPath.length; ++i) {
this.entityPath[i].components.Belt.assignedPath = this;
}
this.onPathChanged();
}
/**
@@ -117,7 +115,14 @@ export class BeltPath extends BasicSerializableObject {
* @returns {boolean}
*/
canAcceptItem() {
return this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts;
return this.spacingToFirstItem >= this.getItemSpacing();
}
/**
* Returns the spacing between items
*/
getItemSpacing() {
return globalConfig.beltItemSpacingByLayer[this.layer];
}
/**
@@ -133,15 +138,15 @@ export class BeltPath extends BasicSerializableObject {
* @param {BaseItem} item
*/
tryAcceptItem(item) {
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
if (this.spacingToFirstItem >= this.getItemSpacing()) {
// So, since we already need one tick to accept this item we will add this directly.
const beltProgressPerTick =
this.root.hubGoals.getBeltBaseSpeed() *
this.root.hubGoals.getBeltBaseSpeed(this.layer) *
this.root.dynamicTickrate.deltaSeconds *
globalConfig.itemSpacingOnBelts;
this.getItemSpacing();
// First, compute how much progress we can make *at max*
const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
const maxProgress = Math.max(0, this.spacingToFirstItem - this.getItemSpacing());
const initialProgress = Math.min(maxProgress, beltProgressPerTick);
this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
@@ -200,6 +205,8 @@ export class BeltPath extends BasicSerializableObject {
}
}
}
this.layer = this.entityPath[0].layer;
}
// Following code will be compiled out outside of dev versions
@@ -376,7 +383,7 @@ export class BeltPath extends BasicSerializableObject {
this.onPathChanged();
// Extend the path length
const additionalLength = beltComp.getEffectiveLengthTiles();
const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer);
this.totalLength += additionalLength;
DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength);
@@ -419,7 +426,7 @@ export class BeltPath extends BasicSerializableObject {
// All items on that belt are simply lost (for now)
const length = beltComp.getEffectiveLengthTiles();
const length = beltComp.getEffectiveLengthTiles(entity.layer);
// Extend the length of this path
this.totalLength += length;
@@ -471,7 +478,7 @@ export class BeltPath extends BasicSerializableObject {
const beltComp = entity.components.Belt;
beltComp.assignedPath = null;
const entityLength = beltComp.getEffectiveLengthTiles();
const entityLength = beltComp.getEffectiveLengthTiles(entity.layer);
assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split");
assert(this.entityPath.indexOf(entity) !== 0, "Entity is first");
assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last");
@@ -489,7 +496,7 @@ export class BeltPath extends BasicSerializableObject {
++firstPathEntityCount;
firstPathEndEntity = otherEntity;
firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles();
firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(otherEntity.layer);
}
DEBUG &&
@@ -633,7 +640,7 @@ export class BeltPath extends BasicSerializableObject {
// Ok, first remove the entity
const beltComp = entity.components.Belt;
const beltLength = beltComp.getEffectiveLengthTiles();
const beltLength = beltComp.getEffectiveLengthTiles(entity.layer);
DEBUG &&
logger.log(
@@ -742,7 +749,7 @@ export class BeltPath extends BasicSerializableObject {
// Ok, first remove the entity
const beltComp = entity.components.Belt;
const beltLength = beltComp.getEffectiveLengthTiles();
const beltLength = beltComp.getEffectiveLengthTiles(entity.layer);
DEBUG &&
logger.log(
@@ -882,7 +889,7 @@ export class BeltPath extends BasicSerializableObject {
beltComp.assignedPath = this;
// Update our length
const additionalLength = beltComp.getEffectiveLengthTiles();
const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer);
this.totalLength += additionalLength;
}
@@ -939,7 +946,8 @@ export class BeltPath extends BasicSerializableObject {
computeTotalLength() {
let length = 0;
for (let i = 0; i < this.entityPath.length; ++i) {
length += this.entityPath[i].components.Belt.getEffectiveLengthTiles();
const entity = this.entityPath[i];
length += entity.components.Belt.getEffectiveLengthTiles(this.layer);
}
return length;
}
@@ -954,15 +962,15 @@ export class BeltPath extends BasicSerializableObject {
// Divide by item spacing on belts since we use throughput and not speed
let beltSpeed =
this.root.hubGoals.getBeltBaseSpeed() *
this.root.hubGoals.getBeltBaseSpeed(this.layer) *
this.root.dynamicTickrate.deltaSeconds *
globalConfig.itemSpacingOnBelts;
this.getItemSpacing();
if (G_IS_DEV && globalConfig.debug.instantBelts) {
beltSpeed *= 100;
}
let minimumDistance = this.ejectorSlot.item ? globalConfig.itemSpacingOnBelts : 0;
let minimumDistance = this.ejectorSlot.item ? this.getItemSpacing() : 0;
// Try to reduce spacing
let remainingAmount = beltSpeed;
@@ -983,7 +991,7 @@ export class BeltPath extends BasicSerializableObject {
break;
}
minimumDistance = globalConfig.itemSpacingOnBelts;
minimumDistance = this.getItemSpacing();
}
const lastItem = this.items[this.items.length - 1];
@@ -1012,14 +1020,14 @@ export class BeltPath extends BasicSerializableObject {
for (let i = 0; i < this.entityPath.length; ++i) {
const beltComp = this.entityPath[i].components.Belt;
const localLength = beltComp.getEffectiveLengthTiles();
const localLength = beltComp.getEffectiveLengthTiles(this.layer);
if (currentLength + localLength >= progress || i === this.entityPath.length - 1) {
// Min required here due to floating point issues
const localProgress = Math.min(1.0, progress - currentLength);
assert(localProgress >= 0.0, "Invalid local progress: " + localProgress);
const localSpace = beltComp.transformBeltToLocalSpace(localProgress);
const localSpace = beltComp.transformBeltToLocalSpace(localProgress, this.layer);
return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace);
}
currentLength += localLength;
@@ -1123,13 +1131,18 @@ export class BeltPath extends BasicSerializableObject {
for (let i = 0; i < this.entityPath.length; ++i) {
const entity = this.entityPath[i];
const beltComp = entity.components.Belt;
const beltLength = beltComp.getEffectiveLengthTiles();
const beltLength = beltComp.getEffectiveLengthTiles(this.layer);
// Check if the item is on the current belt
if (trackPos + beltLength >= currentItemPos) {
// Check if the current items are on the belt
while (trackPos + beltLength >= currentItemPos) {
// Its on the belt, render it now
const staticComp = entity.components.StaticMapEntity;
const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos);
assert(
currentItemPos - trackPos >= 0,
"invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")"
);
const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos, this.layer);
const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile();
const distanceAndItem = this.items[currentItemIndex];
@@ -1143,7 +1156,7 @@ export class BeltPath extends BasicSerializableObject {
if (currentItemIndex >= this.items.length) {
// We rendered all items
break;
return;
}
}

View File

@@ -24,7 +24,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
* @returns {Array<[string, string]>}
*/
getAdditionalStatistics(root, variant) {
const beltSpeed = root.hubGoals.getBeltBaseSpeed();
const beltSpeed = root.hubGoals.getBeltBaseSpeed(enumLayer.regular);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
}

View File

@@ -3,6 +3,7 @@ import { types } from "../../savegame/serialization";
import { BeltPath } from "../belt_path";
import { Component } from "../component";
import { Entity } from "../entity";
import { enumLayer } from "../root";
export const curvedBeltLength = /* Math.PI / 4 */ 0.78;
@@ -44,9 +45,14 @@ export class BeltComponent extends Component {
/**
* Returns the effective length of this belt in tile space
* @param {enumLayer} layer
* @returns {number}
*/
getEffectiveLengthTiles() {
getEffectiveLengthTiles(layer) {
assert(layer, "no layer given");
if (layer === enumLayer.wires) {
return 1.0;
}
return this.direction === enumDirection.top ? 1.0 : curvedBeltLength;
}
@@ -54,27 +60,62 @@ export class BeltComponent extends Component {
* Converts from belt space (0 = start of belt ... 1 = end of belt) to the local
* belt coordinates (-0.5|-0.5 to 0.5|0.5)
* @param {number} progress
* @param {enumLayer} layer
* @returns {Vector}
*/
transformBeltToLocalSpace(progress) {
switch (this.direction) {
case enumDirection.top:
assert(progress <= 1.02, "Invalid progress: " + progress);
return new Vector(0, 0.5 - progress);
transformBeltToLocalSpace(progress, layer) {
assert(progress >= 0.0, "Invalid progress ( < 0): " + progress);
case enumDirection.right: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress);
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
switch (layer) {
case enumLayer.regular: {
switch (this.direction) {
case enumDirection.top:
assert(progress <= 1.02, "Invalid progress: " + progress);
return new Vector(0, 0.5 - progress);
case enumDirection.right: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress);
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(
0.5 - 0.5 * Math.cos(arcProgress),
0.5 - 0.5 * Math.sin(arcProgress)
);
}
case enumDirection.left: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress);
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(
-0.5 + 0.5 * Math.cos(arcProgress),
0.5 - 0.5 * Math.sin(arcProgress)
);
}
default:
assertAlways(false, "Invalid belt direction: " + this.direction);
return new Vector(0, 0);
}
}
case enumDirection.left: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress);
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
case enumLayer.wires: {
const pow = 0.5;
switch (this.direction) {
case enumDirection.top:
assert(progress <= 1.02, "Invalid progress: " + progress);
return new Vector(0, 0.5 - progress);
case enumDirection.right: {
assert(progress <= 1.02, "Invalid progress 2: " + progress);
return progress > 0.5 ? new Vector(progress - 0.5, 0) : new Vector(0, 0.5 - progress);
}
case enumDirection.left: {
assert(progress <= 1.02, "Invalid progress 3: " + progress);
return progress > 0.5
? new Vector(-progress + 0.5, 0)
: new Vector(0, 0.5 - progress);
}
default:
assertAlways(false, "Invalid belt direction: " + this.direction);
return new Vector(0, 0);
}
}
default:
assertAlways(false, "Invalid belt direction: " + this.direction);
return new Vector(0, 0);
}
}
}

View File

@@ -3,7 +3,7 @@ import { BaseItem } from "../base_item";
import { Component } from "../component";
import { ShapeItem } from "../items/shape_item";
const maxQueueSize = 4;
const maxQueueSize = 20;
export const ENERGY_GENERATOR_EJECT_SLOT = 0;
export const ENERGY_GENERATOR_ACCEPT_SLOT = 4;

View File

@@ -4,6 +4,7 @@ import { globalConfig } from "../../core/config";
import { types } from "../../savegame/serialization";
import { gItemRegistry } from "../../core/global_registries";
import { Entity } from "../entity";
import { enumLayer } from "../root";
/** @enum {string} */
export const enumUndergroundBeltMode = {
@@ -102,7 +103,8 @@ export class UndergroundBeltComponent extends Component {
}
// Notice: We assume that for all items the travel distance is the same
const maxItemsInTunnel = (2 + travelDistance) / globalConfig.itemSpacingOnBelts;
const maxItemsInTunnel =
(2 + travelDistance) / globalConfig.beltItemSpacingByLayer[enumLayer.regular];
if (this.pendingItems.length >= maxItemsInTunnel) {
// Simulate a real belt which gets full at some point
return false;
@@ -112,7 +114,8 @@ export class UndergroundBeltComponent extends Component {
// This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item.
// So instead of adding 1 we add 0.5 only.
// Additionally it takes 1 tile for the acceptor which we just add on top.
const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts;
const travelDuration =
(travelDistance + 1.5) / beltSpeed / globalConfig.beltItemSpacingByLayer[enumLayer.regular];
this.pendingItems.push([item, travelDuration]);

View File

@@ -4,7 +4,7 @@ import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/ut
import { BasicSerializableObject, types } from "../savegame/serialization";
import { enumColors } from "./colors";
import { enumItemProcessorTypes } from "./components/item_processor";
import { GameRoot } from "./root";
import { GameRoot, enumLayer } from "./root";
import { enumSubShape, ShapeDefinition } from "./shape_definition";
import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals";
import { UPGRADES, blueprintShape } from "./upgrades";
@@ -370,9 +370,13 @@ export class HubGoals extends BasicSerializableObject {
/**
* Belt speed
* @param {enumLayer} layer
* @returns {number} items / sec
*/
getBeltBaseSpeed() {
getBeltBaseSpeed(layer) {
if (layer === enumLayer.wires) {
return globalConfig.wiresSpeedItemsPerSecond;
}
return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt;
}

View File

@@ -1,4 +1,4 @@
import { GameRoot } from "../root";
import { GameRoot, enumLayer } from "../root";
import { globalConfig } from "../../core/config";
import { Vector, mixVector } from "../../core/vector";
import { lerp } from "../../core/utils";
@@ -92,7 +92,7 @@ export class TrailerMaker {
const speed =
globalConfig.tileSize *
globalConfig.beltSpeedItemsPerSecond *
globalConfig.itemSpacingOnBelts;
globalConfig.beltItemSpacingByLayer[enumLayer.regular];
// let time =
// this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed;
const time = nextMarker.time;

View File

@@ -312,7 +312,7 @@ export class BeltSystem extends GameSystemWithFilter {
drawLayer(parameters, layer) {
for (let i = 0; i < this.beltPaths.length; ++i) {
const path = this.beltPaths[i];
if (path.getLayer() === layer) {
if (path.layer === layer) {
path.draw(parameters);
}
}
@@ -507,13 +507,13 @@ export class BeltSystem extends GameSystemWithFilter {
}
// Limit speed to avoid belts going backwards
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10);
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(enumLayer.regular), 10);
// SYNC with systems/item_acceptor.js:drawEntityUnderlays!
// 126 / 42 is the exact animation speed of the png animation
const animationIndex = Math.floor(
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
globalConfig.itemSpacingOnBelts
globalConfig.beltItemSpacingByLayer[enumLayer.regular]
);
const contents = chunk.contents;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
@@ -546,15 +546,6 @@ export class BeltSystem extends GameSystemWithFilter {
return;
}
// Limit speed to avoid belts going backwards
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10);
// SYNC with systems/item_acceptor.js:drawEntityUnderlays!
// 126 / 42 is the exact animation speed of the png animation
const animationIndex = Math.floor(
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
globalConfig.itemSpacingOnBelts
);
const contents = chunk.wireContents;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {

View File

@@ -22,11 +22,7 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
}
update() {
const progress =
this.root.dynamicTickrate.deltaSeconds *
this.root.hubGoals.getBeltBaseSpeed() *
2 * // * 2 because its only a half tile
globalConfig.itemSpacingOnBelts;
const progress = this.root.dynamicTickrate.deltaSeconds * 2; // * 2 because its only a half tile
for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i];
@@ -36,7 +32,11 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
// Process item consumption animations to avoid items popping from the belts
for (let animIndex = 0; animIndex < animations.length; ++animIndex) {
const anim = animations[animIndex];
anim.animProgress += progress;
const layer = aceptorComp.slots[anim.slotIndex].layer;
anim.animProgress +=
progress *
this.root.hubGoals.getBeltBaseSpeed(layer) *
globalConfig.beltItemSpacingByLayer[layer];
if (anim.animProgress > 1) {
// Original
// animations.splice(animIndex, 1);
@@ -120,7 +120,7 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
}
// Limit speed to avoid belts going backwards
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10);
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10);
const underlays = acceptorComp.beltUnderlays;
for (let i = 0; i < underlays.length; ++i) {
@@ -136,7 +136,7 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
// SYNC with systems/belt.js:drawSingleEntity!
const animationIndex = Math.floor(
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
globalConfig.itemSpacingOnBelts
globalConfig.beltItemSpacingByLayer[layer]
);
drawRotatedSprite({

View File

@@ -185,8 +185,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
}
// Precompute effective belt speed
const effectiveBeltSpeed = this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts;
let progressGrowth = (effectiveBeltSpeed / 0.5) * this.root.dynamicTickrate.deltaSeconds;
let progressGrowth = 2 * this.root.dynamicTickrate.deltaSeconds;
if (G_IS_DEV && globalConfig.debug.instantBelts) {
progressGrowth = 1;
@@ -217,7 +216,13 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
const targetEntity = sourceSlot.cachedTargetEntity;
// Advance items on the slot
sourceSlot.progress = Math.min(1, sourceSlot.progress + progressGrowth);
sourceSlot.progress = Math.min(
1,
sourceSlot.progress +
progressGrowth *
this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) *
globalConfig.beltItemSpacingByLayer[sourceSlot.layer]
);
// Check if we are still in the process of ejecting, can't proceed then
if (sourceSlot.progress < 1.0) {