mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Multiple improvements
This commit is contained in:
parent
ce8640195a
commit
13c6fc7598
@ -1,5 +1,11 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const nodeVersion = process.versions.node.split(".")[0];
|
||||||
|
if (nodeVersion !== "10") {
|
||||||
|
console.error("This cli requires exactly Node 10. You are using node " + nodeVersion);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
require("colors");
|
require("colors");
|
||||||
|
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
|
@ -304,6 +304,24 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
|
<key type="filename">sprites/blueprints/cutter-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/painter-quad.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>192,48,384,96</rect>
|
||||||
|
<key>scale9Paddings</key>
|
||||||
|
<rect>192,48,384,96</rect>
|
||||||
|
<key>scale9FromFile</key>
|
||||||
|
<false/>
|
||||||
|
</struct>
|
||||||
<key type="filename">sprites/blueprints/cutter.png</key>
|
<key type="filename">sprites/blueprints/cutter.png</key>
|
||||||
<key type="filename">sprites/blueprints/mixer.png</key>
|
<key type="filename">sprites/blueprints/mixer.png</key>
|
||||||
<key type="filename">sprites/blueprints/painter.png</key>
|
<key type="filename">sprites/blueprints/painter.png</key>
|
||||||
@ -323,12 +341,22 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
|
<key type="filename">sprites/blueprints/miner-chainable.png</key>
|
||||||
<key type="filename">sprites/blueprints/miner.png</key>
|
<key type="filename">sprites/blueprints/miner.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
|
||||||
<key type="filename">sprites/blueprints/rotater.png</key>
|
<key type="filename">sprites/blueprints/rotater.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/splitter-compact.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.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.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
||||||
|
<key type="filename">sprites/buildings/miner-chainable.png</key>
|
||||||
|
<key type="filename">sprites/buildings/rotater-ccw.png</key>
|
||||||
|
<key type="filename">sprites/buildings/splitter-compact.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.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
||||||
<struct type="IndividualSpriteSettings">
|
<struct type="IndividualSpriteSettings">
|
||||||
<key>pivotPoint</key>
|
<key>pivotPoint</key>
|
||||||
@ -344,6 +372,22 @@
|
|||||||
<key>scale9FromFile</key>
|
<key>scale9FromFile</key>
|
||||||
<false/>
|
<false/>
|
||||||
</struct>
|
</struct>
|
||||||
|
<key type="filename">sprites/blueprints/painter-double.png</key>
|
||||||
|
<key type="filename">sprites/buildings/painter-double.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>96,96,192,192</rect>
|
||||||
|
<key>scale9Paddings</key>
|
||||||
|
<rect>96,96,192,192</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>
|
||||||
|
@ -3,20 +3,21 @@
|
|||||||
@include S(top, 50px);
|
@include S(top, 50px);
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
background: rgba(#f77, 0.8);
|
background: rgba(lighten(#f77, 5), 0.95);
|
||||||
@include S(border-radius, 4px);
|
@include S(border-radius, 2px);
|
||||||
@include S(padding, 9px);
|
@include S(padding, 6px, 10px);
|
||||||
@include PlainText;
|
@include SuperSmallText;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
// color: #f77;
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.keybinding {
|
.keybinding {
|
||||||
|
vertical-align: middle;
|
||||||
@include S(margin, 0, 4px);
|
@include S(margin, 0, 4px);
|
||||||
position: relative;
|
position: relative;
|
||||||
top: unset;
|
top: unset;
|
||||||
left: unset;
|
left: unset;
|
||||||
right: unset;
|
right: unset;
|
||||||
bottom: unset;
|
bottom: unset;
|
||||||
|
@include S(margin-top, -2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,8 @@ ingame_HUD_PinnedShapes,
|
|||||||
ingame_HUD_buildings_toolbar,
|
ingame_HUD_buildings_toolbar,
|
||||||
ingame_HUD_GameMenu,
|
ingame_HUD_GameMenu,
|
||||||
ingame_HUD_KeybindingOverlay,
|
ingame_HUD_KeybindingOverlay,
|
||||||
ingame_HUD_MassSelector,
|
|
||||||
ingame_HUD_Notifications,
|
ingame_HUD_Notifications,
|
||||||
|
ingame_HUD_MassSelector,
|
||||||
|
|
||||||
// Overlays
|
// Overlays
|
||||||
ingame_HUD_BetaOverlay,
|
ingame_HUD_BetaOverlay,
|
||||||
|
@ -38,7 +38,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
// Belt speeds
|
// Belt speeds
|
||||||
// NOTICE: Update webpack.production.config too!
|
// NOTICE: Update webpack.production.config too!
|
||||||
beltSpeedItemsPerSecond: 5,
|
beltSpeedItemsPerSecond: 1,
|
||||||
itemSpacingOnBelts: 0.63,
|
itemSpacingOnBelts: 0.63,
|
||||||
minerSpeedItemsPerSecond: 0, // COMPUTED
|
minerSpeedItemsPerSecond: 0, // COMPUTED
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
|||||||
directions: [enumDirection.bottom],
|
directions: [enumDirection.bottom],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
animated: false,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -44,6 +44,10 @@ export class MetaHubBuilding extends MetaBuilding {
|
|||||||
processorType: enumItemProcessorTypes.hub,
|
processorType: enumItemProcessorTypes.hub,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// We render the sprite ourself
|
||||||
|
entity.components.StaticMapEntity.spriteKey = null;
|
||||||
|
|
||||||
entity.addComponent(new UnremovableComponent());
|
entity.addComponent(new UnremovableComponent());
|
||||||
entity.addComponent(
|
entity.addComponent(
|
||||||
new ItemAcceptorComponent({
|
new ItemAcceptorComponent({
|
||||||
|
@ -112,7 +112,7 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
|||||||
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
entity.components.ItemProcessor.beltUnderlays = [
|
entity.components.ItemAcceptor.beltUnderlays = [
|
||||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||||
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
||||||
];
|
];
|
||||||
@ -135,7 +135,7 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
|||||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
entity.components.ItemProcessor.beltUnderlays = [
|
entity.components.ItemAcceptor.beltUnderlays = [
|
||||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -29,6 +29,15 @@ const velocityFade = 0.98;
|
|||||||
const velocityStrength = 0.4;
|
const velocityStrength = 0.4;
|
||||||
const velocityMax = 20;
|
const velocityMax = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
export const enumMouseButton = {
|
||||||
|
left: "left",
|
||||||
|
middle: "middle",
|
||||||
|
right: "right",
|
||||||
|
};
|
||||||
|
|
||||||
export class Camera extends BasicSerializableObject {
|
export class Camera extends BasicSerializableObject {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super();
|
super();
|
||||||
@ -81,10 +90,10 @@ export class Camera extends BasicSerializableObject {
|
|||||||
this.touchPostMoveVelocity = new Vector(0, 0);
|
this.touchPostMoveVelocity = new Vector(0, 0);
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
this.downPreHandler = new Signal(/* pos */);
|
this.downPreHandler = /** @type {TypedSignal<[Vector, enumMouseButton]>} */ (new Signal());
|
||||||
this.movePreHandler = new Signal(/* pos */);
|
this.movePreHandler = /** @type {TypedSignal<[Vector]>} */ (new Signal());
|
||||||
this.pinchPreHandler = new Signal(/* pos */);
|
// this.pinchPreHandler = /** @type {TypedSignal<[Vector]>} */ (new Signal());
|
||||||
this.upPostHandler = new Signal(/* pos */);
|
this.upPostHandler = /** @type {TypedSignal<[Vector]>} */ (new Signal());
|
||||||
|
|
||||||
this.internalInitEvents();
|
this.internalInitEvents();
|
||||||
this.clampZoomLevel();
|
this.clampZoomLevel();
|
||||||
@ -411,6 +420,10 @@ export class Camera extends BasicSerializableObject {
|
|||||||
this.touchPostMoveVelocity = new Vector(0, 0);
|
this.touchPostMoveVelocity = new Vector(0, 0);
|
||||||
if (event.which === 1) {
|
if (event.which === 1) {
|
||||||
this.combinedSingleTouchStartHandler(event.clientX, event.clientY);
|
this.combinedSingleTouchStartHandler(event.clientX, event.clientY);
|
||||||
|
} else if (event.which === 2) {
|
||||||
|
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.middle);
|
||||||
|
} else if (event.which === 3) {
|
||||||
|
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.right);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -496,10 +509,10 @@ export class Camera extends BasicSerializableObject {
|
|||||||
const touch = event.touches[0];
|
const touch = event.touches[0];
|
||||||
this.combinedSingleTouchStartHandler(touch.clientX, touch.clientY);
|
this.combinedSingleTouchStartHandler(touch.clientX, touch.clientY);
|
||||||
} else if (event.touches.length === 2) {
|
} else if (event.touches.length === 2) {
|
||||||
if (this.pinchPreHandler.dispatch() === STOP_PROPAGATION) {
|
// if (this.pinchPreHandler.dispatch() === STOP_PROPAGATION) {
|
||||||
// Something prevented pinching
|
// // Something prevented pinching
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const touch1 = event.touches[0];
|
const touch1 = event.touches[0];
|
||||||
const touch2 = event.touches[1];
|
const touch2 = event.touches[1];
|
||||||
@ -620,7 +633,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
combinedSingleTouchStartHandler(x, y) {
|
combinedSingleTouchStartHandler(x, y) {
|
||||||
const pos = new Vector(x, y);
|
const pos = new Vector(x, y);
|
||||||
if (this.downPreHandler.dispatch(pos) === STOP_PROPAGATION) {
|
if (this.downPreHandler.dispatch(pos, enumMouseButton.left) === STOP_PROPAGATION) {
|
||||||
// Somebody else captured it
|
// Somebody else captured it
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ export const enumColorsToHexCode = {
|
|||||||
[enumColors.purple]: "#dd66ff",
|
[enumColors.purple]: "#dd66ff",
|
||||||
|
|
||||||
// blue + green
|
// blue + green
|
||||||
[enumColors.cyan]: "#87fff5",
|
[enumColors.cyan]: "#00fcff",
|
||||||
|
|
||||||
// blue + green + red
|
// blue + green + red
|
||||||
[enumColors.white]: "#ffffff",
|
[enumColors.white]: "#ffffff",
|
||||||
|
@ -59,9 +59,8 @@ export class BeltComponent extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the belt can currently accept an item from the given direction
|
* Returns if the belt can currently accept an item from the given direction
|
||||||
* @param {enumDirection} direction
|
|
||||||
*/
|
*/
|
||||||
canAcceptNewItem(direction) {
|
canAcceptNewItem() {
|
||||||
const firstItem = this.sortedItems[0];
|
const firstItem = this.sortedItems[0];
|
||||||
if (!firstItem) {
|
if (!firstItem) {
|
||||||
return true;
|
return true;
|
||||||
@ -73,9 +72,8 @@ export class BeltComponent extends Component {
|
|||||||
/**
|
/**
|
||||||
* Pushes a new item to the belt
|
* Pushes a new item to the belt
|
||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
* @param {enumDirection} direction
|
|
||||||
*/
|
*/
|
||||||
takeNewItem(item, direction) {
|
takeNewItem(item) {
|
||||||
this.sortedItems.unshift([0, item]);
|
this.sortedItems.unshift([0, item]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from "../component";
|
import { Component } from "../component";
|
||||||
import { Vector, enumDirection, enumDirectionToAngle, enumInvertedDirections } from "../../core/vector";
|
import { Vector, enumDirection, enumInvertedDirections } from "../../core/vector";
|
||||||
import { BaseItem } from "../base_item";
|
import { BaseItem } from "../base_item";
|
||||||
import { ShapeItem } from "../items/shape_item";
|
import { ShapeItem } from "../items/shape_item";
|
||||||
import { ColorItem } from "../items/color_item";
|
import { ColorItem } from "../items/color_item";
|
||||||
@ -34,6 +34,23 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
filter: types.nullable(types.enum(enumItemAcceptorItemFilter)),
|
filter: types.nullable(types.enum(enumItemAcceptorItemFilter)),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
animated: types.bool,
|
||||||
|
beltUnderlays: types.array(
|
||||||
|
types.structured({
|
||||||
|
pos: types.vector,
|
||||||
|
direction: types.enum(enumDirection),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
|
||||||
|
// We don't actually need to store the animations
|
||||||
|
// itemConsumptionAnimations: types.array(
|
||||||
|
// types.structured({
|
||||||
|
// item: types.obj(gItemRegistry),
|
||||||
|
// slotIndex: types.uint,
|
||||||
|
// animProgress: types.float,
|
||||||
|
// direction: types.enum(enumDirection),
|
||||||
|
// })
|
||||||
|
// ),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,10 +58,23 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
*
|
*
|
||||||
* @param {object} param0
|
* @param {object} param0
|
||||||
* @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} param0.slots The slots from which we accept items
|
* @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} param0.slots The slots from which we accept items
|
||||||
|
* @param {boolean=} param0.animated Whether to animate item consumption
|
||||||
|
* @param {Array<{pos: Vector, direction: enumDirection}>=} param0.beltUnderlays Where to render belt underlays
|
||||||
*/
|
*/
|
||||||
constructor({ slots = [] }) {
|
constructor({ slots = [], beltUnderlays = [], animated = true }) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.animated = animated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixes belt animations
|
||||||
|
* @type {Array<{ item: BaseItem, slotIndex: number, animProgress: number, direction: enumDirection}>}
|
||||||
|
*/
|
||||||
|
this.itemConsumptionAnimations = [];
|
||||||
|
|
||||||
|
/* Which belt underlays to render */
|
||||||
|
this.beltUnderlays = beltUnderlays;
|
||||||
|
|
||||||
this.setSlots(slots);
|
this.setSlots(slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +116,23 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an item has been accepted so that
|
||||||
|
* @param {number} slotIndex
|
||||||
|
* @param {enumDirection} direction
|
||||||
|
* @param {BaseItem} item
|
||||||
|
*/
|
||||||
|
onItemAccepted(slotIndex, direction, item) {
|
||||||
|
if (this.animated) {
|
||||||
|
this.itemConsumptionAnimations.push({
|
||||||
|
item,
|
||||||
|
slotIndex,
|
||||||
|
direction,
|
||||||
|
animProgress: 0.0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to find a slot which accepts the current item
|
* Tries to find a slot which accepts the current item
|
||||||
* @param {Vector} targetLocalTile
|
* @param {Vector} targetLocalTile
|
||||||
@ -106,12 +153,6 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) {
|
for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) {
|
||||||
const slot = this.slots[slotIndex];
|
const slot = this.slots[slotIndex];
|
||||||
|
|
||||||
// const acceptorLocalPosition = targetStaticComp.applyRotationToVector(
|
|
||||||
// slot.pos
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const acceptorGlobalPosition = acceptorLocalPosition.add(targetStaticComp.origin);
|
|
||||||
|
|
||||||
// Make sure the acceptor slot is on the right position
|
// Make sure the acceptor slot is on the right position
|
||||||
if (!slot.pos.equals(targetLocalTile)) {
|
if (!slot.pos.equals(targetLocalTile)) {
|
||||||
continue;
|
continue;
|
||||||
@ -130,7 +171,6 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// && this.canAcceptItem(slotIndex, ejectingItem)
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,7 @@ export class ItemProcessorComponent extends Component {
|
|||||||
nextOutputSlot: types.uint,
|
nextOutputSlot: types.uint,
|
||||||
type: types.enum(enumItemProcessorTypes),
|
type: types.enum(enumItemProcessorTypes),
|
||||||
inputsPerCharge: types.uint,
|
inputsPerCharge: types.uint,
|
||||||
beltUnderlays: types.array(
|
|
||||||
types.structured({
|
|
||||||
pos: types.vector,
|
|
||||||
direction: types.enum(enumDirection),
|
|
||||||
})
|
|
||||||
),
|
|
||||||
inputSlots: types.array(
|
inputSlots: types.array(
|
||||||
types.structured({
|
types.structured({
|
||||||
item: types.obj(gItemRegistry),
|
item: types.obj(gItemRegistry),
|
||||||
@ -50,14 +45,6 @@ export class ItemProcessorComponent extends Component {
|
|||||||
})
|
})
|
||||||
),
|
),
|
||||||
secondsUntilEject: types.float,
|
secondsUntilEject: types.float,
|
||||||
itemConsumptionAnimations: types.array(
|
|
||||||
types.structured({
|
|
||||||
item: types.obj(gItemRegistry),
|
|
||||||
slotIndex: types.uint,
|
|
||||||
animProgress: types.float,
|
|
||||||
direction: types.enum(enumDirection),
|
|
||||||
})
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,14 +53,9 @@ export class ItemProcessorComponent extends Component {
|
|||||||
* @param {object} param0
|
* @param {object} param0
|
||||||
* @param {enumItemProcessorTypes=} param0.processorType Which type of processor this is
|
* @param {enumItemProcessorTypes=} param0.processorType Which type of processor this is
|
||||||
* @param {number=} param0.inputsPerCharge How many items this machine needs until it can start working
|
* @param {number=} param0.inputsPerCharge How many items this machine needs until it can start working
|
||||||
* @param {Array<{pos: Vector, direction: enumDirection}>=} param0.beltUnderlays Where to render belt underlays
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constructor({
|
constructor({ processorType = enumItemProcessorTypes.splitter, inputsPerCharge = 1 }) {
|
||||||
processorType = enumItemProcessorTypes.splitter,
|
|
||||||
inputsPerCharge = 1,
|
|
||||||
beltUnderlays = [],
|
|
||||||
}) {
|
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// Which slot to emit next, this is only a preference and if it can't emit
|
// Which slot to emit next, this is only a preference and if it can't emit
|
||||||
@ -87,9 +69,6 @@ export class ItemProcessorComponent extends Component {
|
|||||||
// How many inputs we need for one charge
|
// How many inputs we need for one charge
|
||||||
this.inputsPerCharge = inputsPerCharge;
|
this.inputsPerCharge = inputsPerCharge;
|
||||||
|
|
||||||
// Which belt underlays to render
|
|
||||||
this.beltUnderlays = beltUnderlays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our current inputs
|
* Our current inputs
|
||||||
* @type {Array<{ item: BaseItem, sourceSlot: number }>}
|
* @type {Array<{ item: BaseItem, sourceSlot: number }>}
|
||||||
@ -108,19 +87,14 @@ export class ItemProcessorComponent extends Component {
|
|||||||
* How long it takes until we are done with the current items
|
* How long it takes until we are done with the current items
|
||||||
*/
|
*/
|
||||||
this.secondsUntilEject = 0;
|
this.secondsUntilEject = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes belt animations
|
|
||||||
* @type {Array<{ item: BaseItem, slotIndex: number, animProgress: number, direction: enumDirection}>}
|
|
||||||
*/
|
|
||||||
this.itemConsumptionAnimations = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to take the item
|
* Tries to take the item
|
||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
|
* @param {number} sourceSlot
|
||||||
*/
|
*/
|
||||||
tryTakeItem(item, sourceSlot, sourceDirection) {
|
tryTakeItem(item, sourceSlot) {
|
||||||
// Check that we only take one item per slot
|
// Check that we only take one item per slot
|
||||||
for (let i = 0; i < this.inputSlots.length; ++i) {
|
for (let i = 0; i < this.inputSlots.length; ++i) {
|
||||||
const slot = this.inputSlots[i];
|
const slot = this.inputSlots[i];
|
||||||
@ -130,12 +104,6 @@ export class ItemProcessorComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.inputSlots.push({ item, sourceSlot });
|
this.inputSlots.push({ item, sourceSlot });
|
||||||
this.itemConsumptionAnimations.push({
|
|
||||||
item,
|
|
||||||
slotIndex: sourceSlot,
|
|
||||||
direction: sourceDirection,
|
|
||||||
animProgress: 0.0,
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,9 @@ export class UndergroundBeltComponent extends Component {
|
|||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.tier = tier;
|
this.tier = tier;
|
||||||
|
|
||||||
|
/** @type {Array<{ item: BaseItem, progress: number }>} */
|
||||||
|
this.consumptionAnimations = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used on both receiver and sender.
|
* Used on both receiver and sender.
|
||||||
* Reciever: Used to store the next item to transfer, and to block input while doing this
|
* Reciever: Used to store the next item to transfer, and to block input while doing this
|
||||||
|
@ -398,10 +398,10 @@ export class GameCore {
|
|||||||
// systems.mapResources.draw(params);
|
// systems.mapResources.draw(params);
|
||||||
|
|
||||||
if (!this.root.camera.getIsMapOverlayActive()) {
|
if (!this.root.camera.getIsMapOverlayActive()) {
|
||||||
systems.itemProcessor.drawUnderlays(params);
|
systems.itemAcceptor.drawUnderlays(params);
|
||||||
systems.belt.draw(params);
|
systems.belt.draw(params);
|
||||||
systems.itemEjector.draw(params);
|
systems.itemEjector.draw(params);
|
||||||
systems.itemProcessor.draw(params);
|
systems.itemAcceptor.draw(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.map.drawForeground(params);
|
root.map.drawForeground(params);
|
||||||
|
@ -11,6 +11,7 @@ import { ItemProcessorSystem } from "./systems/item_processor";
|
|||||||
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
||||||
import { HubSystem } from "./systems/hub";
|
import { HubSystem } from "./systems/hub";
|
||||||
import { StaticMapEntitySystem } from "./systems/static_map_entity";
|
import { StaticMapEntitySystem } from "./systems/static_map_entity";
|
||||||
|
import { ItemAcceptorSystem } from "./systems/item_acceptor";
|
||||||
|
|
||||||
const logger = createLogger("game_system_manager");
|
const logger = createLogger("game_system_manager");
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ export class GameSystemManager {
|
|||||||
/** @type {StaticMapEntitySystem} */
|
/** @type {StaticMapEntitySystem} */
|
||||||
staticMapEntities: null,
|
staticMapEntities: null,
|
||||||
|
|
||||||
|
/** @type {ItemAcceptorSystem} */
|
||||||
|
itemAcceptor: null,
|
||||||
|
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
};
|
};
|
||||||
this.systemUpdateOrder = [];
|
this.systemUpdateOrder = [];
|
||||||
@ -82,6 +86,8 @@ export class GameSystemManager {
|
|||||||
|
|
||||||
add("staticMapEntities", StaticMapEntitySystem);
|
add("staticMapEntities", StaticMapEntitySystem);
|
||||||
|
|
||||||
|
add("itemAcceptor", ItemAcceptorSystem);
|
||||||
|
|
||||||
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");
|
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import { Math_abs, Math_radians, Math_degrees } from "../../../core/builtins";
|
|||||||
import { Loader } from "../../../core/loader";
|
import { Loader } from "../../../core/loader";
|
||||||
import { drawRotatedSprite } from "../../../core/draw_utils";
|
import { drawRotatedSprite } from "../../../core/draw_utils";
|
||||||
import { Entity } from "../../entity";
|
import { Entity } from "../../entity";
|
||||||
|
import { enumMouseButton } from "../../camera";
|
||||||
|
|
||||||
export class HUDBuildingPlacer extends BaseHUDPart {
|
export class HUDBuildingPlacer extends BaseHUDPart {
|
||||||
initialize() {
|
initialize() {
|
||||||
@ -45,6 +46,11 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
|
|
||||||
this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {});
|
this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we are currently drag-deleting
|
||||||
|
*/
|
||||||
|
this.currentlyDeleting = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores which variants for each building we prefer, this is based on what
|
* Stores which variants for each building we prefer, this is based on what
|
||||||
* the user last selected
|
* the user last selected
|
||||||
@ -87,14 +93,17 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
/**
|
/**
|
||||||
* mouse down pre handler
|
* mouse down pre handler
|
||||||
* @param {Vector} pos
|
* @param {Vector} pos
|
||||||
|
* @param {enumMouseButton} button
|
||||||
*/
|
*/
|
||||||
onMouseDown(pos) {
|
onMouseDown(pos, button) {
|
||||||
if (this.root.camera.getIsMapOverlayActive()) {
|
if (this.root.camera.getIsMapOverlayActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.currentMetaBuilding.get()) {
|
// Placement
|
||||||
|
if (button === enumMouseButton.left && this.currentMetaBuilding.get()) {
|
||||||
this.currentlyDragging = true;
|
this.currentlyDragging = true;
|
||||||
|
this.currentlyDeleting = false;
|
||||||
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
|
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
|
||||||
|
|
||||||
// Place initial building
|
// Place initial building
|
||||||
@ -102,6 +111,15 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
|
|
||||||
return STOP_PROPAGATION;
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deletion
|
||||||
|
if (button === enumMouseButton.right && !this.currentMetaBuilding.get()) {
|
||||||
|
this.currentlyDragging = true;
|
||||||
|
this.currentlyDeleting = true;
|
||||||
|
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
|
||||||
|
this.currentMetaBuilding.set(null);
|
||||||
|
return STOP_PROPAGATION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,7 +132,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metaBuilding = this.currentMetaBuilding.get();
|
const metaBuilding = this.currentMetaBuilding.get();
|
||||||
if (metaBuilding && this.lastDragTile) {
|
if ((metaBuilding || this.currentlyDeleting) && this.lastDragTile) {
|
||||||
const oldPos = this.lastDragTile;
|
const oldPos = this.lastDragTile;
|
||||||
const newPos = this.root.camera.screenToWorld(pos).toTileSpace();
|
const newPos = this.root.camera.screenToWorld(pos).toTileSpace();
|
||||||
|
|
||||||
@ -126,6 +144,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
|
|
||||||
if (!oldPos.equals(newPos)) {
|
if (!oldPos.equals(newPos)) {
|
||||||
if (
|
if (
|
||||||
|
metaBuilding &&
|
||||||
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
|
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
|
||||||
!this.root.app.inputMgr.ctrlIsDown
|
!this.root.app.inputMgr.ctrlIsDown
|
||||||
) {
|
) {
|
||||||
@ -152,8 +171,15 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
var sy = y0 < y1 ? 1 : -1;
|
var sy = y0 < y1 ? 1 : -1;
|
||||||
var err = dx - dy;
|
var err = dx - dy;
|
||||||
|
|
||||||
while (this.currentMetaBuilding.get()) {
|
while (this.currentlyDeleting || this.currentMetaBuilding.get()) {
|
||||||
|
if (this.currentlyDeleting) {
|
||||||
|
const contents = this.root.map.getTileContentXY(x0, y0);
|
||||||
|
if (contents && !contents.queuedForDestroy && !contents.destroyed) {
|
||||||
|
this.root.logic.tryDeleteBuilding(contents);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.tryPlaceCurrentBuildingAt(new Vector(x0, y0));
|
this.tryPlaceCurrentBuildingAt(new Vector(x0, y0));
|
||||||
|
}
|
||||||
if (x0 === x1 && y0 === y1) break;
|
if (x0 === x1 && y0 === y1) break;
|
||||||
var e2 = 2 * err;
|
var e2 = 2 * err;
|
||||||
if (e2 > -dy) {
|
if (e2 > -dy) {
|
||||||
@ -186,6 +212,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
*/
|
*/
|
||||||
abortDragging() {
|
abortDragging() {
|
||||||
this.currentlyDragging = true;
|
this.currentlyDragging = true;
|
||||||
|
this.currentlyDeleting = false;
|
||||||
this.lastDragTile = null;
|
this.lastDragTile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +228,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
* @param {MetaBuilding} metaBuilding
|
* @param {MetaBuilding} metaBuilding
|
||||||
*/
|
*/
|
||||||
onSelectedMetaBuildingChanged(metaBuilding) {
|
onSelectedMetaBuildingChanged(metaBuilding) {
|
||||||
|
this.abortDragging();
|
||||||
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
|
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
|
||||||
if (metaBuilding) {
|
if (metaBuilding) {
|
||||||
this.buildingInfoElements.label.innerHTML = metaBuilding.getName();
|
this.buildingInfoElements.label.innerHTML = metaBuilding.getName();
|
||||||
@ -215,7 +243,8 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
this.currentVariant.set(variant);
|
this.currentVariant.set(variant);
|
||||||
|
|
||||||
this.fakeEntity = new Entity(null);
|
this.fakeEntity = new Entity(null);
|
||||||
metaBuilding.setupEntityComponents(this.fakeEntity, null, variant);
|
metaBuilding.setupEntityComponents(this.fakeEntity, null);
|
||||||
|
|
||||||
this.fakeEntity.addComponent(
|
this.fakeEntity.addComponent(
|
||||||
new StaticMapEntityComponent({
|
new StaticMapEntityComponent({
|
||||||
origin: new Vector(0, 0),
|
origin: new Vector(0, 0),
|
||||||
@ -223,13 +252,13 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
|||||||
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
|
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get());
|
||||||
|
|
||||||
this.buildingInfoElements.tutorialImage.setAttribute(
|
this.buildingInfoElements.tutorialImage.setAttribute(
|
||||||
"data-icon",
|
"data-icon",
|
||||||
"building_tutorials/" + metaBuilding.getId() + ".png"
|
"building_tutorials/" + metaBuilding.getId() + ".png"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.currentlyDragging = false;
|
|
||||||
this.fakeEntity = null;
|
this.fakeEntity = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,13 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
|||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
|
|
||||||
/** @type {Object.<string, { metaBuilding: MetaBuilding, unlocked: boolean, selected: boolean, element: HTMLElement}>} */
|
/** @type {Object.<string, {
|
||||||
|
* metaBuilding: MetaBuilding,
|
||||||
|
* unlocked: boolean,
|
||||||
|
* selected: boolean,
|
||||||
|
* element: HTMLElement,
|
||||||
|
* index: number
|
||||||
|
* }>} */
|
||||||
this.buildingHandles = {};
|
this.buildingHandles = {};
|
||||||
|
|
||||||
this.sigBuildingSelected = new Signal();
|
this.sigBuildingSelected = new Signal();
|
||||||
@ -76,6 +82,7 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
|||||||
element: itemContainer,
|
element: itemContainer,
|
||||||
unlocked: false,
|
unlocked: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
index: i,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +90,9 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
|||||||
this.onSelectedPlacementBuildingChanged,
|
this.onSelectedPlacementBuildingChanged,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.lastSelectedIndex = 0;
|
||||||
|
actionMapper.getBinding("cycle_buildings").add(this.cycleBuildings, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@ -98,6 +108,13 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cycleBuildings() {
|
||||||
|
const newIndex = (this.lastSelectedIndex + 1) % toolbarBuildings.length;
|
||||||
|
const metaBuildingClass = toolbarBuildings[newIndex];
|
||||||
|
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||||
|
this.selectBuildingForPlacement(metaBuilding);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {MetaBuilding} metaBuilding
|
* @param {MetaBuilding} metaBuilding
|
||||||
*/
|
*/
|
||||||
@ -109,6 +126,9 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
|||||||
handle.selected = newStatus;
|
handle.selected = newStatus;
|
||||||
handle.element.classList.toggle("selected", newStatus);
|
handle.element.classList.toggle("selected", newStatus);
|
||||||
}
|
}
|
||||||
|
if (handle.selected) {
|
||||||
|
this.lastSelectedIndex = handle.index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.classList.toggle("buildingSelected", !!metaBuilding);
|
this.element.classList.toggle("buildingSelected", !!metaBuilding);
|
||||||
|
@ -8,6 +8,7 @@ import { globalConfig } from "../../../core/config";
|
|||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { createLogger } from "../../../core/logging";
|
import { createLogger } from "../../../core/logging";
|
||||||
|
import { enumMouseButton } from "../../camera";
|
||||||
|
|
||||||
const logger = createLogger("hud/mass_selector");
|
const logger = createLogger("hud/mass_selector");
|
||||||
|
|
||||||
@ -82,12 +83,17 @@ export class HUDMassSelector extends BaseHUDPart {
|
|||||||
/**
|
/**
|
||||||
* mouse down pre handler
|
* mouse down pre handler
|
||||||
* @param {Vector} pos
|
* @param {Vector} pos
|
||||||
|
* @param {enumMouseButton} mouseButton
|
||||||
*/
|
*/
|
||||||
onMouseDown(pos) {
|
onMouseDown(pos, mouseButton) {
|
||||||
if (!this.root.app.inputMgr.ctrlIsDown) {
|
if (!this.root.app.inputMgr.ctrlIsDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mouseButton !== enumMouseButton.left) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.root.app.inputMgr.shiftIsDown) {
|
if (!this.root.app.inputMgr.shiftIsDown) {
|
||||||
// Start new selection
|
// Start new selection
|
||||||
this.entityUidsMarkedForDeletion = new Set();
|
this.entityUidsMarkedForDeletion = new Set();
|
||||||
|
@ -50,6 +50,8 @@ export const defaultKeybindings = {
|
|||||||
rotate_while_placing: { keyCode: key("R") },
|
rotate_while_placing: { keyCode: key("R") },
|
||||||
|
|
||||||
cycle_variants: { keyCode: key("T") },
|
cycle_variants: { keyCode: key("T") },
|
||||||
|
|
||||||
|
cycle_buildings: { keyCode: 9 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,10 +4,13 @@ import { DrawParameters } from "../../core/draw_parameters";
|
|||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { formatBigNumber } from "../../core/utils";
|
import { formatBigNumber } from "../../core/utils";
|
||||||
import { enumHubGoalRewardToString } from "../tutorial_goals";
|
import { enumHubGoalRewardToString } from "../tutorial_goals";
|
||||||
|
import { Loader } from "../../core/loader";
|
||||||
|
|
||||||
export class HubSystem extends GameSystemWithFilter {
|
export class HubSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, [HubComponent]);
|
super(root, [HubComponent]);
|
||||||
|
|
||||||
|
this.hubSprite = Loader.getSprite("sprites/buildings/hub.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(parameters) {
|
draw(parameters) {
|
||||||
@ -40,6 +43,9 @@ export class HubSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
|
const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
|
||||||
|
|
||||||
|
// Background
|
||||||
|
staticComp.drawSpriteOnFullEntityBounds(parameters, this.hubSprite, 2.2);
|
||||||
|
|
||||||
const definition = this.root.hubGoals.currentGoal.definition;
|
const definition = this.root.hubGoals.currentGoal.definition;
|
||||||
|
|
||||||
definition.draw(pos.x - 25, pos.y - 10, parameters, 40);
|
definition.draw(pos.x - 25, pos.y - 10, parameters, 40);
|
||||||
|
114
src/js/game/systems/item_acceptor.js
Normal file
114
src/js/game/systems/item_acceptor.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
|
import { globalConfig } from "../../core/config";
|
||||||
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { enumDirectionToVector, enumDirectionToAngle } from "../../core/vector";
|
||||||
|
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
||||||
|
import { Loader } from "../../core/loader";
|
||||||
|
import { drawRotatedSprite } from "../../core/draw_utils";
|
||||||
|
import { Math_radians } from "../../core/builtins";
|
||||||
|
|
||||||
|
export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||||
|
constructor(root) {
|
||||||
|
super(root, [ItemAcceptorComponent]);
|
||||||
|
|
||||||
|
this.underlayBeltSprites = [
|
||||||
|
Loader.getSprite("sprites/belt/forward_0.png"),
|
||||||
|
Loader.getSprite("sprites/belt/forward_1.png"),
|
||||||
|
Loader.getSprite("sprites/belt/forward_2.png"),
|
||||||
|
Loader.getSprite("sprites/belt/forward_3.png"),
|
||||||
|
Loader.getSprite("sprites/belt/forward_4.png"),
|
||||||
|
Loader.getSprite("sprites/belt/forward_5.png"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
|
const entity = this.allEntities[i];
|
||||||
|
const aceptorComp = entity.components.ItemAcceptor;
|
||||||
|
|
||||||
|
// Process item consumption animations to avoid items popping from the belts
|
||||||
|
for (let animIndex = 0; animIndex < aceptorComp.itemConsumptionAnimations.length; ++animIndex) {
|
||||||
|
const anim = aceptorComp.itemConsumptionAnimations[animIndex];
|
||||||
|
anim.animProgress +=
|
||||||
|
globalConfig.physicsDeltaSeconds * this.root.hubGoals.getBeltBaseSpeed() * 2;
|
||||||
|
if (anim.animProgress > 1) {
|
||||||
|
aceptorComp.itemConsumptionAnimations.splice(animIndex, 1);
|
||||||
|
animIndex -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(parameters) {
|
||||||
|
this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawUnderlays(parameters) {
|
||||||
|
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
drawEntity(parameters, entity) {
|
||||||
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
|
const acceptorComp = entity.components.ItemAcceptor;
|
||||||
|
|
||||||
|
for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) {
|
||||||
|
const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[
|
||||||
|
animIndex
|
||||||
|
];
|
||||||
|
|
||||||
|
const slotData = acceptorComp.slots[slotIndex];
|
||||||
|
const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin);
|
||||||
|
|
||||||
|
const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)];
|
||||||
|
const finalTile = slotWorldPos.subScalars(
|
||||||
|
fadeOutDirection.x * (animProgress / 2 - 0.5),
|
||||||
|
fadeOutDirection.y * (animProgress / 2 - 0.5)
|
||||||
|
);
|
||||||
|
item.draw(
|
||||||
|
(finalTile.x + 0.5) * globalConfig.tileSize,
|
||||||
|
(finalTile.y + 0.5) * globalConfig.tileSize,
|
||||||
|
parameters
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
drawEntityUnderlays(parameters, entity) {
|
||||||
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
|
const acceptorComp = entity.components.ItemAcceptor;
|
||||||
|
|
||||||
|
const underlays = acceptorComp.beltUnderlays;
|
||||||
|
for (let i = 0; i < underlays.length; ++i) {
|
||||||
|
const { pos, direction } = underlays[i];
|
||||||
|
|
||||||
|
const transformedPos = staticComp.localTileToWorld(pos);
|
||||||
|
const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)];
|
||||||
|
|
||||||
|
// SYNC with systems/belt.js:drawSingleEntity!
|
||||||
|
const animationIndex = Math.floor(
|
||||||
|
(this.root.time.now() *
|
||||||
|
this.root.hubGoals.getBeltBaseSpeed() *
|
||||||
|
this.underlayBeltSprites.length *
|
||||||
|
126) /
|
||||||
|
42
|
||||||
|
);
|
||||||
|
|
||||||
|
drawRotatedSprite({
|
||||||
|
parameters,
|
||||||
|
sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length],
|
||||||
|
x: (transformedPos.x + 0.5) * globalConfig.tileSize,
|
||||||
|
y: (transformedPos.y + 0.5) * globalConfig.tileSize,
|
||||||
|
angle: Math_radians(angle),
|
||||||
|
size: globalConfig.tileSize,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -72,14 +72,12 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.tryPassOverItem(ejectingItem, targetEntity, matchingSlot.index)) {
|
||||||
this.tryPassOverItem(
|
targetAcceptorComp.onItemAccepted(
|
||||||
ejectingItem,
|
|
||||||
targetEntity,
|
|
||||||
matchingSlot.index,
|
matchingSlot.index,
|
||||||
matchingSlot.acceptedDirection
|
matchingSlot.acceptedDirection,
|
||||||
)
|
ejectingItem
|
||||||
) {
|
);
|
||||||
ejectorSlot.item = null;
|
ejectorSlot.item = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -92,9 +90,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
* @param {Entity} receiver
|
* @param {Entity} receiver
|
||||||
* @param {number} slotIndex
|
* @param {number} slotIndex
|
||||||
* @param {string} localDirection
|
|
||||||
*/
|
*/
|
||||||
tryPassOverItem(item, receiver, slotIndex, localDirection) {
|
tryPassOverItem(item, receiver, slotIndex) {
|
||||||
// Try figuring out how what to do with the item
|
// Try figuring out how what to do with the item
|
||||||
// TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell.
|
// TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell.
|
||||||
// Also its just a few cases (hope it stays like this .. :x).
|
// Also its just a few cases (hope it stays like this .. :x).
|
||||||
@ -102,8 +99,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
const beltComp = receiver.components.Belt;
|
const beltComp = receiver.components.Belt;
|
||||||
if (beltComp) {
|
if (beltComp) {
|
||||||
// Ayy, its a belt!
|
// Ayy, its a belt!
|
||||||
if (beltComp.canAcceptNewItem(localDirection)) {
|
if (beltComp.canAcceptNewItem()) {
|
||||||
beltComp.takeNewItem(item, localDirection);
|
beltComp.takeNewItem(item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,7 +108,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
const itemProcessorComp = receiver.components.ItemProcessor;
|
const itemProcessorComp = receiver.components.ItemProcessor;
|
||||||
if (itemProcessorComp) {
|
if (itemProcessorComp) {
|
||||||
// Its an item processor ..
|
// Its an item processor ..
|
||||||
if (itemProcessorComp.tryTakeItem(item, slotIndex, localDirection)) {
|
if (itemProcessorComp.tryTakeItem(item, slotIndex)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,16 @@
|
|||||||
|
import { Math_max } from "../../core/builtins";
|
||||||
import { globalConfig } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
import { DrawParameters } from "../../core/draw_parameters";
|
import { BaseItem } from "../base_item";
|
||||||
import { Loader } from "../../core/loader";
|
import { enumColorMixingResults } from "../colors";
|
||||||
|
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
import { ItemProcessorComponent, enumItemProcessorTypes } from "../components/item_processor";
|
|
||||||
import { Math_max, Math_radians } from "../../core/builtins";
|
|
||||||
import { BaseItem } from "../base_item";
|
|
||||||
import { ShapeItem } from "../items/shape_item";
|
|
||||||
import { enumDirectionToVector, enumDirection, enumDirectionToAngle } from "../../core/vector";
|
|
||||||
import { ColorItem } from "../items/color_item";
|
import { ColorItem } from "../items/color_item";
|
||||||
import { enumColorMixingResults } from "../colors";
|
import { ShapeItem } from "../items/shape_item";
|
||||||
import { drawRotatedSprite } from "../../core/draw_utils";
|
|
||||||
|
|
||||||
export class ItemProcessorSystem extends GameSystemWithFilter {
|
export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, [ItemProcessorComponent]);
|
super(root, [ItemProcessorComponent]);
|
||||||
|
|
||||||
this.underlayBeltSprites = [
|
|
||||||
Loader.getSprite("sprites/belt/forward_0.png"),
|
|
||||||
Loader.getSprite("sprites/belt/forward_1.png"),
|
|
||||||
Loader.getSprite("sprites/belt/forward_2.png"),
|
|
||||||
Loader.getSprite("sprites/belt/forward_3.png"),
|
|
||||||
Loader.getSprite("sprites/belt/forward_4.png"),
|
|
||||||
Loader.getSprite("sprites/belt/forward_5.png"),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
draw(parameters) {
|
|
||||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
drawUnderlays(parameters) {
|
|
||||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@ -47,17 +26,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
processorComp.secondsUntilEject - globalConfig.physicsDeltaSeconds
|
processorComp.secondsUntilEject - globalConfig.physicsDeltaSeconds
|
||||||
);
|
);
|
||||||
|
|
||||||
// Also, process item consumption animations to avoid items popping from the belts
|
|
||||||
for (let animIndex = 0; animIndex < processorComp.itemConsumptionAnimations.length; ++animIndex) {
|
|
||||||
const anim = processorComp.itemConsumptionAnimations[animIndex];
|
|
||||||
anim.animProgress +=
|
|
||||||
globalConfig.physicsDeltaSeconds * this.root.hubGoals.getBeltBaseSpeed() * 2;
|
|
||||||
if (anim.animProgress > 1) {
|
|
||||||
processorComp.itemConsumptionAnimations.splice(animIndex, 1);
|
|
||||||
animIndex -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have any finished items we can eject
|
// Check if we have any finished items we can eject
|
||||||
if (
|
if (
|
||||||
processorComp.secondsUntilEject === 0 && // it was processed in time
|
processorComp.secondsUntilEject === 0 && // it was processed in time
|
||||||
@ -363,68 +331,4 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
processorComp.itemsToEject = outItems;
|
processorComp.itemsToEject = outItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {DrawParameters} parameters
|
|
||||||
* @param {Entity} entity
|
|
||||||
*/
|
|
||||||
drawEntity(parameters, entity) {
|
|
||||||
const staticComp = entity.components.StaticMapEntity;
|
|
||||||
const processorComp = entity.components.ItemProcessor;
|
|
||||||
const acceptorComp = entity.components.ItemAcceptor;
|
|
||||||
|
|
||||||
for (let animIndex = 0; animIndex < processorComp.itemConsumptionAnimations.length; ++animIndex) {
|
|
||||||
const { item, slotIndex, animProgress, direction } = processorComp.itemConsumptionAnimations[
|
|
||||||
animIndex
|
|
||||||
];
|
|
||||||
|
|
||||||
const slotData = acceptorComp.slots[slotIndex];
|
|
||||||
const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin);
|
|
||||||
|
|
||||||
const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)];
|
|
||||||
const finalTile = slotWorldPos.subScalars(
|
|
||||||
fadeOutDirection.x * (animProgress / 2 - 0.5),
|
|
||||||
fadeOutDirection.y * (animProgress / 2 - 0.5)
|
|
||||||
);
|
|
||||||
item.draw(
|
|
||||||
(finalTile.x + 0.5) * globalConfig.tileSize,
|
|
||||||
(finalTile.y + 0.5) * globalConfig.tileSize,
|
|
||||||
parameters
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {DrawParameters} parameters
|
|
||||||
* @param {Entity} entity
|
|
||||||
*/
|
|
||||||
drawEntityUnderlays(parameters, entity) {
|
|
||||||
const staticComp = entity.components.StaticMapEntity;
|
|
||||||
const processorComp = entity.components.ItemProcessor;
|
|
||||||
|
|
||||||
const underlays = processorComp.beltUnderlays;
|
|
||||||
for (let i = 0; i < underlays.length; ++i) {
|
|
||||||
const { pos, direction } = underlays[i];
|
|
||||||
|
|
||||||
const transformedPos = staticComp.localTileToWorld(pos);
|
|
||||||
const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)];
|
|
||||||
|
|
||||||
// SYNC with systems/belt.js:drawSingleEntity!
|
|
||||||
const animationIndex = Math.floor(
|
|
||||||
(this.root.time.now() *
|
|
||||||
this.root.hubGoals.getBeltBaseSpeed() *
|
|
||||||
this.underlayBeltSprites.length *
|
|
||||||
126) /
|
|
||||||
42
|
|
||||||
);
|
|
||||||
|
|
||||||
drawRotatedSprite({
|
|
||||||
parameters,
|
|
||||||
sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length],
|
|
||||||
x: (transformedPos.x + 0.5) * globalConfig.tileSize,
|
|
||||||
y: (transformedPos.y + 0.5) * globalConfig.tileSize,
|
|
||||||
angle: Math_radians(angle),
|
|
||||||
size: globalConfig.tileSize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ export class StaticMapEntitySystem extends GameSystem {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const drawEntitiesOutside = parameters.zoomLevel < globalConfig.mapChunkPrerenderMinZoom;
|
|
||||||
const drawOutlinesOnly = parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom;
|
const drawOutlinesOnly = parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom;
|
||||||
|
|
||||||
const contents = chunk.contents;
|
const contents = chunk.contents;
|
||||||
@ -54,14 +53,6 @@ export class StaticMapEntitySystem extends GameSystem {
|
|||||||
} else {
|
} else {
|
||||||
const spriteKey = staticComp.spriteKey;
|
const spriteKey = staticComp.spriteKey;
|
||||||
if (spriteKey) {
|
if (spriteKey) {
|
||||||
// Check if origin is contained to avoid drawing entities multiple times
|
|
||||||
if (
|
|
||||||
drawEntitiesOutside ||
|
|
||||||
(staticComp.origin.x >= chunk.tileX &&
|
|
||||||
staticComp.origin.x < chunk.tileX + globalConfig.mapChunkSize &&
|
|
||||||
staticComp.origin.y >= chunk.tileY &&
|
|
||||||
staticComp.origin.y < chunk.tileY + globalConfig.mapChunkSize)
|
|
||||||
) {
|
|
||||||
const sprite = Loader.getSprite(spriteKey);
|
const sprite = Loader.getSprite(spriteKey);
|
||||||
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false);
|
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false);
|
||||||
}
|
}
|
||||||
@ -71,4 +62,3 @@ export class StaticMapEntitySystem extends GameSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
6
src/js/globals.d.ts
vendored
6
src/js/globals.d.ts
vendored
@ -199,10 +199,10 @@ declare class TypedTrackedState<T> {
|
|||||||
declare const STOP_PROPAGATION = "stop_propagation";
|
declare const STOP_PROPAGATION = "stop_propagation";
|
||||||
|
|
||||||
declare interface TypedSignal<T extends Array<any>> {
|
declare interface TypedSignal<T extends Array<any>> {
|
||||||
add(receiver: (...args: T) => typeof STOP_PROPAGATION | void, scope?: object);
|
add(receiver: (...args: T) => /* STOP_PROPAGATION */ string | void, scope?: object);
|
||||||
remove(receiver: (...args: T) => typeof STOP_PROPAGATION | void);
|
remove(receiver: (...args: T) => /* STOP_PROPAGATION */ string | void);
|
||||||
|
|
||||||
dispatch(...args: T): typeof STOP_PROPAGATION | void;
|
dispatch(...args: T): /* STOP_PROPAGATION */ string | void;
|
||||||
|
|
||||||
removeAll();
|
removeAll();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user