Refactoring of the key action mapper, allow deselecting buildings, make sure stars always spawn in the start region (closes #7) (closes #9)

pull/33/head
tobspr 4 years ago
parent 1577ebe48c
commit 8760026893

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

@ -375,6 +375,7 @@
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/painter-double.png</key> <key type="filename">sprites/blueprints/painter-double.png</key>
<key type="filename">sprites/blueprints/trash-storage.png</key>
<key type="filename">sprites/buildings/painter-double.png</key> <key type="filename">sprites/buildings/painter-double.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
<key>pivotPoint</key> <key>pivotPoint</key>
@ -475,6 +476,21 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/misc/storage_overlay.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>44,22,89,43</rect>
<key>scale9Paddings</key>
<rect>44,22,89,43</rect>
<key>scale9FromFile</key>
<false/>
</struct>
</map> </map>
<key>fileList</key> <key>fileList</key>
<array> <array>

@ -71,8 +71,8 @@ ingame_HUD_BetaOverlay,
ingame_HUD_UnlockNotification, ingame_HUD_UnlockNotification,
ingame_HUD_Shop, ingame_HUD_Shop,
ingame_HUD_Statistics, ingame_HUD_Statistics,
ingame_HUD_ModalDialogs, ingame_HUD_SettingsMenu,
ingame_HUD_SettingsMenu; ingame_HUD_ModalDialogs;
$zindex: 100; $zindex: 100;

@ -109,7 +109,7 @@
width: 100%; width: 100%;
@include S(height, 50px); @include S(height, 50px);
background: uiResource("get_on_steam.png") center center / contain no-repeat; background: uiResource("get_on_itch_io.svg") center center / contain no-repeat;
overflow: hidden; overflow: hidden;
display: block; display: block;
text-indent: -999em; text-indent: -999em;

@ -5,8 +5,9 @@ export const IS_DEBUG =
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) && (window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
window.location.search.indexOf("nodebug") < 0; window.location.search.indexOf("nodebug") < 0;
// export const IS_DEMO = G_IS_PROD; export const IS_DEMO =
export const IS_DEMO = G_IS_RELEASE; (G_IS_RELEASE && !G_IS_STANDALONE) ||
(typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
const smoothCanvas = true; const smoothCanvas = true;
@ -14,7 +15,8 @@ export const THIRDPARTY_URLS = {
discord: "https://discord.gg/HN7EVzV", discord: "https://discord.gg/HN7EVzV",
github: "https://github.com/tobspr/shapez.io", github: "https://github.com/tobspr/shapez.io",
standaloneStorePage: "https://steam.shapez.io", // standaloneStorePage: "https://steam.shapez.io",
standaloneStorePage: "https://tobspr.itch.io/shapez.io",
}; };
export const globalConfig = { export const globalConfig = {

@ -330,7 +330,7 @@ export class Camera extends BasicSerializableObject {
* Binds the arrow keys * Binds the arrow keys
*/ */
bindKeys() { bindKeys() {
const mapper = this.root.gameState.keyActionMapper; const mapper = this.root.keyMapper;
mapper.getBinding(KEYMAPPINGS.ingame.mapMoveUp).add(() => (this.keyboardForce.y = -1)); mapper.getBinding(KEYMAPPINGS.ingame.mapMoveUp).add(() => (this.keyboardForce.y = -1));
mapper.getBinding(KEYMAPPINGS.ingame.mapMoveDown).add(() => (this.keyboardForce.y = 1)); mapper.getBinding(KEYMAPPINGS.ingame.mapMoveDown).add(() => (this.keyboardForce.y = 1));
mapper.getBinding(KEYMAPPINGS.ingame.mapMoveRight).add(() => (this.keyboardForce.x = 1)); mapper.getBinding(KEYMAPPINGS.ingame.mapMoveRight).add(() => (this.keyboardForce.x = 1));
@ -867,7 +867,7 @@ export class Camera extends BasicSerializableObject {
let forceX = 0; let forceX = 0;
let forceY = 0; let forceY = 0;
const actionMapper = this.root.gameState.keyActionMapper; const actionMapper = this.root.keyMapper;
if (actionMapper.getBinding(KEYMAPPINGS.ingame.mapMoveUp).currentlyDown) { if (actionMapper.getBinding(KEYMAPPINGS.ingame.mapMoveUp).currentlyDown) {
forceY -= 1; forceY -= 1;
} }

@ -75,6 +75,7 @@ export class GameCore {
// Construct the root element, this is the data representation of the game // Construct the root element, this is the data representation of the game
this.root = new GameRoot(this.app); this.root = new GameRoot(this.app);
this.root.gameState = parentState; this.root.gameState = parentState;
this.root.keyMapper = parentState.keyActionMapper;
this.root.savegame = savegame; this.root.savegame = savegame;
this.root.gameWidth = this.app.screenWidth; this.root.gameWidth = this.app.screenWidth;
this.root.gameHeight = this.app.screenHeight; this.root.gameHeight = this.app.screenHeight;
@ -86,7 +87,7 @@ export class GameCore {
const root = this.root; const root = this.root;
// This isn't nice, but we need it right here // This isn't nice, but we need it right here
root.gameState.keyActionMapper = new KeyActionMapper(root, this.root.gameState.inputReciever); root.keyMapper = new KeyActionMapper(root, this.root.gameState.inputReciever);
// Needs to come first // Needs to come first
root.dynamicTickrate = new DynamicTickrate(root); root.dynamicTickrate = new DynamicTickrate(root);

@ -141,10 +141,7 @@ export class BaseHUDPart {
* @param {KeyActionMapper} sourceMapper * @param {KeyActionMapper} sourceMapper
*/ */
forwardGameSpeedKeybindings(sourceMapper) { forwardGameSpeedKeybindings(sourceMapper) {
sourceMapper.forward(this.root.gameState.keyActionMapper, [ sourceMapper.forward(this.root.keyMapper, ["gamespeed_pause", "gamespeed_fastforward"]);
"gamespeed_pause",
"gamespeed_fastforward",
]);
} }
/** /**
@ -153,7 +150,7 @@ export class BaseHUDPart {
* @param {KeyActionMapper} sourceMapper * @param {KeyActionMapper} sourceMapper
*/ */
forwardMapMovementKeybindings(sourceMapper) { forwardMapMovementKeybindings(sourceMapper) {
sourceMapper.forward(this.root.gameState.keyActionMapper, [ sourceMapper.forward(this.root.keyMapper, [
"mapMoveUp", "mapMoveUp",
"mapMoveRight", "mapMoveRight",
"mapMoveDown", "mapMoveDown",

@ -97,7 +97,7 @@ export class GameHUD {
} }
this.internalInitSignalConnections(); this.internalInitSignalConnections();
this.root.gameState.keyActionMapper.getBinding(KEYMAPPINGS.ingame.toggleHud).add(this.toggleUi, this); this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleHud).add(this.toggleUi, this);
} }
/** /**

@ -30,7 +30,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
/** @type {Entity} */ /** @type {Entity} */
this.fakeEntity = null; this.fakeEntity = null;
const keyActionMapper = this.root.gameState.keyActionMapper; const keyActionMapper = this.root.keyMapper;
keyActionMapper keyActionMapper
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement) .getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
.add(this.abortPlacement, this); .add(this.abortPlacement, this);
@ -284,9 +284,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id].name; this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id].name;
this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id].description; this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id].description;
const binding = this.root.gameState.keyActionMapper.getBinding( const binding = this.root.keyMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]);
KEYMAPPINGS.buildings[metaBuilding.getId()]
);
this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace( this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace(
"<key>", "<key>",
"<code class='keybinding'>" + binding.getKeyCodeString() + "</code>" "<code class='keybinding'>" + binding.getKeyCodeString() + "</code>"
@ -327,7 +325,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
T.ingame.buildingPlacement.cycleBuildingVariants.replace( T.ingame.buildingPlacement.cycleBuildingVariants.replace(
"<key>", "<key>",
"<code class='keybinding'>" + "<code class='keybinding'>" +
this.root.gameState.keyActionMapper this.root.keyMapper
.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants) .getBinding(KEYMAPPINGS.placement.cycleBuildingVariants)
.getKeyCodeString() + .getKeyCodeString() +
"</code>" "</code>"

@ -60,7 +60,7 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
} }
initialize() { initialize() {
const actionMapper = this.root.gameState.keyActionMapper; const actionMapper = this.root.keyMapper;
const items = makeDiv(this.element, null, ["buildings"]); const items = makeDiv(this.element, null, ["buildings"]);
@ -143,6 +143,15 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
return; return;
} }
// Allow clicking an item again to deselect it
for (const buildingId in this.buildingHandles) {
const handle = this.buildingHandles[buildingId];
if (handle.selected && handle.metaBuilding === metaBuilding) {
metaBuilding = null;
break;
}
}
this.root.soundProxy.playUiClick(); this.root.soundProxy.playUiClick();
this.sigBuildingSelected.dispatch(metaBuilding); this.sigBuildingSelected.dispatch(metaBuilding);
this.onSelectedPlacementBuildingChanged(metaBuilding); this.onSelectedPlacementBuildingChanged(metaBuilding);

@ -1,6 +1,7 @@
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { makeDiv, round3Digits, round2Digits } from "../../../core/utils"; import { makeDiv, round3Digits, round2Digits } from "../../../core/utils";
import { Math_round } from "../../../core/builtins"; import { Math_round } from "../../../core/builtins";
import { DynamicDomAttach } from "../dynamic_dom_attach";
export class HUDDebugInfo extends BaseHUDPart { export class HUDDebugInfo extends BaseHUDPart {
createElements(parent) { createElements(parent) {
@ -13,6 +14,11 @@ export class HUDDebugInfo extends BaseHUDPart {
initialize() { initialize() {
this.lastTick = 0; this.lastTick = 0;
this.visible = false;
this.domAttach = new DynamicDomAttach(this.root, this.element);
// this.root.keyMapper
} }
update() { update() {

@ -47,7 +47,7 @@ export class HUDGameMenu extends BaseHUDPart {
this.trackClicks(button, handler); this.trackClicks(button, handler);
if (keybinding) { if (keybinding) {
const binding = this.root.gameState.keyActionMapper.getBinding(keybinding); const binding = this.root.keyMapper.getBinding(keybinding);
binding.add(handler); binding.add(handler);
binding.appendLabelToElement(button); binding.appendLabelToElement(button);
} }

@ -20,7 +20,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
} }
createElements(parent) { createElements(parent) {
const mapper = this.root.gameState.keyActionMapper; const mapper = this.root.keyMapper;
const getKeycode = id => { const getKeycode = id => {
return getStringForKeyCode(mapper.getBinding(id).keyCode); return getStringForKeyCode(mapper.getBinding(id).keyCode);

@ -16,12 +16,10 @@ const logger = createLogger("hud/mass_selector");
export class HUDMassSelector extends BaseHUDPart { export class HUDMassSelector extends BaseHUDPart {
createElements(parent) { createElements(parent) {
const removalKeybinding = this.root.gameState.keyActionMapper const removalKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete) .getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.getKeyCodeString(); .getKeyCodeString();
const abortKeybinding = this.root.gameState.keyActionMapper const abortKeybinding = this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).getKeyCodeString();
.getBinding(KEYMAPPINGS.general.back)
.getKeyCodeString();
this.element = makeDiv( this.element = makeDiv(
parent, parent,
@ -46,8 +44,8 @@ export class HUDMassSelector extends BaseHUDPart {
this.root.camera.movePreHandler.add(this.onMouseMove, this); this.root.camera.movePreHandler.add(this.onMouseMove, this);
this.root.camera.upPostHandler.add(this.onMouseUp, this); this.root.camera.upPostHandler.add(this.onMouseUp, this);
this.root.gameState.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this); this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this);
this.root.gameState.keyActionMapper this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete) .getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.add(this.confirmDelete, this); .add(this.confirmDelete, this);

@ -7,6 +7,7 @@ import { T } from "../../../translations";
import { StaticMapEntityComponent } from "../../components/static_map_entity"; import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { ItemProcessorComponent } from "../../components/item_processor"; import { ItemProcessorComponent } from "../../components/item_processor";
import { BeltComponent } from "../../components/belt"; import { BeltComponent } from "../../components/belt";
import { IS_DEMO } from "../../../core/config";
export class HUDSettingsMenu extends BaseHUDPart { export class HUDSettingsMenu extends BaseHUDPart {
createElements(parent) { createElements(parent) {
@ -56,7 +57,16 @@ export class HUDSettingsMenu extends BaseHUDPart {
} }
returnToMenu() { returnToMenu() {
this.root.gameState.goBackToMenu(); if (IS_DEMO) {
const { cancel, deleteGame } = this.root.hud.parts.dialogs.showWarning(
T.dialogs.leaveNotPossibleInDemo.title,
T.dialogs.leaveNotPossibleInDemo.desc,
["cancel:good", "deleteGame:bad"]
);
deleteGame.add(() => this.root.gameState.goBackToMenu());
} else {
this.root.gameState.goBackToMenu();
}
} }
goToSettings() { goToSettings() {
@ -72,7 +82,7 @@ export class HUDSettingsMenu extends BaseHUDPart {
} }
initialize() { initialize() {
this.root.gameState.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.show, this); this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.show, this);
this.domAttach = new DynamicDomAttach(this.root, this.background, { this.domAttach = new DynamicDomAttach(this.root, this.background, {
attachClass: "visible", attachClass: "visible",

@ -31,6 +31,7 @@ export const KEYMAPPINGS = {
menuOpenStats: { keyCode: key("G") }, menuOpenStats: { keyCode: key("G") },
toggleHud: { keyCode: 113 }, // F2 toggleHud: { keyCode: 113 }, // F2
toggleFPSInfo: { keyCode: 112 }, // F1
}, },
buildings: { buildings: {
@ -362,7 +363,7 @@ export class KeyActionMapper {
for (const key in this.keybindings) { for (const key in this.keybindings) {
/** @type {Keybinding} */ /** @type {Keybinding} */
const binding = this.keybindings[key]; const binding = this.keybindings[key];
if (binding.keyCode === keyCode /* && binding.shift === shift && binding.alt === alt */) { if (binding.keyCode === keyCode && !binding.currentlyDown) {
binding.currentlyDown = true; binding.currentlyDown = true;
/** @type {Signal} */ /** @type {Signal} */

@ -163,17 +163,17 @@ export class MapChunk {
[enumSubShape.windmill]: Math_round(6 + clamp(distanceToOriginInChunks / 2, 0, 20)), [enumSubShape.windmill]: Math_round(6 + clamp(distanceToOriginInChunks / 2, 0, 20)),
}; };
if (distanceToOriginInChunks < 4) { if (distanceToOriginInChunks < 7) {
// Initial chunks can not spawn the good stuff // Initial chunks can not spawn the good stuff
weights[enumSubShape.star] = 0; weights[enumSubShape.star] = 0;
weights[enumSubShape.windmill] = 0; weights[enumSubShape.windmill] = 0;
} }
if (distanceToOriginInChunks < 7) { if (distanceToOriginInChunks < 10) {
// Initial chunk patches always have the same shape // Initial chunk patches always have the same shape
const subShape = this.internalGenerateRandomSubShape(rng, weights); const subShape = this.internalGenerateRandomSubShape(rng, weights);
subShapes = [subShape, subShape, subShape, subShape]; subShapes = [subShape, subShape, subShape, subShape];
} else if (distanceToOriginInChunks < 17) { } else if (distanceToOriginInChunks < 15) {
// Later patches can also have mixed ones // Later patches can also have mixed ones
const subShapeA = this.internalGenerateRandomSubShape(rng, weights); const subShapeA = this.internalGenerateRandomSubShape(rng, weights);
const subShapeB = this.internalGenerateRandomSubShape(rng, weights); const subShapeB = this.internalGenerateRandomSubShape(rng, weights);
@ -269,22 +269,12 @@ export class MapChunk {
return true; return true;
} }
if (this.x === -1 && this.y === 0) { if (this.x === -1 && this.y === 0) {
const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes([ const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("CuCuCuCu");
enumSubShape.circle,
enumSubShape.circle,
enumSubShape.circle,
enumSubShape.circle,
]);
this.internalGeneratePatch(rng, 2, new ShapeItem(definition), globalConfig.mapChunkSize - 9, 7); this.internalGeneratePatch(rng, 2, new ShapeItem(definition), globalConfig.mapChunkSize - 9, 7);
return true; return true;
} }
if (this.x === 0 && this.y === -1) { if (this.x === 0 && this.y === -1) {
const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes([ const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("RuRuRuRu");
enumSubShape.rect,
enumSubShape.rect,
enumSubShape.rect,
enumSubShape.rect,
]);
this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7); this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7);
return true; return true;
} }
@ -294,6 +284,12 @@ export class MapChunk {
return true; return true;
} }
if (this.x === 5 && this.y === -2) {
const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("SuSuSuSu");
this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7);
return true;
}
return false; return false;
} }

@ -27,6 +27,7 @@ import { Entity } from "./entity";
import { ShapeDefinition } from "./shape_definition"; import { ShapeDefinition } from "./shape_definition";
import { BaseItem } from "./base_item"; import { BaseItem } from "./base_item";
import { DynamicTickrate } from "./dynamic_tickrate"; import { DynamicTickrate } from "./dynamic_tickrate";
import { KeyActionMapper } from "./key_action_mapper";
/* typehints:end */ /* typehints:end */
const logger = createLogger("game/root"); const logger = createLogger("game/root");
@ -50,6 +51,9 @@ export class GameRoot {
/** @type {InGameState} */ /** @type {InGameState} */
this.gameState = null; this.gameState = null;
/** @type {KeyActionMapper} */
this.keyMapper = null;
// Store game dimensions // Store game dimensions
this.gameWidth = 500; this.gameWidth = 500;
this.gameHeight = 500; this.gameHeight = 500;

@ -194,8 +194,7 @@ export class MainMenuState extends GameState {
onSteamLinkClicked(event) { onSteamLinkClicked(event) {
this.app.analytics.trackUiClick("main_menu_steam_link"); this.app.analytics.trackUiClick("main_menu_steam_link");
alert("The steam version will launch very soon! (Planned date: Begin of June 2020)"); window.open(THIRDPARTY_URLS.standaloneStorePage);
// window.open("https://steam.shapez.io");
event.preventDefault(); event.preventDefault();
return false; return false;
} }

@ -59,7 +59,7 @@ demoBanners:
# This is the "advertisement" shown in the main menu and other various places # This is the "advertisement" shown in the main menu and other various places
title: This is a demo version title: This is a demo version
intro: >- intro: >-
Get <strong>shapez.io on steam</strong> to: Get the <strong>shapez.io standalone</strong> to:
advantages: advantages:
- Save and resume your games. - Save and resume your games.
- No advertisements. - No advertisements.
@ -84,6 +84,7 @@ dialogs:
restart: Restart restart: Restart
reset: Reset reset: Reset
getStandalone: Get Standalone getStandalone: Get Standalone
deleteGame: Delete Progress
importSavegameError: importSavegameError:
title: Import Error title: Import Error
@ -134,6 +135,10 @@ dialogs:
saveNotPossibleInDemo: saveNotPossibleInDemo:
desc: Your game has been saved, but restoring it is only possible in the standalone version. Consider to get the standalone for the full experience! desc: Your game has been saved, but restoring it is only possible in the standalone version. Consider to get the standalone for the full experience!
leaveNotPossibleInDemo:
title: Saving not possible
desc: You can not save in the demo. Your game will be lost. Are you sure?
ingame: ingame:
# This is shown in the top left corner and displays useful keybindings in # This is shown in the top left corner and displays useful keybindings in
# every situation # every situation

Loading…
Cancel
Save