This commit is contained in:
Renan LE CARO 2025-05-03 16:42:03 +02:00
parent ca1c75a5a1
commit 94ffb80f49
19 changed files with 186 additions and 73 deletions

View file

@ -13,25 +13,27 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
# Changelog # Changelog
## To do ## To do
- +1 upgrade per gold medal, but they are all applied to the selected perk
## Done ## Done
- reworked level up screen :
- when you earn multiple upgrade points, they all need to be put on the same perk - bigger "level X / Y cleared"
- wait for bricks to respawn before leveling up - upgardes need to all be spent on the same list of perks (to avoid reading too much)
- creative mode : removed tooltips for perks as they were getting in the way on mobile - instead of rerolls, you get a longer list of choices to pick from with gold medals
- unlocked upgrades and levels : split item description (with tooltip) and "try" button - clarified challenges, only show them when you pass one of them
- unlocked level: removed progress bars as there's no real progress
- bigger "level X of Y cleared"
- clarify challenges but only show them when you pass one of them
- removed the "sides bounce" challenge, bouncing on sides shouldn't be punished - removed the "sides bounce" challenge, bouncing on sides shouldn't be punished
- upgrades list now uses numbers instead of bars, looks better with limitless - once you reach high score of 1000, level unlock hints appear, and required / forbidden upgrades and colored gold/red
- somehow score clicks didn't register while the game was playing, that's solved - added tooltip on most items on that screen, that can be triggered on mobile by tapping the text
- Fix : click tooltip to open on mobile, click anywhere to close
- Can't press help buttons in Creative Menu
- unlocked upgrades and levels : split item description (with tooltip) and "try" button
- creative mode : removed tooltips for perks as they were getting in the way on mobile
- Fix: removed progress bars from unlocked level as there's no real progress
- Fix :upgrades list now uses numbers instead of bars, looks better with limitless
- Fix :somehow score clicks didn't register while the game was playing, that's solved
- Fix : click tooltip to open on mobile, click anywhere to close
- Fix: Can't press help buttons in Creative Menu
- Fix: wait for bricks to respawn before leveling up
- UX : score and menu button look extra clickable until you tap them 3 times and restart the app
## 29097764 ## 29097764

View file

@ -29,8 +29,8 @@ android {
applicationId = "me.lecaro.breakout" applicationId = "me.lecaro.breakout"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 29103645 versionCode = 29104573
versionName = "29103645" versionName = "29104573"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

File diff suppressed because one or more lines are too long

63
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
// The version of the cache. // The version of the cache.
const VERSION = "29103645"; const VERSION = "29104573";
// The name of the cache // The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`; const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -12,6 +12,7 @@ export type AsyncAlertAction<t> = {
disabled?: boolean; disabled?: boolean;
icon?: string; icon?: string;
className?: string; className?: string;
actionLabel?: string;
}; };
const popupWrap = document.getElementById("popup") as HTMLDivElement; const popupWrap = document.getElementById("popup") as HTMLDivElement;
@ -163,7 +164,7 @@ function addButton<t>(
addto.appendChild(buttonWrap); addto.appendChild(buttonWrap);
if (actionLabel) { if (actionLabel) {
buttonWrap.className = className; buttonWrap.className = className + " upgrade";
buttonWrap.innerHTML = icon; buttonWrap.innerHTML = icon;

View file

@ -1 +1 @@
"29103645" "29104573"

View file

@ -211,16 +211,15 @@ body:not(.has-alert-open) #popup {
opacity: 0.2; opacity: 0.2;
} }
} }
}
&.forbidden { &.forbidden {
background: linear-gradient(45deg, darkred, transparent); background: linear-gradient(-45deg, #0000, #ff00004a, #0000);
} }
&.required { &.required {
background: linear-gradient(45deg, gold, transparent); background: linear-gradient(-45deg, #0000, #ffd3005c, #0000);
} }
}
> button[data-help-content] { > button[data-help-content] {
user-select: none; user-select: none;
border-radius: 4px; border-radius: 4px;
@ -414,8 +413,9 @@ h2.histogram-title strong {
.upgrade { .upgrade {
display: flex; display: flex;
gap: 2px; gap: 2px;
margin: 0 0 10px 0; padding: 5px 5px;
margin: 0 -5px;
width: calc(100% + 10px);
img { img {
width: 32px; width: 32px;
height: 32px; height: 32px;

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": "لقد انتهيت للتو من المستوى {{level}}/{{max}}.", "level_up.title": "لقد انتهيت للتو من المستوى {{level}}/{{max}}.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -2897,6 +2897,76 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<concept_node>
<name>forbidden</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>required</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>title</name> <name>title</name>
<description/> <description/>

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": "Du hast gerade Level {{level}}/{{max}} beendet.", "level_up.title": "Du hast gerade Level {{level}}/{{max}} beendet.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "You'll get a gold medal under {{gold}}s and a silver medal under {{silver}}s. ", "level_up.challenges.levelTime.description": "You'll get a gold medal under {{gold}}s and a silver medal under {{silver}}s. ",
"level_up.challenges.levelTime.name": "{{value}}s play time", "level_up.challenges.levelTime.name": "{{value}}s play time",
"level_up.challenges.no_gain": "No gain", "level_up.challenges.no_gain": "No gain",
"level_up.forbidden": "Picking this perk will prevent you from unlocking the level \"{{levelName}}\" in this game run.",
"level_up.required": "Picking this perk may allow you to unlock level \"{{levelName}}\" in this game run.",
"level_up.title": "Level {{level}}/{{max}} cleared", "level_up.title": "Level {{level}}/{{max}} cleared",
"level_up.upgrade_perks": "You caught {{coins}} coins. Pick {{count}} upgrade(s) below. ", "level_up.upgrade_perks": "You caught {{coins}} coins. Pick {{count}} upgrade(s) below. ",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": "Acabas de completar el nivel {{level}}/{{max}}.", "level_up.title": "Acabas de completar el nivel {{level}}/{{max}}.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "Gráficos simplificados", "main_menu.basic": "Gráficos simplificados",

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": "Vous venez de terminer le niveau {{level}}/{{max}}.", "level_up.title": "Vous venez de terminer le niveau {{level}}/{{max}}.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": "Вы только что закончили уровень {{level}}/{{max}}.", "level_up.title": "Вы только что закончили уровень {{level}}/{{max}}.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -79,6 +79,8 @@
"level_up.challenges.levelTime.description": "", "level_up.challenges.levelTime.description": "",
"level_up.challenges.levelTime.name": "", "level_up.challenges.levelTime.name": "",
"level_up.challenges.no_gain": "", "level_up.challenges.no_gain": "",
"level_up.forbidden": "",
"level_up.required": "",
"level_up.title": " {{level}}/{{max}}seviyesini yeni bitirdiniz.", "level_up.title": " {{level}}/{{max}}seviyesini yeni bitirdiniz.",
"level_up.upgrade_perks": "", "level_up.upgrade_perks": "",
"main_menu.basic": "", "main_menu.basic": "",

View file

@ -2,12 +2,12 @@ import { GameState, PerkId } from "./types";
import { import {
catchRateBest, catchRateBest,
catchRateGood, catchRateGood,
choicePerGold,
choicePerSilver,
levelTimeBest, levelTimeBest,
levelTimeGood, levelTimeGood,
missesBest, missesBest,
missesGood, missesGood,
choicePerGold,
choicePerSilver,
upPerGold, upPerGold,
upPerSilver, upPerSilver,
} from "./pure_functions"; } from "./pure_functions";
@ -122,34 +122,44 @@ export async function openUpgradesPicker(gameState: GameState) {
); );
} }
const unlockable = getFirstUnlockable(gameState); let sorted = getPossibleUpgrades(gameState)
let offered = getPossibleUpgrades(gameState)
.map((u) => ({ .map((u) => ({
...u, ...u,
score: Math.random() + (gameState.lastOffered[u.id] || 0), score: Math.random() + (gameState.lastOffered[u.id] || 0),
})) }))
.sort((a, b) => a.score - b.score) .sort((a, b) => a.score - b.score)
.filter((u) => gameState.perks[u.id] < u.max + gameState.perks.limitless) .filter((u) => gameState.perks[u.id] < u.max + gameState.perks.limitless);
.slice(0, 3 + extraChoices + gameState.perks.one_more_choice);
while (true) {
// refresh the list if you pick extra one_more_choice
const offered = sorted.slice(
0,
3 + extraChoices + gameState.perks.one_more_choice,
);
offered.forEach((u) => { offered.forEach((u) => {
dontOfferTooSoon(gameState, u.id); dontOfferTooSoon(gameState, u.id);
}); });
while (true) { const unlockable = getFirstUnlockable(gameState);
let unlockRelatedUpgradesOffered = 0; let unlockRelatedUpgradesOffered = 0;
let unlockHint = "";
const upgradesActions = offered.map((u) => { const upgradesActions = offered.map((u) => {
let className = ""; let className = "";
if (isOptionOn("level_unlocks_hints")) { if (isOptionOn("level_unlocks_hints")) {
if (unlockable?.forbidden?.includes(u.id)) { if (unlockable?.forbidden?.includes(u.id) && !gameState.perks[u.id]) {
unlockRelatedUpgradesOffered++; unlockRelatedUpgradesOffered++;
className += " forbidden"; className += " forbidden";
unlockHint = t("level_up.forbidden", {
levelName: unlockable?.l.name || "",
});
} }
if (unlockable?.required?.includes(u.id)) { if (unlockable?.required?.includes(u.id)) {
unlockRelatedUpgradesOffered++; unlockRelatedUpgradesOffered++;
className += " required"; className += " required";
unlockHint = t("level_up.required", {
levelName: unlockable?.l.name || "",
});
} }
} }
return { return {
@ -161,9 +171,10 @@ export async function openUpgradesPicker(gameState: GameState) {
? upgradeLevelAndMaxDisplay(u, gameState) ? upgradeLevelAndMaxDisplay(u, gameState)
: ""), : ""),
icon: icons["icon:" + u.id], icon: icons["icon:" + u.id],
help: u.help(gameState.perks[u.id] || 1), help: unlockHint || u.help(gameState.perks[u.id] || 1),
tooltip: u.fullHelp(gameState.perks[u.id] || 1), tooltip: u.fullHelp(gameState.perks[u.id] || 1),
className, className,
actionLabel: gameState.perks[u.id] ? "upgrade" : "pick",
}; };
}); });

View file

@ -19,12 +19,14 @@ function setupMobileTooltips(tooltip: HTMLDivElement) {
console.log("openTooltip", e); console.log("openTooltip", e);
hideAnyTooltip(); hideAnyTooltip();
const hovering = e.target as HTMLElement; const hovering = e.target as HTMLElement;
if (!hovering?.hasAttribute("data-help-content")) { const tooltipContent =
hovering?.getAttribute("data-help-content")?.trim() || "";
if (!tooltipContent) {
return; return;
} }
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
tooltip.innerHTML = hovering.getAttribute("data-help-content") || ""; tooltip.innerHTML = tooltipContent;
tooltip.style.display = ""; tooltip.style.display = "";
const { top } = hovering.getBoundingClientRect(); const { top } = hovering.getBoundingClientRect();
tooltip.style.transform = `translate(0,${top}px) translate(0,-100%)`; tooltip.style.transform = `translate(0,${top}px) translate(0,-100%)`;