mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-25 14:36:15 -04:00
wip
This commit is contained in:
parent
f2bf1e3f9f
commit
83b9c0dec5
14 changed files with 322 additions and 499 deletions
|
@ -74,9 +74,9 @@ export async function asyncAlert<t>({
|
|||
}
|
||||
|
||||
if (title) {
|
||||
const h2 = document.createElement("h2");
|
||||
h2.innerHTML = title;
|
||||
popup.appendChild(h2);
|
||||
const h1 = document.createElement("h1");
|
||||
h1.innerHTML = title;
|
||||
popup.appendChild(h1);
|
||||
}
|
||||
|
||||
content
|
||||
|
|
43
src/game.ts
43
src/game.ts
|
@ -65,7 +65,14 @@ import {
|
|||
} from "./asyncAlert";
|
||||
import { isOptionOn, options, toggleOption } from "./options";
|
||||
import { hashCode } from "./getLevelBackground";
|
||||
import { hoursSpentPlaying } from "./pure_functions";
|
||||
import {
|
||||
catchRateBest, catchRateGood,
|
||||
hoursSpentPlaying,
|
||||
levelTimeBest,
|
||||
levelTimeGood, missesBest, missesGood,
|
||||
wallBouncedBest,
|
||||
wallBouncedGood
|
||||
} from "./pure_functions";
|
||||
import { helpMenuEntry } from "./help";
|
||||
import { creativeMode } from "./creative";
|
||||
import { setupTooltips } from "./tooltip";
|
||||
|
@ -210,35 +217,35 @@ export async function openUpgradesPicker(gameState: GameState) {
|
|||
wallHitsGain = "",
|
||||
missesGain = "";
|
||||
|
||||
if (gameState.levelWallBounces < 3) {
|
||||
if (gameState.levelWallBounces < wallBouncedBest) {
|
||||
repeats++;
|
||||
gameState.rerolls++;
|
||||
wallHitsGain = t("level_up.plus_one_upgrade_and_reroll");
|
||||
} else if (gameState.levelWallBounces < 10) {
|
||||
} else if (gameState.levelWallBounces < wallBouncedGood) {
|
||||
repeats++;
|
||||
wallHitsGain = t("level_up.plus_one_upgrade");
|
||||
}
|
||||
if (gameState.levelTime < 30 * 1000) {
|
||||
if (gameState.levelTime < levelTimeBest * 1000) {
|
||||
repeats++;
|
||||
gameState.rerolls++;
|
||||
timeGain = t("level_up.plus_one_upgrade_and_reroll");
|
||||
} else if (gameState.levelTime < 60 * 1000) {
|
||||
} else if (gameState.levelTime < levelTimeGood * 1000) {
|
||||
repeats++;
|
||||
timeGain = t("level_up.plus_one_upgrade");
|
||||
}
|
||||
if (catchRate > 0.95) {
|
||||
if (catchRate > catchRateBest/100) {
|
||||
repeats++;
|
||||
gameState.rerolls++;
|
||||
catchGain = t("level_up.plus_one_upgrade_and_reroll");
|
||||
} else if (catchRate > 0.9) {
|
||||
} else if (catchRate > catchRateGood/100) {
|
||||
repeats++;
|
||||
catchGain = t("level_up.plus_one_upgrade");
|
||||
}
|
||||
if (gameState.levelMisses < 3) {
|
||||
if (gameState.levelMisses < missesBest) {
|
||||
repeats++;
|
||||
gameState.rerolls++;
|
||||
missesGain = t("level_up.plus_one_upgrade_and_reroll");
|
||||
} else if (gameState.levelMisses < 6) {
|
||||
} else if (gameState.levelMisses < missesGood) {
|
||||
repeats++;
|
||||
missesGain = t("level_up.plus_one_upgrade");
|
||||
}
|
||||
|
@ -500,7 +507,23 @@ export async function openMainMenu() {
|
|||
|
||||
const cb = await asyncAlert<() => void>({
|
||||
title: t("main_menu.title"),
|
||||
content: [...actions, t("main_menu.footer_html", { appVersion })],
|
||||
content: [...actions,
|
||||
|
||||
`<p>
|
||||
<span>Made in France by <a href="https://lecaro.me">Renan LE CARO</a>.</span>
|
||||
<a href="https://paypal.me/renanlecaro" target="_blank">Donate</a>
|
||||
<a href="https://discord.gg/bbcQw4x5zA" target="_blank">Discord</a>
|
||||
<a href="https://f-droid.org/en/packages/me.lecaro.breakout/" target="_blank">F-Droid</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=me.lecaro.breakout" target="_blank">Google Play</a>
|
||||
<a href="https://renanlecaro.itch.io/breakout71" target="_blank">itch.io</a>
|
||||
<a href="https://gitlab.com/lecarore/breakout71" target="_blank">Gitlab</a>
|
||||
<a href="https://breakout.lecaro.me/" target="_blank">Web version</a>
|
||||
<a href="https://news.ycombinator.com/item?id=43183131" target="_blank">HackerNews</a>
|
||||
<a href="https://breakout.lecaro.me/privacy.html" target="_blank">Privacy Policy</a>
|
||||
<a href="https://archive.lecaro.me/public-files/b71/" target="_blank">Archives</a>
|
||||
<span>v.${appVersion}</span>
|
||||
</p>`
|
||||
],
|
||||
allowClose: true,
|
||||
});
|
||||
if (cb) {
|
||||
|
|
|
@ -78,7 +78,7 @@ export function gameOver(title: string, intro: string) {
|
|||
{
|
||||
icon: icons["icon:new_run"],
|
||||
value: null,
|
||||
text: t("gameOver.restart"),
|
||||
text: t("confirmRestart.yes"),
|
||||
help: "",
|
||||
},
|
||||
`<div id="level-recording-container"></div>`,
|
||||
|
|
19
src/help.ts
19
src/help.ts
|
@ -2,6 +2,13 @@ import { allLevels, icons, upgrades } from "./loadGameData";
|
|||
import { t } from "./i18n/i18n";
|
||||
import { asyncAlert } from "./asyncAlert";
|
||||
import { miniMarkDown } from "./pure_functions";
|
||||
import {
|
||||
catchRateBest, catchRateGood,
|
||||
levelTimeBest,
|
||||
levelTimeGood, missesBest, missesGood,
|
||||
wallBouncedBest,
|
||||
wallBouncedGood
|
||||
} from "./pure_functions"
|
||||
|
||||
export function helpMenuEntry() {
|
||||
return {
|
||||
|
@ -13,8 +20,14 @@ export function helpMenuEntry() {
|
|||
title: t("main_menu.help_title"),
|
||||
allowClose: true,
|
||||
content: [
|
||||
miniMarkDown(t("main_menu.help_content")),
|
||||
t("main_menu.help_upgrades"),
|
||||
miniMarkDown(t("main_menu.help_content",{
|
||||
catchRateBest, catchRateGood,
|
||||
levelTimeBest,
|
||||
levelTimeGood, missesBest, missesGood,
|
||||
wallBouncedBest,
|
||||
wallBouncedGood
|
||||
})),
|
||||
miniMarkDown(t("main_menu.help_upgrades")),
|
||||
...upgrades.map(
|
||||
(u) => `
|
||||
<div class="upgrade used">
|
||||
|
@ -28,7 +41,7 @@ export function helpMenuEntry() {
|
|||
${miniMarkDown(u.fullHelp)}
|
||||
`,
|
||||
),
|
||||
t("main_menu.credit_levels"),
|
||||
'<h2>'+t("main_menu.credit_levels")+'</h2>',
|
||||
...allLevels
|
||||
.filter((l) => l.credit?.trim())
|
||||
.map(
|
||||
|
|
|
@ -152,21 +152,6 @@
|
|||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<concept_node>
|
||||
<name>restart</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<folder_node>
|
||||
<name>stats</name>
|
||||
<children>
|
||||
|
@ -425,96 +410,6 @@
|
|||
<folder_node>
|
||||
<name>columns</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>max_combo</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>max_level</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>puck_bounces</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>puck_bounces_tooltip</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>runTime</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>runTime_tooltip</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>score</name>
|
||||
<description/>
|
||||
|
@ -545,21 +440,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>upgrades_picked</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<concept_node>
|
||||
|
@ -857,36 +737,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>unlocked_level</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>unlocked_perk</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>upgrade_perk_to_level</name>
|
||||
<description/>
|
||||
|
@ -1162,21 +1012,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>footer_html</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>fullscreen</name>
|
||||
<description/>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
{
|
||||
"confirmRestart.no": "Cancel",
|
||||
"confirmRestart.text": "You're about to start a new game, is that really what you wanted?",
|
||||
"confirmRestart.text": "You're about to start a new game. Are you sure you want to continue?",
|
||||
"confirmRestart.title": "Start a new game?",
|
||||
"confirmRestart.yes": "Restart game",
|
||||
"gameOver.creative": "This is a test game, its score is not recorded.",
|
||||
"gameOver.creative": "This run will not be recorded. ",
|
||||
"gameOver.cumulative_total": "Your total cumulative score went from {{startTs}} to {{endTs}}.",
|
||||
"gameOver.lost.summary": "You dropped the ball after catching {{score}} coins.",
|
||||
"gameOver.lost.title": "Game Over",
|
||||
"gameOver.restart": "Start a new game",
|
||||
"gameOver.stats.balls_lost": "Balls lost",
|
||||
"gameOver.stats.bricks_broken": "Bricks broken",
|
||||
"gameOver.stats.bricks_per_minute": "Bricks broken per minute",
|
||||
|
@ -24,27 +23,20 @@
|
|||
"gameOver.unlocked_perk_plural": "You just unlocked {{count}} perks",
|
||||
"gameOver.win.summary": "This game is over. You stashed {{score}} coins. ",
|
||||
"gameOver.win.title": "You completed this game",
|
||||
"history.columns.max_combo": "Max combo",
|
||||
"history.columns.max_level": "Levels",
|
||||
"history.columns.puck_bounces": "PB",
|
||||
"history.columns.puck_bounces_tooltip": "Puck bounces : number of time the ball bounced on the puck",
|
||||
"history.columns.runTime": "Dur.",
|
||||
"history.columns.runTime_tooltip": "Duration of the run, in seconds, only counting time where the game is running and the ball is in motion",
|
||||
"history.columns.score": "Score",
|
||||
"history.columns.started": "Date",
|
||||
"history.columns.upgrades_picked": "Upgrades",
|
||||
"history.help": "See the list of your {{count}} game",
|
||||
"history.help": "See your {{count}} best games.",
|
||||
"history.locked": "Play at least ten games to unlock",
|
||||
"history.title": "Runs history",
|
||||
"lab.help": "Try any build you want",
|
||||
"lab.instructions": "Select upgrades below, then pick the level to play. Creative mode runs are ignored in unlocks, high score, total score and statistics, and only last one level.",
|
||||
"lab.instructions": "Select upgrades below, then pick a level to play. ",
|
||||
"lab.menu_entry": "Creative mode",
|
||||
"lab.reset": "Reset all to 0",
|
||||
"lab.select_level": "Select a level to play on",
|
||||
"lab.unlocks_at": "Unlocks at total score {{score}}",
|
||||
"level_up.after_buttons": "You just finished level {{level}}/{{max}}.",
|
||||
"level_up.before_buttons": "You caught {{score}} coins {{catchGain}} out of {{levelSpawnedCoins}} in {{time}} seconds {{timeGain}}.\n\nYou missed {{levelMisses}} times {{missesGain}} and hit the walls or ceiling {{levelWallBounces}} times{{wallHitsGain}}.\n\n{{compliment}}",
|
||||
"level_up.compliment_advice": "Try to catch all coins, never miss the bricks, never hit the walls/ceiling or clear the level under 30s to gain additional choices and upgrades.",
|
||||
"level_up.compliment_advice": "Try to catch all coins, never miss the bricks, never hit the walls/ceiling or clear the level under 30s to gain additional upgrades.",
|
||||
"level_up.compliment_good": "Well done !",
|
||||
"level_up.compliment_perfect": "Impressive, keep it up !",
|
||||
"level_up.pick_upgrade_title": "Pick an upgrade",
|
||||
|
@ -52,8 +44,6 @@
|
|||
"level_up.plus_one_upgrade_and_reroll": "(+1 upgrade and +1 re-roll)",
|
||||
"level_up.reroll": "Re-roll ({{count}})",
|
||||
"level_up.reroll_help": "Offer new choices",
|
||||
"level_up.unlocked_level": " (Level)",
|
||||
"level_up.unlocked_perk": " (Perk)",
|
||||
"level_up.upgrade_perk_to_level": " lvl {{level}}",
|
||||
"main_menu.basic": "Basic graphics",
|
||||
"main_menu.basic_help": "Better performance.",
|
||||
|
@ -63,7 +53,7 @@
|
|||
"main_menu.comboIncreaseTexts_help": "When the combo increase",
|
||||
"main_menu.contrast": "High Contrast",
|
||||
"main_menu.contrast_help": "More colorful and dark rendering",
|
||||
"main_menu.credit_levels": "<h2>Levels origin</h2>",
|
||||
"main_menu.credit_levels": "Levels",
|
||||
"main_menu.donate": "You've played for {{hours}} hours",
|
||||
"main_menu.donate_help": "How about donating? You can hide this reminder in the settings. ",
|
||||
"main_menu.donation_reminder": "Remind me to donate",
|
||||
|
@ -72,13 +62,12 @@
|
|||
"main_menu.download_save_file_help": "Get a save file",
|
||||
"main_menu.extra_bright": "Extra bright",
|
||||
"main_menu.extra_bright_help": "Increases the size of the halo around coins and bricks.",
|
||||
"main_menu.footer_html": "<p> \n<span>Made in France by <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> \n<a href=\"https://paypal.me/renanlecaro\" target=\"_blank\">Donate</a>\n<a href=\"https://discord.gg/bbcQw4x5zA\" target=\"_blank\">Discord</a>\n<a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n<a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n<a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> \n<a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n<a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Web version</a>\n<a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n<a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Privacy Policy</a>\n<span>v.{{appVersion}}</span>\n</p>\n",
|
||||
"main_menu.fullscreen": "Fullscreen",
|
||||
"main_menu.fullscreen_help": "Game will try to go full screen before starting",
|
||||
"main_menu.help_content": "# Goal\n\nThe goal is to catch as many coins as possible during 7 levels. \nCoins appear when you break bricks.\nThey fly around, bounce and roll, and you need to catch them with your puck to increase your score. \nYour score is displayed in the top right corner of the screen.\nYou must delete all bricks to progress to the next level. \nIf you drop the ball, it's game over, unless you had the \"extra life\" upgrade.\n\n# Upgrades \n\nAfter clearing a level, you'll be able to pick upgrades among a small selection presented to you. \n\nThe upgrade you pick will apply until the end of the run. You will get more upgrade if you play well : catch all coins, clear the level quickly, never miss the bricks, never bounce on the sides or ceiling.\n\nIf you play very well, you'll also get \"rerolls\" that allow you to shuffle the list of upgrades that are offered to you. Once an upgrade is offered, it's less likely to reappear afterward. \n\nYou also get a free random upgrade at the beginning of each run. There's also an easy mode for kids, where the game will always start with the \"slower ball\" upgrade. The icon of your randomly assigned upgrade will be the used as the first level you play in each run. You can decide which upgrades can be starting upgrades in the settings. \n\nUpgrades apply to the whole run and can synergize, or really work against each other. Most of the fun of the game is discovering which ones work best together.\n\nSome upgrades help with aiming, like \"Telekinesis\". Some upgrades can be picked multiple times to increase the effect, you'll see for example \"+1 ball level 2\" which adds a third ball.\n\nWhen you first play, only a few upgrades are available, you unlock the rest by simply playing and scoring points. At the end of a run, the things you just unlocked will be shown, and you can check the full content in menu / unlocks.\n\nMany upgrades impact your combo. \n\n# Combo\n\nYour \"combo\" is the number of coins spawned when a brick breaks. It is displayed on your puck, for example x4 means each\nbrick will spawn 4 coins. It will reset if you miss. \n\nMany upgrades will increase the combo when you break a brick, but also add a condition to reset it. So the more upgrades you pick, the faster it will climb, but the more likely it will be that it returns to it's base value. \n\n# Aiming\n\nWhat decides how the ball flies away is only the position of the puck hit. If the ball hits the puck dead center, it will bounce back up vertically, while in you hit more on one side, it will have more angle. \n\nThe puck speed and incoming angle have no impact on the ball direction after bouncing.\n\nYou might find that a smaller puck makes it a bit easier to aim near corners, but also makes it much harder to catch coins.\n\n\"Wind\" and \"puck controls ball\" can help you aim even after the ball bounced to the wrong direction.\n\n\"Slower ball\" gives you a bit more time to aim, particularly useful in later levels where the ball goes faster. The ball also\naccelerates as you spend time in each level. \n\n# Unlocks\n\nWhen starting breakout 71 for the first time, you can access a few upgrades and levels. The rest needs to be unlocked. Upgrades are unlocked by simply playing. Every time you catch a coin, your total score is raised by one. Then once you reach the threshold of the upgrade, it's unlocked.\n\nUnlocking levels is a bit different, it requires you to play very well, in many different ways. The first levels just need a high score of X, but later level are unlocked by reaching a high score of X with perk Y and without perk Z. All those requirements are pseudo random and not handpicked, so some are likely much harder than others. They should be the same for everyone though. It might happen that an update of the game perks list changes the required perks. \n\n# System requirements \n\nThe game should perform well even on low-end devices. It's very lean and does not take much storage space (Roughly 0.1MB). The web version is supposed to work on iOS safari, Firefox ESR and chrome, on desktop and mobile.\n\nIf the app stutters, turn on \"fast mode\" in the settings to render a simplified view that should be faster. You can adjust many aspects of the game there, go have a look ! \n\n",
|
||||
"main_menu.help_content": "## Goal\n\nCatch as many coins as possible during 7 levels. \nCoins appear when you break bricks.\nCatch them with your puck to increase your score.\nYour score is displayed in the top right corner of the screen.\nDon't drop the ball or it's game over.\n\nAfter destroying all bricks, you'll get to pick an upgrade.\n\n## Upgrades \n\nThe upgrades you pick will apply until the end of the run. \nSome can be picked multiple times for stronger effect.\nSome help with aiming, or make the game easier in some other ways. \nSome are only useful when combined.\n\nYou always get one upgrade at the beginning of each game. \nIts icon will serve as the bricks of the first level. \nYou can select starting upgrades in the settings.\n\nMany upgrades impact your combo. \n\n## Combo\n\nYour \"combo\" is the number of coins spawned when a brick breaks. \nIt is displayed on your puck, for example x4 means each brick will spawn 4 coins. \nMost upgrades that increase the combo also add a condition to reset it. \nThe combo will also reset if the ball returns to the puck without hitting any brick.\nA \"miss\" message will be shown when that happens. \n\nTry to aim towards a brick every time. \n\n## Aiming\n\nOnly the ball position on the puck decides how it will bounce.\nIf the ball hits the puck dead center, it will bounce back up vertically. \nIf you hit more on one side, it will have more angle. \nThe puck speed and incoming angle have no impact on the ball direction after bouncing.\n\nMany upgrades that help with aiming can be unlocked.\n\n## Unlocks\n\nWhen playing Breakout 71 for the first time, most upgrades and levels are locked. \nUpgrades are unlocked by simply playing and catching many coins. \nThe first levels are unlocked by reaching a high score.\nLater levels add a condition about which perks you can select. \n\nReach high scores is much easier when you get multiple upgrades after each level. \n\n## Re-rolls and free upgrades\n\nYou'll get an extra upgrade to pick when you play well : \n\n- Clear the level under {{levelTimeGood}} seconds\n- Hit the sides or top less than {{wallBouncedGood}} times\n- Catch {{catchRateGood}}% of coins\n- Miss the bricks less than {{missesGood}} times \n\nYou will also get a re-roll that lets you skip upgrades if you do even better : \n\n- Clear a level under {{levelTimeBest}} seconds\n- Hit the sides or top less than {{wallBouncedBest}} times\n- Catch {{catchRateBest}}% of coins\n- Miss the bricks less than {{missesBest}} times \n\nAn option in the settings lets you display those statistics",
|
||||
"main_menu.help_help": "Learn more about the game",
|
||||
"main_menu.help_title": "Help",
|
||||
"main_menu.help_upgrades": "<h2>Upgrades</h2>",
|
||||
"main_menu.help_upgrades": "## Upgrades",
|
||||
"main_menu.high_score": "High score : {{score}}",
|
||||
"main_menu.kid": "Kids mode",
|
||||
"main_menu.kid_help": "Start future games with \"slower ball\".",
|
||||
|
@ -92,7 +81,7 @@
|
|||
"main_menu.max_particles_help": "Limits the number of particles show on screen for visual effect. ",
|
||||
"main_menu.mobile": "Mobile mode",
|
||||
"main_menu.mobile_help": "Leaves space under the puck.",
|
||||
"main_menu.normal": "New game",
|
||||
"main_menu.normal": "New Game",
|
||||
"main_menu.normal_help": "Play 7 levels with a random starting perk",
|
||||
"main_menu.pointer_lock": "Mouse pointer lock",
|
||||
"main_menu.pointer_lock_help": "Locks and hides the mouse cursor.",
|
||||
|
@ -105,7 +94,7 @@
|
|||
"main_menu.reset_cancel": "No",
|
||||
"main_menu.reset_confirm": "Yes",
|
||||
"main_menu.reset_help": "Erase high score, play time and statistics",
|
||||
"main_menu.reset_instruction": "You will loose all progress you made in the game, are you sure?",
|
||||
"main_menu.reset_instruction": "You will lose all progress you made in the game, are you sure?",
|
||||
"main_menu.save_file_error": "Error loading save file",
|
||||
"main_menu.save_file_loaded": "Save file loaded",
|
||||
"main_menu.save_file_loaded_help": "The app will now reload to apply your save",
|
||||
|
@ -119,7 +108,7 @@
|
|||
"main_menu.sounds": "Game sounds",
|
||||
"main_menu.sounds_help": "Can slow down some phones.",
|
||||
"main_menu.starting_perks": "Starting perks",
|
||||
"main_menu.starting_perks_checked": "When you start a new game, one of those perks will be give to you. You can click the list to exclude some perks from the pool.",
|
||||
"main_menu.starting_perks_checked": "When you start a new game, one of those perks will be given to you. Click a perk to exclude it. ",
|
||||
"main_menu.starting_perks_help": "Choose possible starting upgrades",
|
||||
"main_menu.starting_perks_unchecked": "The perks below are not offered as starting perks, but you can click to add them to the pool. ",
|
||||
"main_menu.title": "Breakout 71",
|
||||
|
@ -143,11 +132,11 @@
|
|||
"score_panel.title": "{{score}} points at level {{level}}/{{max}} ",
|
||||
"score_panel.upcoming_levels": "Upcoming levels :",
|
||||
"score_panel.upgrades_picked": "Upgrades picked in this game run : ",
|
||||
"unlocks.greyed_out_help": "The grayed out upgrades can be unlocked by increasing your total score. The total score increases every time you score in game, outside of test runs.",
|
||||
"unlocks.intro": "Your total score is {{ts}}. Below are all the upgrades and levels the games has to offer. Click an upgrade or level below to start a test game with it. Hint: you can set the starting upgrades in the settings.",
|
||||
"unlocks.greyed_out_help": "The grayed out upgrades can be unlocked by increasing your total score. The total score increases every time you score in game.",
|
||||
"unlocks.intro": "Your total score is {{ts}}. Below are all the upgrades and levels the games has to offer. Click an upgrade or level below to start a test game with it.",
|
||||
"unlocks.just_unlocked": "Level unlocked",
|
||||
"unlocks.just_unlocked_plural": "You just unlocked {{count}} levels",
|
||||
"unlocks.level": "<h2>You unlocked {{unlocked}} levels out of {{out_of}}</h2>\n<p>Here are all the game levels, click one to start a test game with that starting level. </p> ",
|
||||
"unlocks.level": "<h2>You unlocked {{unlocked}} levels out of {{out_of}}</h2>\n<p>Here are all the game levels, click one to try it out.</p> ",
|
||||
"unlocks.level_description": "A {{size}}x{{size}} level with {{bricks}} bricks, {{colors}} colors and {{bombs}} bombs.",
|
||||
"unlocks.minScore": "Reach ${{minScore}} in a run to unlock.",
|
||||
"unlocks.minScoreWithPerks": "Reach ${{minScore}} in a run with {{required}} but without {{forbidden}} to unlock.",
|
||||
|
@ -166,24 +155,24 @@
|
|||
"upgrades.ball_attract_ball.name": "Gravity",
|
||||
"upgrades.ball_attracts_coins.fullHelp": "This could be used to \"paint around\" the balls with coins if you combined it with \"stain\" and \"ghost coins\".",
|
||||
"upgrades.ball_attracts_coins.help": "Balls attract coins",
|
||||
"upgrades.ball_attracts_coins.name": "Fortunate ball",
|
||||
"upgrades.ball_attracts_coins.name": "Coins cloud",
|
||||
"upgrades.ball_repulse_ball.fullHelp": "Balls that are less than a quarter screen width away will start repulsing each other. The repulsion force is stronger if they are close to each other. Particles will jet out to symbolize this force being applied. This perk is only offered if you have more than one ball already.",
|
||||
"upgrades.ball_repulse_ball.help": "Balls repulse balls",
|
||||
"upgrades.ball_repulse_ball.help_plural": "Stronger repulsion force",
|
||||
"upgrades.ball_repulse_ball.name": "Personal space",
|
||||
"upgrades.base_combo.fullHelp": "Your combo normally starts at 1 at the beginning of the level, and resets to 1 when you bounce around without hitting anything. With this perk, the combo starts 3 points higher, so you'll always get at least 4 coins per brick. Whenever your combo reset, it will go back to 4 and not 1. Your ball will glitter a bit to indicate that its combo is higher than one.",
|
||||
"upgrades.base_combo.help": "Combo starts at {{coins}}.",
|
||||
"upgrades.base_combo.name": "+3 base combo",
|
||||
"upgrades.base_combo.help": "Combo starts at {{coins}} instead of 1.",
|
||||
"upgrades.base_combo.name": "Strong foundations",
|
||||
"upgrades.bigger_explosions.fullHelp": "The default explosion clears a 3x3 square, with this it becomes a 5x5 square, and the blow on the coins is also significantly stronger. The screen will flash after each explosion (except in basic mode)",
|
||||
"upgrades.bigger_explosions.help": "Bigger explosions",
|
||||
"upgrades.bigger_explosions.name": "Kaboom",
|
||||
"upgrades.bigger_puck.fullHelp": "A bigger puck makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the puck). \n\nHowever, a large puck is harder to use around the sides of the level, and will make it sometimes unavoidable to miss. You could word around that with other perks.",
|
||||
"upgrades.bigger_puck.fullHelp": "A bigger puck makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the puck). \n\nHowever, a large puck is harder to use around the sides of the level, and will make it sometimes unavoidable to miss.",
|
||||
"upgrades.bigger_puck.help": "Easily catch more coins.",
|
||||
"upgrades.bigger_puck.name": "Bigger puck",
|
||||
"upgrades.clairvoyant.fullHelp": "Helps you pick the right upgrades and understand what's going on with sturdy bricks. Level 2 and 3 bring additional knowledge of dubious utility (reachable in loop mode)",
|
||||
"upgrades.clairvoyant.help": "See upcoming levels, bricks HP and ball direction",
|
||||
"upgrades.clairvoyant.name": "Clairvoyant",
|
||||
"upgrades.coin_magnet.fullHelp": "Directs the coins to the puck. The effect is stronger if the coin is close to it already. Catching all coins bring special bonuses in the game. \n\nAnother way to catch more coins is to hit bricks from the bottom. The ball's speed and direction impacts the spawned coin's velocity. ",
|
||||
"upgrades.coin_magnet.fullHelp": "Directs the coins to the puck. The effect is stronger if the coin is close to it already. Catching all coins bring special bonuses in the game. \n\nAnother way to catch more coins is to hit bricks from the bottom. The ball's speed and direction impact the spawned coin's velocity. ",
|
||||
"upgrades.coin_magnet.help": "Puck attracts coins",
|
||||
"upgrades.coin_magnet.help_plural": "Stronger effect on the coins",
|
||||
"upgrades.coin_magnet.name": "Coins magnet",
|
||||
|
@ -191,7 +180,7 @@
|
|||
"upgrades.compound_interest.help": "+{{lvl}} combo per brick broken, resets on coin lost",
|
||||
"upgrades.compound_interest.name": "Compound interest",
|
||||
"upgrades.concave_puck.fullHelp": "Balls starts the level going straight up, and bounces with less angle.",
|
||||
"upgrades.concave_puck.help": " Helps with aiming straight up",
|
||||
"upgrades.concave_puck.help": "Improves vertical aiming precision",
|
||||
"upgrades.concave_puck.name": "Concave puck",
|
||||
"upgrades.corner_shot.fullHelp": "Helps with aiming in the corners. Further levels let you go further out. ",
|
||||
"upgrades.corner_shot.help": "Lets your puck overlap with the borders of the screen",
|
||||
|
@ -201,16 +190,16 @@
|
|||
"upgrades.etherealcoins.name": "Coins, in Space",
|
||||
"upgrades.extra_levels.fullHelp": "The default game can last a max of 7 levels, after which the game is over. \n\nEach level of this perk lets you go one level higher. The last levels are often the ones where you make the most score, so the difference can be dramatic.",
|
||||
"upgrades.extra_levels.help": "Play {{count}} levels instead of 7",
|
||||
"upgrades.extra_levels.name": "+1 level",
|
||||
"upgrades.extra_life.fullHelp": "Normally, you have one ball, and the game is over as soon as you drop it.\n\nThis perk adds a white bar at the bottom of the screen that will save a ball once, and break in the process. \n\nYou'll loose one level of that perk every time a ball bounces at the bottom of the screen.",
|
||||
"upgrades.extra_levels.name": "5 min more",
|
||||
"upgrades.extra_life.fullHelp": "Normally, you have one ball, and the game is over as soon as you drop it.\n\nThis perk adds a white bar at the bottom of the screen that will save a ball once, and break in the process. \n\nYou'll lose one level of that perk every time a ball bounces at the bottom of the screen.",
|
||||
"upgrades.extra_life.help": "The ball will bounce once on the bottom line before being lost.",
|
||||
"upgrades.extra_life.help_plural": "The ball will bounce on the bottom {{lvl}} times before being lost.",
|
||||
"upgrades.extra_life.name": "+1 life",
|
||||
"upgrades.extra_life.help_plural": "Your (last) ball will bounce on the bottom instead of being lost ({{lvl}} times).",
|
||||
"upgrades.extra_life.name": "Extra Life",
|
||||
"upgrades.forgiving.fullHelp": "The first miss per level is free, then 10% of the combo, then 20% .. ",
|
||||
"upgrades.forgiving.help": "Missing breaks reduces combo progressively instead of all at once.",
|
||||
"upgrades.forgiving.name": "Forgiving",
|
||||
"upgrades.fountain_toss.fullHelp": "",
|
||||
"upgrades.fountain_toss.help": "When you miss a coin and your combo was under {{max}}, your combo has a probability of {{lvl}}/combo to grow by one.",
|
||||
"upgrades.fountain_toss.fullHelp": "When you miss a coin and your combo was under {{max}}, your combo has a probability of {{lvl}}/combo to grow by one.",
|
||||
"upgrades.fountain_toss.help": "Gain some combo when you miss some coins. ",
|
||||
"upgrades.fountain_toss.name": "Fountain toss",
|
||||
"upgrades.ghost_coins.fullHelp": "It's not a bug, it's a feature ! Coins fly through bricks slowly. Higher levels let them move faster. ",
|
||||
"upgrades.ghost_coins.help": "Coins slowly pass through bricks",
|
||||
|
@ -218,40 +207,40 @@
|
|||
"upgrades.helium.fullHelp": "This affects the coins and will let the float up until you are ready to pick them up.",
|
||||
"upgrades.helium.help": "Gravity reversed left and right of puck",
|
||||
"upgrades.helium.name": "Helium",
|
||||
"upgrades.hot_start.fullHelp": "At the start of every level, your combo will start at +30 points, but then every second it will be decreased by one.\n\nThis means the first 30 seconds in a level will spawn many more coins than the following ones, and you should make sure that you clear the level quickly. \n\nThe effect stacks with other combo related perks, so you might be able to raise the combo after the 30s timeout, but it will keep ticking down. \n\nEvery time you take the perk again, the effect will be more dramatic.",
|
||||
"upgrades.hot_start.fullHelp": "At the start of every level, your combo will start at +30 points, but then every second it will be decreased by one. The effect stacks with other perks. ",
|
||||
"upgrades.hot_start.help": "Start at combo {{start}}, -{{loss}} combo per second",
|
||||
"upgrades.hot_start.name": "Hot start",
|
||||
"upgrades.implosions.fullHelp": "The explosion force is applied the other way. Further levels act as \"bigger explosion\"",
|
||||
"upgrades.implosions.help": "Explosions suck coins in instead of blowing them out",
|
||||
"upgrades.implosions.name": "Implosions",
|
||||
"upgrades.instant_upgrade.fullHelp": "Immediately pick two upgrades, so that you get one free one and one to repay the one used to get this perk. Every further menu to pick upgrades will have fewer options to choose from.",
|
||||
"upgrades.instant_upgrade.help": "-{{lvl}} choice until game end.",
|
||||
"upgrades.instant_upgrade.name": "+2 upgrades now",
|
||||
"upgrades.instant_upgrade.help": "+1 upgrade now, -1 choice until game end.",
|
||||
"upgrades.instant_upgrade.name": "Instant upgrade",
|
||||
"upgrades.left_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one, so you'll get one more coin from all the next bricks you break.\n\nHowever, your combo will reset as soon as your ball hits the left side . \n\nAs soon as your combo rises, the left side becomes red to remind you that you should avoid hitting them. \n",
|
||||
"upgrades.left_is_lava.help": "+{{lvl}} combo per brick broken, resets on left side hit",
|
||||
"upgrades.left_is_lava.help": "+{{lvl}} combo per brick broken. Combo resets if ball hits the left side of the screen",
|
||||
"upgrades.left_is_lava.name": "Avoid left side",
|
||||
"upgrades.limitless.fullHelp": "Choosing this perk also raises his own limit by one, letting you pick it again.",
|
||||
"upgrades.limitless.help": "Raise all upgrade's maximum level by {{lvl}} ",
|
||||
"upgrades.limitless.name": "Limitless",
|
||||
"upgrades.metamorphosis.fullHelp": "With this perk, coins will be of the color of the brick they come from, and will color the first brick they touch in the same color. \n\nCoins spawn with the speed of the ball that broke them, which means you can aim a bit in the direction of the bricks you want to \"paint\".",
|
||||
"upgrades.metamorphosis.help": "Each coins can stain {{lvl}} brick(s) with its color",
|
||||
"upgrades.metamorphosis.help": "Each coin can stain {{lvl}} brick(s) with its color",
|
||||
"upgrades.metamorphosis.name": "Metamorphosis",
|
||||
"upgrades.minefield.fullHelp": "Adds +lvl to the combo when a brick is place, -lvl when it is destroyed, and raises the base combo by the number of bricks times lvl",
|
||||
"upgrades.minefield.help": "+{{lvl}} combo per bomb brick on screen",
|
||||
"upgrades.minefield.name": "Minefield",
|
||||
"upgrades.multiball.fullHelp": "As soon as you drop the ball in Breakout 71, you loose. \n\nWith this perk, you get two balls, and so you can afford to lose one. \n\nThe lost balls come back on the next level. \n\nHaving more than one balls makes some further perks available, and of course clears the level faster.",
|
||||
"upgrades.multiball.fullHelp": "As soon as you drop the ball in Breakout 71, you lose. \n\nWith this perk, you get two balls, and so you can afford to lose one. \n\nThe lost balls come back on the next level. \n\nHaving more than one balls makes some further perks available, and of course clears the level faster.",
|
||||
"upgrades.multiball.help": "Start every levels with {{count}} balls.",
|
||||
"upgrades.multiball.name": "+1 ball",
|
||||
"upgrades.multiball.name": "Multi ball",
|
||||
"upgrades.nbricks.fullHelp": "You don't necessarily need to destroy those bricks, but you need to hit them. Bricks destroyed by explosions don't count",
|
||||
"upgrades.nbricks.help": "Hit exactly {{lvl}} bricks per puck bounce for +{{lvl}} combo, otherwise it resets",
|
||||
"upgrades.nbricks.name": "Strict sample size",
|
||||
"upgrades.one_more_choice.fullHelp": "Every upgrade menu will have one more option. Doesn't increase the number of upgrades you can pick.",
|
||||
"upgrades.one_more_choice.help": "Further level ups will offer {{lvl}} more option(s) in the list",
|
||||
"upgrades.one_more_choice.name": "+1 choice",
|
||||
"upgrades.one_more_choice.name": "Extra choice",
|
||||
"upgrades.passive_income.fullHelp": "Some perks can help the balls do what you want without needing to do anything.",
|
||||
"upgrades.passive_income.help": "+{{lvl}} combo / brick, unless the puck moved in the last {{time}}s, then it resets instead",
|
||||
"upgrades.passive_income.name": "Passive income",
|
||||
"upgrades.picky_eater.fullHelp": "Whenever you break a brick the same color as your ball, your combo increases by one. \n\nIf it's a different color, the ball takes that new color, but the combo resets, unless there were no bricks left of the ball's color. \n\nOnce you get a combo higher than your minimum, the bricks of the wrong color will get a red halo. \n\nIf you have more than one ball, they all switch color whenever one of them hits a brick.",
|
||||
"upgrades.picky_eater.fullHelp": "Whenever you break a brick the same color as your ball, your combo increases by one. \nIf it's a different color, the ball takes that new color, but the combo resets, unless there were no bricks left of the ball's color. \nOnce you get a combo higher than your minimum, the bricks of the wrong color will get a red border. \nIf you have more than one ball, they all switch color whenever one of them hits a brick.",
|
||||
"upgrades.picky_eater.help": "+{{lvl}} combo per brick broken, resets on ball color change",
|
||||
"upgrades.picky_eater.name": "Picky eater",
|
||||
"upgrades.pierce.fullHelp": "The ball normally bounces as soon as it touches something. With this perk, it will continue its trajectory for up to 3 bricks broken. \n\nAfter that, it will bounce on the 4th brick, and you'll need to touch the puck to reset the counter.",
|
||||
|
@ -271,7 +260,7 @@
|
|||
"upgrades.respawn.help": "{{percent}}% of bricks re-spawn after {{delay}}s.",
|
||||
"upgrades.respawn.name": "Re-spawn",
|
||||
"upgrades.right_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one, so you'll get one more coin from all the next bricks you break.\n\nHowever, your combo will reset as soon as your ball hits the right side. \n\nAs soon as your combo rises, the right side becomes red to remind you that you should avoid hitting them.\n",
|
||||
"upgrades.right_is_lava.help": "+{{lvl}} combo per brick broken, resets on right side hit",
|
||||
"upgrades.right_is_lava.help": "+{{lvl}} combo per brick. Combo resets if ball hits the left side of the screen",
|
||||
"upgrades.right_is_lava.name": "Avoid right side",
|
||||
"upgrades.sacrifice.fullHelp": "This might get the combo pretty high.",
|
||||
"upgrades.sacrifice.help_l1": "Loosing a life clears all bricks",
|
||||
|
@ -281,7 +270,7 @@
|
|||
"upgrades.sapper.help": "The first brick broken becomes a bomb.",
|
||||
"upgrades.sapper.help_plural": "The first {{lvl}} bricks broken become bombs.",
|
||||
"upgrades.sapper.name": "Sapper",
|
||||
"upgrades.shocks.fullHelp": "Whenever two balls collide, they exchange their speed, spawn an explosion, and gain added speed to separated them. ",
|
||||
"upgrades.shocks.fullHelp": "Whenever two balls collide, they exchange their speed, spawn an explosion, and gain added speed to separate them. ",
|
||||
"upgrades.shocks.help": "Explosive balls collisions",
|
||||
"upgrades.shocks.name": "Shocks",
|
||||
"upgrades.shunt.fullHelp": "If you also have hot start, the hot start is just added to the current combo",
|
||||
|
@ -308,8 +297,8 @@
|
|||
"upgrades.soft_reset.help": "Combo resets keeps {{percent}}%",
|
||||
"upgrades.soft_reset.name": "Soft reset",
|
||||
"upgrades.streak_shots.fullHelp": "Every time you break a brick, your combo (number of coins per bricks) increases by one. \n\nHowever, as soon as the ball touches your puck, the combo is reset to its default value, and you'll just get one coin per brick.\n\nOnce your combo rises above the base value, your puck will become red to remind you that it will destroy your combo to touch it with the ball.",
|
||||
"upgrades.streak_shots.help": "More coins if you break many bricks at once.",
|
||||
"upgrades.streak_shots.name": "Single puck hit streak",
|
||||
"upgrades.streak_shots.help": "More coins if you break many bricks before bouncing on the puck.",
|
||||
"upgrades.streak_shots.name": "Hit streak",
|
||||
"upgrades.sturdy_bricks.fullHelp": "Each level of this perk adds one HP to all bricks. You can see the HP number with the \"clairvoyant\" perk. You can increase ball damage by getting the \"piercing\" perk. Each level of the perk adds +50% coins spawn. ",
|
||||
"upgrades.sturdy_bricks.help": "+{{lvl}} bricks HP, +{{percent}}% coins spawned when broken",
|
||||
"upgrades.sturdy_bricks.name": "Sturdy bricks",
|
||||
|
@ -330,7 +319,7 @@
|
|||
"upgrades.viscosity.fullHelp": "Coins normally accelerate with gravity and explosions to pretty high speeds. \n\nThis perk constantly makes them slow down, as if they were in some sort of viscous liquid. \n\nThis makes catching them easier, and combines nicely with perks that influence the coin's movement.",
|
||||
"upgrades.viscosity.help": "Slower coin fall",
|
||||
"upgrades.viscosity.name": "Viscosity",
|
||||
"upgrades.wind.fullHelp": "The wind depends on where your puck is, if it's in the center of the screen nothing happens, if it's on the left it will blow left-wise, if it's on the right of the screen then it will blow right-wise. \n\nThe wind affects both the balls and coins.",
|
||||
"upgrades.wind.fullHelp": "Wind depends on puck position: left blows left, right blows right. Affects both balls and coins.",
|
||||
"upgrades.wind.help": "Puck position creates wind",
|
||||
"upgrades.wind.help_plural": "Stronger wind force",
|
||||
"upgrades.wind.name": "Wind",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,77 +1,88 @@
|
|||
export function clamp(value: number, min: number, max: number) {
|
||||
return Math.max(min, Math.min(value, max));
|
||||
return Math.max(min, Math.min(value, max));
|
||||
}
|
||||
|
||||
export function comboKeepingRate(level: number) {
|
||||
return clamp(1 - (1 / (1 + level)) * 1.5, 0, 1);
|
||||
return clamp(1 - (1 / (1 + level)) * 1.5, 0, 1);
|
||||
}
|
||||
|
||||
export function hoursSpentPlaying() {
|
||||
try {
|
||||
const timePlayed =
|
||||
localStorage.getItem("breakout_71_total_play_time") || "0";
|
||||
return Math.floor(parseFloat(timePlayed) / 1000 / 60 / 60);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
const timePlayed =
|
||||
localStorage.getItem("breakout_71_total_play_time") || "0";
|
||||
return Math.floor(parseFloat(timePlayed) / 1000 / 60 / 60);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function miniMarkDown(md: string) {
|
||||
let html: { tagName: string; text: string }[] = [];
|
||||
let lastNode: { tagName: string; text: string } | null = null;
|
||||
let html: { tagName: string; text: string }[] = [];
|
||||
let lastNode: { tagName: string; text: string } | null = null;
|
||||
|
||||
md.split("\n").forEach((line) => {
|
||||
const titlePrefix = line.match(/^#+ /)?.[0];
|
||||
md.split("\n").forEach((line) => {
|
||||
const titlePrefix = line.match(/^#+ /)?.[0];
|
||||
|
||||
if (titlePrefix) {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = {
|
||||
tagName: "h" + (titlePrefix.length - 1),
|
||||
text: line.slice(titlePrefix.length),
|
||||
};
|
||||
} else if (line.startsWith("- ")) {
|
||||
if (lastNode?.tagName !== "ul") {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = { tagName: "ul", text: "" };
|
||||
}
|
||||
lastNode.text += "<li>" + line.slice(2) + "</li>";
|
||||
} else if (!line.trim()) {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = null;
|
||||
} else {
|
||||
if (lastNode?.tagName !== "p") {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = { tagName: "p", text: "" };
|
||||
}
|
||||
lastNode.text += line + " ";
|
||||
if (titlePrefix) {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = {
|
||||
tagName: "h" + (titlePrefix.length - 1),
|
||||
text: line.slice(titlePrefix.length),
|
||||
};
|
||||
} else if (line.startsWith("- ")) {
|
||||
if (lastNode?.tagName !== "ul") {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = {tagName: "ul", text: ""};
|
||||
}
|
||||
lastNode.text += "<li>" + line.slice(2) + "</li>";
|
||||
} else if (!line.trim()) {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = null;
|
||||
} else {
|
||||
if (lastNode?.tagName !== "p") {
|
||||
if (lastNode) html.push(lastNode);
|
||||
lastNode = {tagName: "p", text: ""};
|
||||
}
|
||||
lastNode.text += line + " ";
|
||||
}
|
||||
});
|
||||
if (lastNode) {
|
||||
html.push(lastNode);
|
||||
}
|
||||
});
|
||||
if (lastNode) {
|
||||
html.push(lastNode);
|
||||
}
|
||||
return html
|
||||
.map(
|
||||
(h) =>
|
||||
"<" +
|
||||
h.tagName +
|
||||
">" +
|
||||
h.text.replace(
|
||||
/\bhttps?:\/\/[^\s<>]+/gi,
|
||||
(a) => `<a href="${a}">${a}</a>`,
|
||||
) +
|
||||
"</" +
|
||||
h.tagName +
|
||||
">",
|
||||
)
|
||||
.join("\n");
|
||||
return html
|
||||
.map(
|
||||
(h) =>
|
||||
"<" +
|
||||
h.tagName +
|
||||
">" +
|
||||
h.text.replace(
|
||||
/\bhttps?:\/\/[^\s<>]+/gi,
|
||||
(a) => `<a href="${a}">${a}</a>`,
|
||||
) +
|
||||
"</" +
|
||||
h.tagName +
|
||||
">",
|
||||
)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
export function firstWhere<Input, Output>(
|
||||
arr: Input[],
|
||||
mapper: (item: Input, index: number) => Output | undefined,
|
||||
arr: Input[],
|
||||
mapper: (item: Input, index: number) => Output | undefined,
|
||||
): Output | undefined {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const result = mapper(arr[i], i);
|
||||
if (typeof result !== "undefined") return result;
|
||||
}
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const result = mapper(arr[i], i);
|
||||
if (typeof result !== "undefined") return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const
|
||||
wallBouncedBest = 3,
|
||||
wallBouncedGood = 10,
|
||||
levelTimeBest = 30,
|
||||
levelTimeGood = 60,
|
||||
catchRateBest = 95,
|
||||
catchRateGood = 90,
|
||||
missesBest = 3,
|
||||
missesGood = 6;
|
||||
|
||||
|
|
|
@ -14,6 +14,14 @@ import { Coin, colorString, GameState } from "./types";
|
|||
import { t } from "./i18n/i18n";
|
||||
import { gameState, lastMeasuredFPS } from "./game";
|
||||
import { isOptionOn } from "./options";
|
||||
import {
|
||||
catchRateBest,
|
||||
catchRateGood,
|
||||
levelTimeBest,
|
||||
levelTimeGood, missesBest, missesGood,
|
||||
wallBouncedBest,
|
||||
wallBouncedGood
|
||||
} from "./pure_functions";
|
||||
|
||||
export const gameCanvas = document.getElementById("game") as HTMLCanvasElement;
|
||||
export const ctx = gameCanvas.getContext("2d", {
|
||||
|
@ -71,16 +79,16 @@ export function render(gameState: GameState) {
|
|||
: "") +
|
||||
(isOptionOn("show_stats")
|
||||
? `
|
||||
<span class="${(catchRate > 0.95 && "great") || (catchRate > 0.9 && "good") || ""}" data-tooltip="${t("play.stats.coins_catch_rate")}">
|
||||
<span class="${(catchRate > catchRateBest/100 && "great") || (catchRate > catchRateGood/100 && "good") || ""}" data-tooltip="${t("play.stats.coins_catch_rate")}">
|
||||
${Math.floor(catchRate * 100)}%
|
||||
</span><span> / </span>
|
||||
<span class="${(gameState.levelTime < 30000 && "great") || (gameState.levelTime < 60000 && "good") || ""}" data-tooltip="${t("play.stats.levelTime")}">
|
||||
<span class="${(gameState.levelTime <levelTimeBest*1000 && "great") || (gameState.levelTime < levelTimeGood*1000 && "good") || ""}" data-tooltip="${t("play.stats.levelTime")}">
|
||||
${Math.ceil(gameState.levelTime / 1000)}s
|
||||
</span><span> / </span>
|
||||
<span class="${(gameState.levelWallBounces < 3 && "great") || (gameState.levelWallBounces < 10 && "good") || ""}" data-tooltip="${t("play.stats.levelWallBounces")}">
|
||||
<span class="${(gameState.levelWallBounces < wallBouncedBest && "great") || (gameState.levelWallBounces < wallBouncedGood && "good") || ""}" data-tooltip="${t("play.stats.levelWallBounces")}">
|
||||
${gameState.levelWallBounces} B
|
||||
</span><span> / </span>
|
||||
<span class="${(gameState.levelMisses < 3 && "great") || (gameState.levelMisses < 6 && "good") || ""}" data-tooltip="${t("play.stats.levelMisses")}">
|
||||
<span class="${(gameState.levelMisses < missesBest && "great") || (gameState.levelMisses < missesGood && "good") || ""}" data-tooltip="${t("play.stats.levelMisses")}">
|
||||
${gameState.levelMisses} M
|
||||
</span><span> / </span>
|
||||
`
|
||||
|
|
|
@ -30,28 +30,6 @@ export function runHistoryViewerMenuEntry() {
|
|||
label: t("history.columns.score"),
|
||||
field: (r) => r.score,
|
||||
},
|
||||
{
|
||||
label: t("history.columns.runTime"),
|
||||
tooltip: t("history.columns.runTime_tooltip"),
|
||||
|
||||
field: (r) => r.runTime,
|
||||
render(v) {
|
||||
return Math.floor(v / 1000) + "s";
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t("history.columns.puck_bounces"),
|
||||
tooltip: t("history.columns.puck_bounces_tooltip"),
|
||||
field: (r) => r.puck_bounces,
|
||||
},
|
||||
{
|
||||
label: t("history.columns.max_combo"),
|
||||
field: (r) => r.max_combo,
|
||||
},
|
||||
{
|
||||
label: t("history.columns.upgrades_picked"),
|
||||
field: (r) => r.upgrades_picked,
|
||||
},
|
||||
...rawUpgrades.map((u) => ({
|
||||
label: icons["icon:" + u.id],
|
||||
tooltip: u.name,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue