diff --git a/Readme.md b/Readme.md
index d9a48b4..e962551 100644
--- a/Readme.md
+++ b/Readme.md
@@ -35,13 +35,11 @@ already maxed out.
- [jaceys] A visual indication of whether a ball has hit a brick this serve
- Top down /reach: punishing now, maybe only reset if you hit the lowest populate row of the level, if it's not a full width row
-
-
# Todo before next release
-
-# 29 march 2025
+# Next
+- disabled auto-release on fdroid of every web version, as there's a big delay and bugs woudl stay for a long time
- [jaceys] Counters for coins lost, misses, and boundary bounces, as well as a timer.
- added a white border around all coins, to make dark ones visible on dark bg
- Removed all previous loop only hazards
@@ -66,13 +64,20 @@ already maxed out.
- shocks lvl 2+ make bigger explosions
- Make fullscreen an option and turn it back on when playing
- Made the "combo lost" text last 500ms instead of the pointless 150ms
-
-# 28 march 2025
-
-- loop : added red/blue coins (red kill you, blue freeze puck) (removed later)
-- added more hazard that were then removed
- add a toggle to switch between the “coin” design and colored bubbles
+# 29049575
+
+- added rerolls
+- Sacrifice : clear screen instead of doubling coins
+
+# 29048147
+
+- Ascetism : render coins with red border if there's a combo
+- Warn about unbounded
+- Red border dashes
+
+
# UX / gameplay
- on mobile, relative movement of the touch would be amplified and added to the puck
diff --git a/deploy.sh b/deploy.sh
index 9d39e40..013b60f 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -13,11 +13,12 @@ versionCode=$(($(date +%s) / 60))
bash ./build.sh $versionCode
-# Create a release commit and tag
+# Create a release commit
git add .
git commit -m "Build $versionCode"
-git tag -a $versionCode -m $versionCode
git push
+# Auto tagging created random releases on fdroid, not great.
+# git tag -a $versionCode -m $versionCode
# upload to breakout.lecaro.me
DOMAIN="breakout.lecaro.me"
diff --git a/dist/index.html b/dist/index.html
index 67cc90e..e36eb86 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -76,7 +76,7 @@ body {
color: #90ee90;
}
-#score span.good {
+#score span.good, #score span.bad {
color: #fff;
}
@@ -84,22 +84,6 @@ body {
left: 0;
}
-#FPSDisplay {
- z-index: 1;
- white-space: nowrap;
- pointer-events: none;
- user-select: none;
- opacity: .8;
- color: #fff;
- transform-origin: 0 0;
- padding: 0;
- line-height: 20px;
- position: fixed;
- bottom: 0;
- left: 0;
- transform: rotate(-90deg);
-}
-
body.has-alert-open {
height: auto;
overflow: visible;
@@ -629,6 +613,7 @@ parcelHelpers.export(exports, "brickIndex", ()=>brickIndex);
parcelHelpers.export(exports, "hasBrick", ()=>hasBrick);
parcelHelpers.export(exports, "hitsSomething", ()=>hitsSomething);
parcelHelpers.export(exports, "tick", ()=>tick);
+parcelHelpers.export(exports, "lastMeasuredFPS", ()=>lastMeasuredFPS);
parcelHelpers.export(exports, "openMainMenu", ()=>openMainMenu);
parcelHelpers.export(exports, "confirmRestart", ()=>confirmRestart);
parcelHelpers.export(exports, "setKeyPressed", ()=>setKeyPressed);
@@ -881,10 +866,9 @@ function tick() {
FPSCounter++;
}
let FPSCounter = 0;
-let FPSDisplay = document.getElementById("FPSDisplay");
+let lastMeasuredFPS = 60;
setInterval(()=>{
- if ((0, _options.isOptionOn)("show_fps")) FPSDisplay.innerText = FPSCounter + " FPS " + (0, _gameStateMutators.liveCount)(gameState.coins) + " COINS " + ((0, _gameStateMutators.liveCount)(gameState.particles) + (0, _gameStateMutators.liveCount)(gameState.texts) + (0, _gameStateMutators.liveCount)(gameState.lights)) + " PARTICLES ";
- else FPSDisplay.innerText = "";
+ lastMeasuredFPS = FPSCounter;
FPSCounter = 0;
}, 1000);
window.addEventListener("visibilitychange", ()=>{
@@ -2173,7 +2157,7 @@ function getRowColIndex(gameState, row, col) {
return row * gameState.gridSize + col;
}
function getPossibleUpgrades(gameState) {
- return (0, _loadGameData.upgrades).filter((u)=>gameState.totalScoreAtRunStart >= u.threshold).filter((u)=>!u?.requires || gameState.perks[u?.requires]);
+ return (0, _loadGameData.upgrades).filter((u)=>gameState.totalScoreAtRunStart >= u.threshold || gameState.loop > 0).filter((u)=>!u?.requires || gameState.perks[u?.requires]);
}
function max_levels(gameState) {
return gameState.levelsPerLoop + gameState.perks.extra_levels;
@@ -3549,7 +3533,12 @@ function render(gameState) {
});
else menuLabel.innerText = (0, _i18N.t)("play.menu_label");
const catchRate = gameState.levelSpawnedCoins ? (gameState.levelSpawnedCoins - gameState.levelLostCoins) / gameState.levelSpawnedCoins : 1;
- scoreDisplay.innerHTML = ((0, _options.isOptionOn)('show_stats') ? `
+ scoreDisplay.innerHTML = ((0, _options.isOptionOn)("show_fps") ? `
+
+ ${0, _game.lastMeasuredFPS} FPS
+ /
+
+ ` : '') + ((0, _options.isOptionOn)('show_stats') ? `
${Math.floor(catchRate * 100)}%
/
diff --git a/src/game.less b/src/game.less
index 602a33f..e10657f 100644
--- a/src/game.less
+++ b/src/game.less
@@ -1,10 +1,9 @@
* {
- font-family:
- Courier New,
- Courier,
- Lucida Sans Typewriter,
- Lucida Typewriter,
- monospace;
+ font-family: Courier New,
+ Courier,
+ Lucida Sans Typewriter,
+ Lucida Typewriter,
+ monospace;
box-sizing: border-box;
}
@@ -45,11 +44,13 @@ body {
min-width: 40px;
min-height: 40px;
line-height: 20px;
+
&:hover,
&:focus {
background: rgba(0, 0, 0, 0.3);
cursor: pointer;
}
+
text-shadow: 0 0 4px rgba(0, 0, 0, 0.8);
}
@@ -57,20 +58,25 @@ body {
right: 0;
color: white;
transition: color 0.3s;
+
&.active {
color: gold;
transition: color 0.01s;
}
- span{
+ span {
color: #333;
- &.great{
- color: lightgreen;
- }
- &.good{
- color: white;
- }
+ &.great {
+ color: lightgreen;
+ }
+
+ &.good {
+ color: white;
+ }
+ &.bad {
+ color: white;
+ }
}
}
@@ -78,32 +84,15 @@ body {
left: 0;
}
-#FPSDisplay {
- z-index: 1;
- white-space: nowrap;
- padding: 10px;
- line-height: 20px;
- pointer-events: none;
- user-select: none;
- opacity: 0.8;
-
- color: white;
- padding: 0;
- position: fixed;
-
- bottom: 0;
- left: 0;
- transform-origin: top left;
- transform: rotate(-90deg);
-}
-
body.has-alert-open {
height: auto;
overflow: visible;
}
+
body:not(.has-alert-open) #popup {
display: none;
}
+
#popup {
&::before {
z-index: 10;
@@ -342,6 +331,7 @@ body:not(.has-alert-open) #popup {
}
}
}
+
& > span:not(:hover):not(.active) > span > span {
opacity: 0;
}
@@ -358,6 +348,7 @@ h2.histogram-title strong {
.red-icon {
background: red;
+
img {
filter: saturate(0);
mix-blend-mode: luminosity;
diff --git a/src/game.ts b/src/game.ts
index 88e17db..0d45177 100644
--- a/src/game.ts
+++ b/src/game.ts
@@ -386,21 +386,10 @@ export function tick() {
}
let FPSCounter = 0;
-let FPSDisplay = document.getElementById("FPSDisplay") as HTMLDivElement;
+export let lastMeasuredFPS = 60;
+
setInterval(() => {
- if (isOptionOn("show_fps")) {
- FPSDisplay.innerText =
- FPSCounter +
- " FPS " +
- liveCount(gameState.coins) +
- " COINS " +
- (liveCount(gameState.particles) +
- liveCount(gameState.texts) +
- liveCount(gameState.lights)) +
- " PARTICLES ";
- } else {
- FPSDisplay.innerText = "";
- }
+ lastMeasuredFPS = FPSCounter
FPSCounter = 0;
}, 1000);
diff --git a/src/game_utils.ts b/src/game_utils.ts
index 6872854..0738313 100644
--- a/src/game_utils.ts
+++ b/src/game_utils.ts
@@ -55,7 +55,7 @@ export function getRowColIndex(gameState: GameState, row: number, col: number) {
export function getPossibleUpgrades(gameState: GameState) {
return upgrades
- .filter((u) => gameState.totalScoreAtRunStart >= u.threshold)
+ .filter((u) => gameState.totalScoreAtRunStart >= u.threshold || gameState.loop>0)
.filter((u) => !u?.requires || gameState.perks[u?.requires]);
}
diff --git a/src/render.ts b/src/render.ts
index 5abedd8..dc6582b 100644
--- a/src/render.ts
+++ b/src/render.ts
@@ -11,7 +11,7 @@ import {
} from "./game_utils";
import {colorString, GameState} from "./types";
import {t} from "./i18n/i18n";
-import {gameState} from "./game";
+import {gameState, lastMeasuredFPS} from "./game";
import {isOptionOn} from "./options";
export const gameCanvas = document.getElementById("game") as HTMLCanvasElement;
@@ -54,7 +54,17 @@ export function render(gameState: GameState) {
const catchRate = gameState.levelSpawnedCoins ?
(gameState.levelSpawnedCoins - gameState.levelLostCoins)/gameState.levelSpawnedCoins :1
- scoreDisplay.innerHTML= (isOptionOn('show_stats') ? `
+ scoreDisplay.innerHTML=
+ (isOptionOn("show_fps") ? `
+
+ ${lastMeasuredFPS} FPS
+ /
+
+ `:'')+
+
+
+
+ (isOptionOn('show_stats') ? `
${Math.floor(catchRate*100)}%
/