mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Add hidden HUD elements, zone, and zoom, boundary constraints
This commit is contained in:
parent
f478228557
commit
af980c7114
@ -62,6 +62,9 @@ export default {
|
|||||||
// Allows unlocked achievements to be logged to console in the local build
|
// Allows unlocked achievements to be logged to console in the local build
|
||||||
// testAchievements: true,
|
// testAchievements: true,
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
|
// Enables use of (some) existing flags within the puzzle mode context
|
||||||
|
// testPuzzleMode: true,
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
// Disables the automatic switch to an overview when zooming out
|
// Disables the automatic switch to an overview when zooming out
|
||||||
// disableMapOverview: true,
|
// disableMapOverview: true,
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
|
@ -392,13 +392,20 @@ export class Camera extends BasicSerializableObject {
|
|||||||
return rect.containsPoint(point.x, point.y);
|
return rect.containsPoint(point.x, point.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMaximumZoom() {
|
||||||
|
return this.root.gameMode.getMaximumZoom() * this.root.app.platformWrapper.getScreenScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
getMinimumZoom() {
|
||||||
|
return this.root.gameMode.getMinimumZoom() * this.root.app.platformWrapper.getScreenScale();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if we can further zoom in
|
* Returns if we can further zoom in
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
canZoomIn() {
|
canZoomIn() {
|
||||||
const maxLevel = this.root.app.platformWrapper.getMaximumZoom();
|
return this.zoomLevel <= this.getMaximumZoom() - 0.01;
|
||||||
return this.zoomLevel <= maxLevel - 0.01;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -406,8 +413,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
canZoomOut() {
|
canZoomOut() {
|
||||||
const minLevel = this.root.app.platformWrapper.getMinimumZoom();
|
return this.zoomLevel >= this.getMinimumZoom() + 0.01;
|
||||||
return this.zoomLevel >= minLevel + 0.01;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EVENTS
|
// EVENTS
|
||||||
@ -705,6 +711,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
|
|
||||||
this.didMoveSinceTouchStart = this.didMoveSinceTouchStart || delta.length() > 0;
|
this.didMoveSinceTouchStart = this.didMoveSinceTouchStart || delta.length() > 0;
|
||||||
this.center = this.center.add(delta);
|
this.center = this.center.add(delta);
|
||||||
|
this.clampPosition(this.center);
|
||||||
|
|
||||||
this.touchPostMoveVelocity = this.touchPostMoveVelocity
|
this.touchPostMoveVelocity = this.touchPostMoveVelocity
|
||||||
.multiplyScalar(velocitySmoothing)
|
.multiplyScalar(velocitySmoothing)
|
||||||
@ -743,17 +750,31 @@ export class Camera extends BasicSerializableObject {
|
|||||||
if (G_IS_DEV && globalConfig.debug.disableZoomLimits) {
|
if (G_IS_DEV && globalConfig.debug.disableZoomLimits) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const wrapper = this.root.app.platformWrapper;
|
|
||||||
|
|
||||||
assert(Number.isFinite(this.zoomLevel), "Invalid zoom level *before* clamp: " + this.zoomLevel);
|
assert(Number.isFinite(this.zoomLevel), "Invalid zoom level *before* clamp: " + this.zoomLevel);
|
||||||
this.zoomLevel = clamp(this.zoomLevel, wrapper.getMinimumZoom(), wrapper.getMaximumZoom());
|
this.zoomLevel = clamp(this.zoomLevel, this.getMinimumZoom(), this.getMaximumZoom());
|
||||||
assert(Number.isFinite(this.zoomLevel), "Invalid zoom level *after* clamp: " + this.zoomLevel);
|
assert(Number.isFinite(this.zoomLevel), "Invalid zoom level *after* clamp: " + this.zoomLevel);
|
||||||
|
|
||||||
if (this.desiredZoom) {
|
if (this.desiredZoom) {
|
||||||
this.desiredZoom = clamp(this.desiredZoom, wrapper.getMinimumZoom(), wrapper.getMaximumZoom());
|
this.desiredZoom = clamp(this.desiredZoom, this.getMinimumZoom(), this.getMaximumZoom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clamps x, y position within set boundaries
|
||||||
|
* @param {Vector} vector
|
||||||
|
*/
|
||||||
|
clampPosition(vector) {
|
||||||
|
if (!this.root.gameMode.hasBoundaries()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = this.root.gameMode.getBoundaryWidth();
|
||||||
|
const height = this.root.gameMode.getBoundaryHeight();
|
||||||
|
|
||||||
|
vector.x = clamp(vector.x, -width, width);
|
||||||
|
vector.y = clamp(vector.y, -height, height);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the camera
|
* Updates the camera
|
||||||
* @param {number} dt Delta time in milliseconds
|
* @param {number} dt Delta time in milliseconds
|
||||||
@ -921,6 +942,8 @@ export class Camera extends BasicSerializableObject {
|
|||||||
((0.5 * dt) / this.zoomLevel) * this.root.app.settings.getMovementSpeed()
|
((0.5 * dt) / this.zoomLevel) * this.root.app.settings.getMovementSpeed()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.clampPosition(this.center)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
registerCanvas,
|
registerCanvas,
|
||||||
} from "../core/buffer_utils";
|
} from "../core/buffer_utils";
|
||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { gGameModeRegistry } from "./game_mode_registry";
|
|
||||||
import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager";
|
import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { gMetaBuildingRegistry } from "../core/global_registries";
|
import { gMetaBuildingRegistry } from "../core/global_registries";
|
||||||
@ -169,6 +168,10 @@ export class GameCore {
|
|||||||
this.root.gameIsFresh = true;
|
this.root.gameIsFresh = true;
|
||||||
this.root.map.seed = randomInt(0, 100000);
|
this.root.map.seed = randomInt(0, 100000);
|
||||||
|
|
||||||
|
if (!this.root.gameMode.hasHub()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Place the hub
|
// Place the hub
|
||||||
const hub = gMetaBuildingRegistry.findByClass(MetaHubBuilding).createEntity({
|
const hub = gMetaBuildingRegistry.findByClass(MetaHubBuilding).createEntity({
|
||||||
root: this.root,
|
root: this.root,
|
||||||
|
@ -5,50 +5,160 @@ import { GameRoot } from "./root";
|
|||||||
import { gGameModeRegistry } from "../core/global_registries";
|
import { gGameModeRegistry } from "../core/global_registries";
|
||||||
import { types, BasicSerializableObject } from "../savegame/serialization";
|
import { types, BasicSerializableObject } from "../savegame/serialization";
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumGameModeIds = {
|
||||||
|
puzzleEdit: "puzzleEditMode",
|
||||||
|
puzzlePlay: "puzzlePlayMode",
|
||||||
|
regular: "regularMode",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumGameModeTypes = {
|
||||||
|
default: "defaultModeType",
|
||||||
|
puzzle: "puzzleModeType",
|
||||||
|
};
|
||||||
|
|
||||||
export class GameMode extends BasicSerializableObject {
|
export class GameMode extends BasicSerializableObject {
|
||||||
/** @returns {string} */
|
/** @returns {string} */
|
||||||
static getId() {
|
static getId() {
|
||||||
abstract;
|
abstract;
|
||||||
return "Unknown";
|
return "unknownMode";
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSchema() {
|
/** @returns {string} */
|
||||||
return {};
|
static getType() {
|
||||||
|
abstract;
|
||||||
|
return "unknownType";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {string} [id=Regular]
|
* @param {string} [id=Regular]
|
||||||
*/
|
*/
|
||||||
static create (root, id = "Regular") {
|
static create(root, id = enumGameModeIds.regular) {
|
||||||
// id = "Regular"
|
|
||||||
return new (gGameModeRegistry.findById(id))(root);
|
return new (gGameModeRegistry.findById(id))(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {string} [id=Regular]
|
|
||||||
*/
|
*/
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super();
|
super();
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {object} */
|
||||||
serialize() {
|
serialize() {
|
||||||
return {
|
return {
|
||||||
$: this.getId(),
|
$: this.getId(),
|
||||||
data: super.serialize()
|
data: super.serialize(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize({ $, data }) {
|
/** @param {object} savedata */
|
||||||
const Mode = gGameModeRegistry.findById($);
|
deserialize({ data }) {
|
||||||
|
super.deserialize(data, this.root);
|
||||||
return super.deserialize(data, Mode, gGameModeRegistry.getId(), this.root);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {string} */
|
||||||
getId() {
|
getId() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return this.constructor.getId();
|
return this.constructor.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {string} */
|
||||||
|
getType() {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.constructor.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name - Class name of HUD Part
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isHudPartHidden(name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name - Class name of HUD Part
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isHudPartExcluded(name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
hasZone() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
hasHints() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
hasHub() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
hasResources() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
hasBoundaries() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getMinimumZoom() {
|
||||||
|
return 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getMaximumZoom() {
|
||||||
|
return 3.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {object} */
|
||||||
|
getUpgrades() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getZoneWidth() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getZoneHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getBoundaryWidth() {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
|
getBoundaryHeight() {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {array} */
|
||||||
|
getLevelDefinitions() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
getIsFreeplayAvailable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {string} */
|
||||||
|
getBlueprintShapeKey() {
|
||||||
|
return "CbCbCbRb:CwCwCwCw";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import { createLogger } from "../core/logging";
|
|||||||
import { BeltSystem } from "./systems/belt";
|
import { BeltSystem } from "./systems/belt";
|
||||||
import { ItemEjectorSystem } from "./systems/item_ejector";
|
import { ItemEjectorSystem } from "./systems/item_ejector";
|
||||||
import { MapResourcesSystem } from "./systems/map_resources";
|
import { MapResourcesSystem } from "./systems/map_resources";
|
||||||
|
import { MapZoneSystem } from "./systems/map_zone";
|
||||||
import { MinerSystem } from "./systems/miner";
|
import { MinerSystem } from "./systems/miner";
|
||||||
import { ItemProcessorSystem } from "./systems/item_processor";
|
import { ItemProcessorSystem } from "./systems/item_processor";
|
||||||
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
||||||
@ -46,6 +47,9 @@ export class GameSystemManager {
|
|||||||
/** @type {MapResourcesSystem} */
|
/** @type {MapResourcesSystem} */
|
||||||
mapResources: null,
|
mapResources: null,
|
||||||
|
|
||||||
|
/** @type {MapZoneSystem} */
|
||||||
|
mapZone: null,
|
||||||
|
|
||||||
/** @type {MinerSystem} */
|
/** @type {MinerSystem} */
|
||||||
miner: null,
|
miner: null,
|
||||||
|
|
||||||
@ -140,6 +144,8 @@ export class GameSystemManager {
|
|||||||
|
|
||||||
add("mapResources", MapResourcesSystem);
|
add("mapResources", MapResourcesSystem);
|
||||||
|
|
||||||
|
add("mapZone", MapZoneSystem);
|
||||||
|
|
||||||
add("hub", HubSystem);
|
add("hub", HubSystem);
|
||||||
|
|
||||||
add("staticMapEntities", StaticMapEntitySystem);
|
add("staticMapEntities", StaticMapEntitySystem);
|
||||||
|
@ -74,42 +74,42 @@ export class GameHUD {
|
|||||||
unlockNotificationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
unlockNotificationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.parts = {
|
this.initParts({
|
||||||
buildingsToolbar: new HUDBuildingsToolbar(this.root),
|
buildingsToolbar: HUDBuildingsToolbar,
|
||||||
wiresToolbar: new HUDWiresToolbar(this.root),
|
wiresToolbar: HUDWiresToolbar,
|
||||||
blueprintPlacer: new HUDBlueprintPlacer(this.root),
|
blueprintPlacer: HUDBlueprintPlacer,
|
||||||
buildingPlacer: new HUDBuildingPlacer(this.root),
|
buildingPlacer: HUDBuildingPlacer,
|
||||||
unlockNotification: new HUDUnlockNotification(this.root),
|
unlockNotification: HUDUnlockNotification,
|
||||||
gameMenu: new HUDGameMenu(this.root),
|
gameMenu: HUDGameMenu,
|
||||||
massSelector: new HUDMassSelector(this.root),
|
massSelector: HUDMassSelector,
|
||||||
shop: new HUDShop(this.root),
|
shop: HUDShop,
|
||||||
statistics: new HUDStatistics(this.root),
|
statistics: HUDStatistics,
|
||||||
waypoints: new HUDWaypoints(this.root),
|
waypoints: HUDWaypoints,
|
||||||
wireInfo: new HUDWireInfo(this.root),
|
wireInfo: HUDWireInfo,
|
||||||
leverToggle: new HUDLeverToggle(this.root),
|
leverToggle: HUDLeverToggle,
|
||||||
constantSignalEdit: new HUDConstantSignalEdit(this.root),
|
constantSignalEdit: HUDConstantSignalEdit,
|
||||||
|
|
||||||
// Must always exist
|
// Must always exist
|
||||||
pinnedShapes: new HUDPinnedShapes(this.root),
|
pinnedShapes: HUDPinnedShapes,
|
||||||
notifications: new HUDNotifications(this.root),
|
notifications: HUDNotifications,
|
||||||
settingsMenu: new HUDSettingsMenu(this.root),
|
settingsMenu: HUDSettingsMenu,
|
||||||
debugInfo: new HUDDebugInfo(this.root),
|
debugInfo: HUDDebugInfo,
|
||||||
dialogs: new HUDModalDialogs(this.root),
|
dialogs: HUDModalDialogs,
|
||||||
screenshotExporter: new HUDScreenshotExporter(this.root),
|
screenshotExporter: HUDScreenshotExporter,
|
||||||
shapeViewer: new HUDShapeViewer(this.root),
|
shapeViewer: HUDShapeViewer,
|
||||||
|
|
||||||
wiresOverlay: new HUDWiresOverlay(this.root),
|
wiresOverlay: HUDWiresOverlay,
|
||||||
layerPreview: new HUDLayerPreview(this.root),
|
layerPreview: HUDLayerPreview,
|
||||||
|
|
||||||
minerHighlight: new HUDMinerHighlight(this.root),
|
minerHighlight: HUDMinerHighlight,
|
||||||
tutorialVideoOffer: new HUDTutorialVideoOffer(this.root),
|
tutorialVideoOffer: HUDTutorialVideoOffer,
|
||||||
|
|
||||||
// Typing hints
|
// Typing hints
|
||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
/** @type {HUDChangesDebugger} */
|
/** @type {HUDChangesDebugger} */
|
||||||
changesDebugger: null,
|
changesDebugger: null,
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
};
|
});
|
||||||
|
|
||||||
if (!IS_MOBILE) {
|
if (!IS_MOBILE) {
|
||||||
this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root);
|
this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root);
|
||||||
@ -129,7 +129,7 @@ export class GameHUD {
|
|||||||
this.parts.changesDebugger = new HUDChangesDebugger(this.root);
|
this.parts.changesDebugger = new HUDChangesDebugger(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
if (this.root.gameMode.hasHints() && this.root.app.settings.getAllSettings().offerHints) {
|
||||||
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
||||||
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
|
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
|
||||||
}
|
}
|
||||||
@ -170,6 +170,21 @@ export class GameHUD {
|
|||||||
/* dev:end*/
|
/* dev:end*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {object} parts */
|
||||||
|
initParts(parts) {
|
||||||
|
this.parts = {};
|
||||||
|
|
||||||
|
for (let key in parts) {
|
||||||
|
const Part = parts[key];
|
||||||
|
|
||||||
|
if (!Part || this.root.gameMode.isHudPartExcluded(Part)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parts[key] = new Part(this.root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to close all overlays
|
* Attempts to close all overlays
|
||||||
*/
|
*/
|
||||||
|
@ -153,6 +153,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* Rerenders the whole component
|
* Rerenders the whole component
|
||||||
*/
|
*/
|
||||||
rerenderFull() {
|
rerenderFull() {
|
||||||
|
if (this.root.gameMode.isHudPartHidden(this.constructor.name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const currentGoal = this.root.hubGoals.currentGoal;
|
const currentGoal = this.root.hubGoals.currentGoal;
|
||||||
const currentKey = currentGoal.definition.getHash();
|
const currentKey = currentGoal.definition.getHash();
|
||||||
|
|
||||||
|
@ -100,16 +100,16 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
|
|
||||||
this.directionIndicatorSprite = Loader.getSprite("sprites/misc/hub_direction_indicator.png");
|
this.directionIndicatorSprite = Loader.getSprite("sprites/misc/hub_direction_indicator.png");
|
||||||
|
|
||||||
/** @type {Array<Waypoint>}
|
/** @type {Array<Waypoint>} */
|
||||||
*/
|
this.waypoints = [];
|
||||||
this.waypoints = [
|
if (this.root.gameMode.hasHub()) {
|
||||||
{
|
this.waypoints.push({
|
||||||
label: null,
|
label: null,
|
||||||
center: { x: 0, y: 0 },
|
center: { x: 0, y: 0 },
|
||||||
zoomLevel: 3,
|
zoomLevel: 3,
|
||||||
layer: gMetaBuildingRegistry.findByClass(MetaHubBuilding).getLayer(),
|
layer: gMetaBuildingRegistry.findByClass(MetaHubBuilding).getLayer(),
|
||||||
},
|
});
|
||||||
];
|
}
|
||||||
|
|
||||||
// Create a buffer we can use to measure text
|
// Create a buffer we can use to measure text
|
||||||
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
|
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
|
||||||
|
@ -41,7 +41,14 @@ export class MapChunkView extends MapChunk {
|
|||||||
*/
|
*/
|
||||||
drawBackgroundLayer(parameters) {
|
drawBackgroundLayer(parameters) {
|
||||||
const systems = this.root.systemMgr.systems;
|
const systems = this.root.systemMgr.systems;
|
||||||
|
if (this.root.gameMode.hasZone()) {
|
||||||
|
systems.mapZone.drawChunk(parameters, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.root.gameMode.hasResources()) {
|
||||||
systems.mapResources.drawChunk(parameters, this);
|
systems.mapResources.drawChunk(parameters, this);
|
||||||
|
}
|
||||||
|
|
||||||
systems.beltUnderlays.drawChunk(parameters, this);
|
systems.beltUnderlays.drawChunk(parameters, this);
|
||||||
systems.belt.drawChunk(parameters, this);
|
systems.belt.drawChunk(parameters, this);
|
||||||
}
|
}
|
||||||
|
99
src/js/game/modes/puzzle.js
Normal file
99
src/js/game/modes/puzzle.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { globalConfig } from "../../core/config";
|
||||||
|
import { types } from "../../savegame/serialization";
|
||||||
|
import { HUDPinnedShapes } from "../hud/parts/pinned_shapes";
|
||||||
|
import { enumGameModeTypes, GameMode } from "../game_mode";
|
||||||
|
|
||||||
|
export class PuzzleGameMode extends GameMode {
|
||||||
|
static getType() {
|
||||||
|
return enumGameModeTypes.puzzle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSchema() {
|
||||||
|
return {
|
||||||
|
hiddenHudParts: types.keyValueMap(types.bool),
|
||||||
|
zoneHeight: types.uint,
|
||||||
|
zoneWidth: types.uint,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param {GameRoot} root */
|
||||||
|
constructor(root) {
|
||||||
|
super(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
const data = this.getSaveData();
|
||||||
|
|
||||||
|
this.type = this.getType();
|
||||||
|
this.hiddenHudParts = data.hiddenHudParts || this.getDefaultHiddenHudParts();
|
||||||
|
// this.excludedHudParts = data.hiddenHudParts || this.getDefaultHiddenHudParts();
|
||||||
|
this.zoneHeight = data.zoneHeight || (3 * globalConfig.tileSize);
|
||||||
|
this.zoneWidth = data.zoneWidth || (4 * globalConfig.tileSize);
|
||||||
|
this.boundaryHeight = this.zoneHeight * 2;
|
||||||
|
this.boundaryWidth = this.zoneWidth * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSaveData() {
|
||||||
|
const save = this.root.savegame.getCurrentDump();
|
||||||
|
|
||||||
|
if (!save) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return save.gameMode.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultHiddenHudParts() {
|
||||||
|
return {
|
||||||
|
[HUDPinnedShapes.name]: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
isHudPartHidden(name) {
|
||||||
|
return this.hiddenHudParts[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
hasZone() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasHints() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasHub() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasResources() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasBoundaries() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMinimumZoom() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBoundaryWidth() {
|
||||||
|
return this.boundaryWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBoundaryHeight() {
|
||||||
|
return this.boundaryHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
getZoneWidth() {
|
||||||
|
return this.zoneWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
getZoneHeight() {
|
||||||
|
return this.zoneHeight;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,16 @@
|
|||||||
import { GameMode } from "../game_mode";
|
/* typehints:start */
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
export class PuzzleEditGameMode extends GameMode {
|
import { PuzzleGameMode } from "./puzzle";
|
||||||
|
import { enumGameModeIds } from "../game_mode";
|
||||||
|
|
||||||
|
export class PuzzleEditGameMode extends PuzzleGameMode {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "PuzzleEdit";
|
return enumGameModeIds.puzzleEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import { GameMode } from "../game_mode";
|
/* typehints:start */
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
export class PuzzlePlayGameMode extends GameMode {
|
import { PuzzleGameMode } from "./puzzle";
|
||||||
|
import { enumGameModeIds } from "../game_mode";
|
||||||
|
|
||||||
|
export class PuzzlePlayGameMode extends PuzzleGameMode {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "PuzzlePlay";
|
return enumGameModeIds.puzzlePlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
|
this.initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { findNiceIntegerValue } from "../../core/utils";
|
import { findNiceIntegerValue } from "../../core/utils";
|
||||||
import { GameMode } from "../game_mode";
|
import { enumGameModeIds, enumGameModeTypes, GameMode } from "../game_mode";
|
||||||
import { ShapeDefinition } from "../shape_definition";
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
import { types } from "../../savegame/serialization";
|
import { types } from "../../savegame/serialization";
|
||||||
@ -32,14 +31,13 @@ import { types } from "../../savegame/serialization";
|
|||||||
const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
||||||
const finalGameShape = "RuCw--Cw:----Ru--";
|
const finalGameShape = "RuCw--Cw:----Ru--";
|
||||||
const preparementShape = "CpRpCp--:SwSwSwSw";
|
const preparementShape = "CpRpCp--:SwSwSwSw";
|
||||||
const blueprintShape = "CbCbCbRb:CwCwCwCw";
|
|
||||||
|
|
||||||
// Tiers need % of the previous tier as requirement too
|
// Tiers need % of the previous tier as requirement too
|
||||||
const tierGrowth = 2.5;
|
const tierGrowth = 2.5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates all upgrades
|
* Generates all upgrades
|
||||||
* @returns {Object<string, import("../game_mode").UpgradeTiers>} */
|
* @returns {Object<string, UpgradeTiers>} */
|
||||||
function generateUpgrades(limitedVersion = false) {
|
function generateUpgrades(limitedVersion = false) {
|
||||||
const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1];
|
const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1];
|
||||||
const numEndgameUpgrades = limitedVersion ? 0 : 1000 - fixedImprovements.length - 1;
|
const numEndgameUpgrades = limitedVersion ? 0 : 1000 - fixedImprovements.length - 1;
|
||||||
@ -481,18 +479,16 @@ const demoVersionLevels = generateLevelDefinitions(true);
|
|||||||
|
|
||||||
export class RegularGameMode extends GameMode {
|
export class RegularGameMode extends GameMode {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "Regular";
|
return enumGameModeIds.regular;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSchema() {
|
static getType() {
|
||||||
return {
|
return enumGameModeTypes.default;
|
||||||
test: types.string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
this.test = "test";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,23 +501,6 @@ export class RegularGameMode extends GameMode {
|
|||||||
: demoVersionUpgrades;
|
: demoVersionUpgrades;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Should return whether free play is available or if the game stops
|
|
||||||
* after the predefined levels
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
getIsFreeplayAvailable() {
|
|
||||||
return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the blueprint shape key
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getBlueprintShapeKey() {
|
|
||||||
return blueprintShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the goals for all levels including their reward
|
* Returns the goals for all levels including their reward
|
||||||
* @returns {Array<LevelDefinition>}
|
* @returns {Array<LevelDefinition>}
|
||||||
@ -531,4 +510,13 @@ export class RegularGameMode extends GameMode {
|
|||||||
? fullVersionLevels
|
? fullVersionLevels
|
||||||
: demoVersionLevels;
|
: demoVersionLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return whether free play is available or if the game stops
|
||||||
|
* after the predefined levels
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsFreeplayAvailable() {
|
||||||
|
return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
60
src/js/game/systems/map_zone.js
Normal file
60
src/js/game/systems/map_zone.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
|
import { MapChunkView } from "../map_chunk_view";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { globalConfig } from "../../core/config";
|
||||||
|
import { drawSpriteClipped } from "../../core/draw_utils";
|
||||||
|
import { GameSystem } from "../game_system";
|
||||||
|
import { THEME } from "../theme";
|
||||||
|
|
||||||
|
export class MapZoneSystem extends GameSystem {
|
||||||
|
/**
|
||||||
|
* Draws the map resources
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {MapChunkView} chunk
|
||||||
|
*/
|
||||||
|
drawChunk(parameters, chunk) {
|
||||||
|
const width = this.root.gameMode.getZoneWidth();
|
||||||
|
const height = this.root.gameMode.getZoneHeight();
|
||||||
|
|
||||||
|
const zoneChunkBackground = this.root.buffers.getForKey({
|
||||||
|
key: "mapzonebg",
|
||||||
|
subKey: chunk.renderKey,
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
dpi: 1,
|
||||||
|
redrawMethod: this.generateChunkBackground.bind(this, chunk),
|
||||||
|
});
|
||||||
|
|
||||||
|
parameters.context.imageSmoothingEnabled = false;
|
||||||
|
drawSpriteClipped({
|
||||||
|
parameters,
|
||||||
|
sprite: zoneChunkBackground,
|
||||||
|
x: -width,
|
||||||
|
y: -height,
|
||||||
|
w: this.root.gameMode.getBoundaryWidth(),
|
||||||
|
h: this.root.gameMode.getBoundaryHeight(),
|
||||||
|
originalW: width,
|
||||||
|
originalH: height,
|
||||||
|
});
|
||||||
|
parameters.context.imageSmoothingEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MapChunkView} chunk
|
||||||
|
* @param {HTMLCanvasElement} canvas
|
||||||
|
* @param {CanvasRenderingContext2D} context
|
||||||
|
* @param {number} w
|
||||||
|
* @param {number} h
|
||||||
|
* @param {number} dpi
|
||||||
|
*/
|
||||||
|
generateChunkBackground(chunk, canvas, context, w, h, dpi) {
|
||||||
|
context.clearRect(0, 0, w, h);
|
||||||
|
|
||||||
|
context.fillStyle = THEME.map.zone.background;
|
||||||
|
context.strokeStyle = THEME.map.zone.border;
|
||||||
|
context.fillRect(0, 0, w, h);
|
||||||
|
context.strokeRect(0, 0, w, h);
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,11 @@
|
|||||||
"textColor": "#fff",
|
"textColor": "#fff",
|
||||||
"textColorCapped": "#ef5072",
|
"textColorCapped": "#ef5072",
|
||||||
"background": "rgba(40, 50, 60, 0.8)"
|
"background": "rgba(40, 50, 60, 0.8)"
|
||||||
|
},
|
||||||
|
|
||||||
|
"zone": {
|
||||||
|
"background": "#3e3f47",
|
||||||
|
"border": "#667964"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@
|
|||||||
"textColor": "#fff",
|
"textColor": "#fff",
|
||||||
"textColorCapped": "#ef5072",
|
"textColorCapped": "#ef5072",
|
||||||
"background": "rgba(40, 50, 60, 0.8)"
|
"background": "rgba(40, 50, 60, 0.8)"
|
||||||
|
},
|
||||||
|
|
||||||
|
"zone": {
|
||||||
|
"background": "#fff",
|
||||||
|
"border": "#cbffc4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* time: any,
|
* time: any,
|
||||||
* entityMgr: any,
|
* entityMgr: any,
|
||||||
* map: any,
|
* map: any,
|
||||||
* gameMode: any,
|
* gameMode: object,
|
||||||
* hubGoals: any,
|
* hubGoals: any,
|
||||||
* pinnedShapes: any,
|
* pinnedShapes: any,
|
||||||
* waypoints: any,
|
* waypoints: any,
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
startFileChoose,
|
startFileChoose,
|
||||||
waitNextFrame,
|
waitNextFrame,
|
||||||
} from "../core/utils";
|
} from "../core/utils";
|
||||||
import { gGameModeRegistry } from "../core/global_registries";
|
import { enumGameModeIds } from "../game/game_mode";
|
||||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||||
import { getApplicationSettingById } from "../profile/application_settings";
|
import { getApplicationSettingById } from "../profile/application_settings";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
@ -360,10 +360,9 @@ export class MainMenuState extends GameState {
|
|||||||
|
|
||||||
onPuzzlePlayButtonClicked() {
|
onPuzzlePlayButtonClicked() {
|
||||||
const savegame = this.app.savegameMgr.createNewSavegame();
|
const savegame = this.app.savegameMgr.createNewSavegame();
|
||||||
const gameModeId = gGameModeRegistry.idToEntry.PuzzlePlay.getId();
|
|
||||||
|
|
||||||
this.moveToState("InGameState", {
|
this.moveToState("InGameState", {
|
||||||
gameModeId,
|
gameModeId: enumGameModeIds.puzzlePlay,
|
||||||
savegame,
|
savegame,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user