mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-05-04 18:59:13 -04:00
wip
This commit is contained in:
parent
ca1c75a5a1
commit
94ffb80f49
19 changed files with 186 additions and 73 deletions
28
Readme.md
28
Readme.md
|
@ -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 :
|
||||||
|
- bigger "level X / Y cleared"
|
||||||
|
- upgardes need to all be spent on the same list of perks (to avoid reading too much)
|
||||||
|
- instead of rerolls, you get a longer list of choices to pick from with gold medals
|
||||||
|
- clarified challenges, only show them when you pass one of them
|
||||||
|
- removed the "sides bounce" challenge, bouncing on sides shouldn't be punished
|
||||||
|
- once you reach high score of 1000, level unlock hints appear, and required / forbidden upgrades and colored gold/red
|
||||||
|
- added tooltip on most items on that screen, that can be triggered on mobile by tapping the text
|
||||||
|
|
||||||
- when you earn multiple upgrade points, they all need to be put on the same perk
|
|
||||||
- wait for bricks to respawn before leveling up
|
|
||||||
- creative mode : removed tooltips for perks as they were getting in the way on mobile
|
|
||||||
- unlocked upgrades and levels : split item description (with tooltip) and "try" button
|
- unlocked upgrades and levels : split item description (with tooltip) and "try" button
|
||||||
- unlocked level: removed progress bars as there's no real progress
|
- creative mode : removed tooltips for perks as they were getting in the way on mobile
|
||||||
- bigger "level X of Y cleared"
|
- Fix: removed progress bars from unlocked level as there's no real progress
|
||||||
- clarify challenges but only show them when you pass one of them
|
- Fix :upgrades list now uses numbers instead of bars, looks better with limitless
|
||||||
- removed the "sides bounce" challenge, bouncing on sides shouldn't be punished
|
- Fix :somehow score clicks didn't register while the game was playing, that's solved
|
||||||
- upgrades list now uses numbers instead of bars, looks better with limitless
|
|
||||||
- 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 : click tooltip to open on mobile, click anywhere to close
|
||||||
- Can't press help buttons in Creative Menu
|
- 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
|
||||||
|
|
||||||
|
|
|
@ -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
67
dist/index.html
vendored
67
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -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}`;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29103645"
|
"29104573"
|
||||||
|
|
|
@ -211,16 +211,15 @@ body:not(.has-alert-open) #popup {
|
||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.forbidden {
|
|
||||||
background: linear-gradient(45deg, darkred, transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.required {
|
|
||||||
background: linear-gradient(45deg, gold, transparent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.forbidden {
|
||||||
|
background: linear-gradient(-45deg, #0000, #ff00004a, #0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.required {
|
||||||
|
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;
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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/>
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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": "",
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
offered.forEach((u) => {
|
|
||||||
dontOfferTooSoon(gameState, u.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
while (true) {
|
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) => {
|
||||||
|
dontOfferTooSoon(gameState, u.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
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",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { t } from "./i18n/i18n";
|
||||||
import { OptionDef, OptionId } from "./types";
|
import { OptionDef, OptionId } from "./types";
|
||||||
import { getSettingValue, setSettingValue } from "./settings";
|
import { getSettingValue, setSettingValue } from "./settings";
|
||||||
|
|
||||||
import {getHighScore, hoursSpentPlaying} from "./game_utils";
|
import { getHighScore, hoursSpentPlaying } from "./game_utils";
|
||||||
|
|
||||||
export const options = {
|
export const options = {
|
||||||
sound: {
|
sound: {
|
||||||
|
@ -91,7 +91,7 @@ export const options = {
|
||||||
help: t("settings.donation_reminder_help"),
|
help: t("settings.donation_reminder_help"),
|
||||||
},
|
},
|
||||||
level_unlocks_hints: {
|
level_unlocks_hints: {
|
||||||
default: getHighScore()>1000,
|
default: getHighScore() > 1000,
|
||||||
name: t("settings.level_unlocks_hints"),
|
name: t("settings.level_unlocks_hints"),
|
||||||
help: t("settings.level_unlocks_hints_help"),
|
help: t("settings.level_unlocks_hints_help"),
|
||||||
},
|
},
|
||||||
|
|
|
@ -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%)`;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue