diff --git a/artwork/buildings/buildings_2x2.psd b/artwork/buildings/buildings_2x2.psd
index 027486dd..1bb23259 100644
Binary files a/artwork/buildings/buildings_2x2.psd and b/artwork/buildings/buildings_2x2.psd differ
diff --git a/artwork/itch.io/background.jpg b/artwork/itch.io/background.jpg
new file mode 100644
index 00000000..619876a2
Binary files /dev/null and b/artwork/itch.io/background.jpg differ
diff --git a/artwork/itch.io/background.png b/artwork/itch.io/background.png
new file mode 100644
index 00000000..674b7fab
Binary files /dev/null and b/artwork/itch.io/background.png differ
diff --git a/artwork/itch.io/banner.png b/artwork/itch.io/banner.png
new file mode 100644
index 00000000..bff1dc6c
Binary files /dev/null and b/artwork/itch.io/banner.png differ
diff --git a/artwork/itch.io/banner.psd b/artwork/itch.io/banner.psd
new file mode 100644
index 00000000..6fb9ef3c
Binary files /dev/null and b/artwork/itch.io/banner.psd differ
diff --git a/artwork/logo.png b/artwork/logo.png
new file mode 100644
index 00000000..14141d58
Binary files /dev/null and b/artwork/logo.png differ
diff --git a/artwork/steam/screenshots/9.png b/artwork/steam/screenshots/9.png
index 9bf9534f..376ee4e4 100644
Binary files a/artwork/steam/screenshots/9.png and b/artwork/steam/screenshots/9.png differ
diff --git a/res/ui/get_on_itch_io.svg b/res/ui/get_on_itch_io.svg
new file mode 100644
index 00000000..f6dde21e
--- /dev/null
+++ b/res/ui/get_on_itch_io.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps
index 0190d204..883a6932 100644
--- a/res_raw/atlas.tps
+++ b/res_raw/atlas.tps
@@ -375,6 +375,7 @@
sprites/blueprints/painter-double.png
+ sprites/blueprints/trash-storage.png
sprites/buildings/painter-double.png
pivotPoint
@@ -475,6 +476,21 @@
scale9FromFile
+ sprites/misc/storage_overlay.png
+
+ pivotPoint
+ 0.5,0.5
+ spriteScale
+ 1
+ scale9Enabled
+
+ scale9Borders
+ 44,22,89,43
+ scale9Paddings
+ 44,22,89,43
+ scale9FromFile
+
+
fileList
diff --git a/src/css/main.scss b/src/css/main.scss
index e4ee1b24..2d3f6857 100644
--- a/src/css/main.scss
+++ b/src/css/main.scss
@@ -71,8 +71,8 @@ ingame_HUD_BetaOverlay,
ingame_HUD_UnlockNotification,
ingame_HUD_Shop,
ingame_HUD_Statistics,
-ingame_HUD_ModalDialogs,
-ingame_HUD_SettingsMenu;
+ingame_HUD_SettingsMenu,
+ingame_HUD_ModalDialogs;
$zindex: 100;
diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss
index 42f24c15..553fd960 100644
--- a/src/css/states/main_menu.scss
+++ b/src/css/states/main_menu.scss
@@ -109,7 +109,7 @@
width: 100%;
@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;
display: block;
text-indent: -999em;
diff --git a/src/js/core/config.js b/src/js/core/config.js
index 31ced8c2..04c7b1a3 100644
--- a/src/js/core/config.js
+++ b/src/js/core/config.js
@@ -5,8 +5,9 @@ export const IS_DEBUG =
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
window.location.search.indexOf("nodebug") < 0;
-// export const IS_DEMO = G_IS_PROD;
-export const IS_DEMO = G_IS_RELEASE;
+export const IS_DEMO =
+ (G_IS_RELEASE && !G_IS_STANDALONE) ||
+ (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
const smoothCanvas = true;
@@ -14,7 +15,8 @@ export const THIRDPARTY_URLS = {
discord: "https://discord.gg/HN7EVzV",
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 = {
diff --git a/src/js/game/camera.js b/src/js/game/camera.js
index 671f3b6e..99df0675 100644
--- a/src/js/game/camera.js
+++ b/src/js/game/camera.js
@@ -330,7 +330,7 @@ export class Camera extends BasicSerializableObject {
* Binds the arrow keys
*/
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.mapMoveDown).add(() => (this.keyboardForce.y = 1));
mapper.getBinding(KEYMAPPINGS.ingame.mapMoveRight).add(() => (this.keyboardForce.x = 1));
@@ -867,7 +867,7 @@ export class Camera extends BasicSerializableObject {
let forceX = 0;
let forceY = 0;
- const actionMapper = this.root.gameState.keyActionMapper;
+ const actionMapper = this.root.keyMapper;
if (actionMapper.getBinding(KEYMAPPINGS.ingame.mapMoveUp).currentlyDown) {
forceY -= 1;
}
diff --git a/src/js/game/core.js b/src/js/game/core.js
index 73346504..3d2c1f3d 100644
--- a/src/js/game/core.js
+++ b/src/js/game/core.js
@@ -75,6 +75,7 @@ export class GameCore {
// Construct the root element, this is the data representation of the game
this.root = new GameRoot(this.app);
this.root.gameState = parentState;
+ this.root.keyMapper = parentState.keyActionMapper;
this.root.savegame = savegame;
this.root.gameWidth = this.app.screenWidth;
this.root.gameHeight = this.app.screenHeight;
@@ -86,7 +87,7 @@ export class GameCore {
const root = this.root;
// 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
root.dynamicTickrate = new DynamicTickrate(root);
diff --git a/src/js/game/hud/base_hud_part.js b/src/js/game/hud/base_hud_part.js
index a700a6b3..032530fb 100644
--- a/src/js/game/hud/base_hud_part.js
+++ b/src/js/game/hud/base_hud_part.js
@@ -141,10 +141,7 @@ export class BaseHUDPart {
* @param {KeyActionMapper} sourceMapper
*/
forwardGameSpeedKeybindings(sourceMapper) {
- sourceMapper.forward(this.root.gameState.keyActionMapper, [
- "gamespeed_pause",
- "gamespeed_fastforward",
- ]);
+ sourceMapper.forward(this.root.keyMapper, ["gamespeed_pause", "gamespeed_fastforward"]);
}
/**
@@ -153,7 +150,7 @@ export class BaseHUDPart {
* @param {KeyActionMapper} sourceMapper
*/
forwardMapMovementKeybindings(sourceMapper) {
- sourceMapper.forward(this.root.gameState.keyActionMapper, [
+ sourceMapper.forward(this.root.keyMapper, [
"mapMoveUp",
"mapMoveRight",
"mapMoveDown",
diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js
index cb591687..b66c85e3 100644
--- a/src/js/game/hud/hud.js
+++ b/src/js/game/hud/hud.js
@@ -97,7 +97,7 @@ export class GameHUD {
}
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);
}
/**
diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js
index 8c83f17d..a581a0b3 100644
--- a/src/js/game/hud/parts/building_placer.js
+++ b/src/js/game/hud/parts/building_placer.js
@@ -30,7 +30,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
/** @type {Entity} */
this.fakeEntity = null;
- const keyActionMapper = this.root.gameState.keyActionMapper;
+ const keyActionMapper = this.root.keyMapper;
keyActionMapper
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
.add(this.abortPlacement, this);
@@ -284,9 +284,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id].name;
this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id].description;
- const binding = this.root.gameState.keyActionMapper.getBinding(
- KEYMAPPINGS.buildings[metaBuilding.getId()]
- );
+ const binding = this.root.keyMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]);
this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace(
"",
"" + binding.getKeyCodeString() + "
"
@@ -327,7 +325,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
T.ingame.buildingPlacement.cycleBuildingVariants.replace(
"",
"" +
- this.root.gameState.keyActionMapper
+ this.root.keyMapper
.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants)
.getKeyCodeString() +
"
"
diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js
index f7a21a1b..86c99a01 100644
--- a/src/js/game/hud/parts/buildings_toolbar.js
+++ b/src/js/game/hud/parts/buildings_toolbar.js
@@ -60,7 +60,7 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
}
initialize() {
- const actionMapper = this.root.gameState.keyActionMapper;
+ const actionMapper = this.root.keyMapper;
const items = makeDiv(this.element, null, ["buildings"]);
@@ -143,6 +143,15 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
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.sigBuildingSelected.dispatch(metaBuilding);
this.onSelectedPlacementBuildingChanged(metaBuilding);
diff --git a/src/js/game/hud/parts/debug_info.js b/src/js/game/hud/parts/debug_info.js
index 745fbbd5..59a1d98e 100644
--- a/src/js/game/hud/parts/debug_info.js
+++ b/src/js/game/hud/parts/debug_info.js
@@ -1,6 +1,7 @@
import { BaseHUDPart } from "../base_hud_part";
import { makeDiv, round3Digits, round2Digits } from "../../../core/utils";
import { Math_round } from "../../../core/builtins";
+import { DynamicDomAttach } from "../dynamic_dom_attach";
export class HUDDebugInfo extends BaseHUDPart {
createElements(parent) {
@@ -13,6 +14,11 @@ export class HUDDebugInfo extends BaseHUDPart {
initialize() {
this.lastTick = 0;
+
+ this.visible = false;
+ this.domAttach = new DynamicDomAttach(this.root, this.element);
+
+ // this.root.keyMapper
}
update() {
diff --git a/src/js/game/hud/parts/game_menu.js b/src/js/game/hud/parts/game_menu.js
index 86ad2564..b71adff4 100644
--- a/src/js/game/hud/parts/game_menu.js
+++ b/src/js/game/hud/parts/game_menu.js
@@ -47,7 +47,7 @@ export class HUDGameMenu extends BaseHUDPart {
this.trackClicks(button, handler);
if (keybinding) {
- const binding = this.root.gameState.keyActionMapper.getBinding(keybinding);
+ const binding = this.root.keyMapper.getBinding(keybinding);
binding.add(handler);
binding.appendLabelToElement(button);
}
diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js
index a1a941dc..6f6040b6 100644
--- a/src/js/game/hud/parts/keybinding_overlay.js
+++ b/src/js/game/hud/parts/keybinding_overlay.js
@@ -20,7 +20,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
}
createElements(parent) {
- const mapper = this.root.gameState.keyActionMapper;
+ const mapper = this.root.keyMapper;
const getKeycode = id => {
return getStringForKeyCode(mapper.getBinding(id).keyCode);
diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js
index 3dca5678..ddcf9117 100644
--- a/src/js/game/hud/parts/mass_selector.js
+++ b/src/js/game/hud/parts/mass_selector.js
@@ -16,12 +16,10 @@ const logger = createLogger("hud/mass_selector");
export class HUDMassSelector extends BaseHUDPart {
createElements(parent) {
- const removalKeybinding = this.root.gameState.keyActionMapper
+ const removalKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.getKeyCodeString();
- const abortKeybinding = this.root.gameState.keyActionMapper
- .getBinding(KEYMAPPINGS.general.back)
- .getKeyCodeString();
+ const abortKeybinding = this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).getKeyCodeString();
this.element = makeDiv(
parent,
@@ -46,8 +44,8 @@ export class HUDMassSelector extends BaseHUDPart {
this.root.camera.movePreHandler.add(this.onMouseMove, this);
this.root.camera.upPostHandler.add(this.onMouseUp, this);
- this.root.gameState.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this);
- this.root.gameState.keyActionMapper
+ this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this);
+ this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.add(this.confirmDelete, this);
diff --git a/src/js/game/hud/parts/settings_menu.js b/src/js/game/hud/parts/settings_menu.js
index 4acc04b1..28ceb9ff 100644
--- a/src/js/game/hud/parts/settings_menu.js
+++ b/src/js/game/hud/parts/settings_menu.js
@@ -7,6 +7,7 @@ import { T } from "../../../translations";
import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { ItemProcessorComponent } from "../../components/item_processor";
import { BeltComponent } from "../../components/belt";
+import { IS_DEMO } from "../../../core/config";
export class HUDSettingsMenu extends BaseHUDPart {
createElements(parent) {
@@ -56,7 +57,16 @@ export class HUDSettingsMenu extends BaseHUDPart {
}
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() {
@@ -72,7 +82,7 @@ export class HUDSettingsMenu extends BaseHUDPart {
}
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, {
attachClass: "visible",
diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js
index 6aff0e88..eab0f408 100644
--- a/src/js/game/key_action_mapper.js
+++ b/src/js/game/key_action_mapper.js
@@ -31,6 +31,7 @@ export const KEYMAPPINGS = {
menuOpenStats: { keyCode: key("G") },
toggleHud: { keyCode: 113 }, // F2
+ toggleFPSInfo: { keyCode: 112 }, // F1
},
buildings: {
@@ -362,7 +363,7 @@ export class KeyActionMapper {
for (const key in this.keybindings) {
/** @type {Keybinding} */
const binding = this.keybindings[key];
- if (binding.keyCode === keyCode /* && binding.shift === shift && binding.alt === alt */) {
+ if (binding.keyCode === keyCode && !binding.currentlyDown) {
binding.currentlyDown = true;
/** @type {Signal} */
diff --git a/src/js/game/map_chunk.js b/src/js/game/map_chunk.js
index f51f63a0..bffaf9e8 100644
--- a/src/js/game/map_chunk.js
+++ b/src/js/game/map_chunk.js
@@ -163,17 +163,17 @@ export class MapChunk {
[enumSubShape.windmill]: Math_round(6 + clamp(distanceToOriginInChunks / 2, 0, 20)),
};
- if (distanceToOriginInChunks < 4) {
+ if (distanceToOriginInChunks < 7) {
// Initial chunks can not spawn the good stuff
weights[enumSubShape.star] = 0;
weights[enumSubShape.windmill] = 0;
}
- if (distanceToOriginInChunks < 7) {
+ if (distanceToOriginInChunks < 10) {
// Initial chunk patches always have the same shape
const subShape = this.internalGenerateRandomSubShape(rng, weights);
subShapes = [subShape, subShape, subShape, subShape];
- } else if (distanceToOriginInChunks < 17) {
+ } else if (distanceToOriginInChunks < 15) {
// Later patches can also have mixed ones
const subShapeA = this.internalGenerateRandomSubShape(rng, weights);
const subShapeB = this.internalGenerateRandomSubShape(rng, weights);
@@ -269,22 +269,12 @@ export class MapChunk {
return true;
}
if (this.x === -1 && this.y === 0) {
- const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes([
- enumSubShape.circle,
- enumSubShape.circle,
- enumSubShape.circle,
- enumSubShape.circle,
- ]);
+ const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("CuCuCuCu");
this.internalGeneratePatch(rng, 2, new ShapeItem(definition), globalConfig.mapChunkSize - 9, 7);
return true;
}
if (this.x === 0 && this.y === -1) {
- const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes([
- enumSubShape.rect,
- enumSubShape.rect,
- enumSubShape.rect,
- enumSubShape.rect,
- ]);
+ const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("RuRuRuRu");
this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7);
return true;
}
@@ -294,6 +284,12 @@ export class MapChunk {
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;
}
diff --git a/src/js/game/root.js b/src/js/game/root.js
index f73f9a9d..0c4e6792 100644
--- a/src/js/game/root.js
+++ b/src/js/game/root.js
@@ -27,6 +27,7 @@ import { Entity } from "./entity";
import { ShapeDefinition } from "./shape_definition";
import { BaseItem } from "./base_item";
import { DynamicTickrate } from "./dynamic_tickrate";
+import { KeyActionMapper } from "./key_action_mapper";
/* typehints:end */
const logger = createLogger("game/root");
@@ -50,6 +51,9 @@ export class GameRoot {
/** @type {InGameState} */
this.gameState = null;
+ /** @type {KeyActionMapper} */
+ this.keyMapper = null;
+
// Store game dimensions
this.gameWidth = 500;
this.gameHeight = 500;
diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js
index cb93156b..48c42041 100644
--- a/src/js/states/main_menu.js
+++ b/src/js/states/main_menu.js
@@ -194,8 +194,7 @@ export class MainMenuState extends GameState {
onSteamLinkClicked(event) {
this.app.analytics.trackUiClick("main_menu_steam_link");
- alert("The steam version will launch very soon! (Planned date: Begin of June 2020)");
- // window.open("https://steam.shapez.io");
+ window.open(THIRDPARTY_URLS.standaloneStorePage);
event.preventDefault();
return false;
}
diff --git a/translations/base-en.yaml b/translations/base-en.yaml
index 37f111b1..d8e5373a 100644
--- a/translations/base-en.yaml
+++ b/translations/base-en.yaml
@@ -59,7 +59,7 @@ demoBanners:
# This is the "advertisement" shown in the main menu and other various places
title: This is a demo version
intro: >-
- Get shapez.io on steam to:
+ Get the shapez.io standalone to:
advantages:
- Save and resume your games.
- No advertisements.
@@ -84,6 +84,7 @@ dialogs:
restart: Restart
reset: Reset
getStandalone: Get Standalone
+ deleteGame: Delete Progress
importSavegameError:
title: Import Error
@@ -134,6 +135,10 @@ dialogs:
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!
+ leaveNotPossibleInDemo:
+ title: Saving not possible
+ desc: You can not save in the demo. Your game will be lost. Are you sure?
+
ingame:
# This is shown in the top left corner and displays useful keybindings in
# every situation