This commit is contained in:
Renan LE CARO 2025-05-03 18:29:54 +02:00
parent 94ffb80f49
commit 258d578ad3
22 changed files with 385 additions and 26 deletions

View file

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

View file

@ -1474,5 +1474,12 @@
"size": 8,
"bricks": "_________GGWWrr__GGWWrr__GGWWrr__GGWWrr_________________________",
"credit": "italia by Topenvy"
},
{
"name": "icon:steering",
"size": 9,
"bricks": "_bb__bb_____b___b_____b___bWWW_b___bWWW_WWWWWWWW_b___b____b___b___b___b__bb__bb__",
"svg": null,
"color": ""
}
]

View file

@ -1 +1 @@
"29104573"
"29104759"

View file

@ -643,6 +643,14 @@ h2.histogram-title strong {
opacity: 0.8;
transform: none;
}
&.big {
border: none;
left: 50vw;
top: 50vh;
font-size: 60px;
opacity: 0.9;
background: none;
}
}
.gridEdit > div > span,

View file

@ -82,6 +82,7 @@ import { monitorLevelsUnlocks } from "./monitorLevelsUnlocks";
import { levelEditorMenuEntry } from "./levelEditor";
import { categories } from "./upgrades";
import { reasonLevelIsLocked } from "./get_level_unlock_condition";
import { toast } from "./toast";
export async function play() {
if (await applyFullScreenChoice()) return;
@ -250,19 +251,42 @@ gameCanvas.addEventListener("mousemove", (e) => {
}
});
let timers = [];
function startPlayCountDown() {
stopPlayCountDown();
toast("3", "big");
timers.push(setTimeout(() => toast("2", "big"), 1000));
timers.push(setTimeout(() => toast("1", "big"), 2000));
timers.push(
setTimeout(() => {
toast("GO", "big");
play();
}, 3000),
);
}
function stopPlayCountDown() {
timers.forEach((id) => clearTimeout(id));
timers.length = 0;
}
gameCanvas.addEventListener("touchstart", (e) => {
e.preventDefault();
if (!e.touches?.length) return;
setMousePos(gameState, e.touches[0].pageX);
normalizeGameState(gameState);
play();
if (gameState.levelTime || !isOptionOn("touch_delayed_start")) {
play();
} else {
// start play sequence
startPlayCountDown();
}
});
gameCanvas.addEventListener("touchend", (e) => {
stopPlayCountDown();
e.preventDefault();
pause(true);
});
gameCanvas.addEventListener("touchcancel", (e) => {
stopPlayCountDown();
e.preventDefault();
pause(true);
});
@ -326,6 +350,7 @@ export function tick() {
gameStateTick(gameState, frames / steps);
}
}
gameState.lastPuckPosition = gameState.puckPosition;
if (gameState.running || gameState.needsRender) {
gameState.needsRender = false;

View file

@ -209,7 +209,6 @@ export function normalizeGameState(gameState: GameState) {
) {
gameState.lastPuckMove = gameState.levelTime;
}
gameState.lastPuckPosition = gameState.puckPosition;
}
export function baseCombo(gameState: GameState) {
@ -1613,6 +1612,8 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
gameState.perks.puck_repulse_ball +
gameState.perks.ball_attract_ball;
// Speed changes
if (telekinesisEffectRate(gameState, ball) > 0) {
speedLimitDampener += 3;
ball.vx +=
@ -1650,6 +1651,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
ball.vx *= 1 - 0.02 / speedLimitDampener;
ball.vy *= 1 - 0.02 / speedLimitDampener;
}
// Ball could get stuck horizontally because of ball-ball interactions in repulse/attract
if (Math.abs(ball.vy) < 0.2 * gameState.baseSpeed) {
ball.vy += ((ball.vy > 0 ? 1 : -1) * 0.02) / speedLimitDampener;
@ -1662,6 +1664,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
repulse(gameState, ball, b2, gameState.perks.ball_repulse_ball, true);
}
}
if (gameState.perks.ball_attract_ball) {
for (let b2 of gameState.balls) {
// avoid computing this twice, and repulsing itself
@ -1669,6 +1672,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
attract(gameState, ball, b2, gameState.perks.ball_attract_ball);
}
}
if (
gameState.perks.puck_repulse_ball &&
!isMovingWhilePassiveIncome(gameState) &&
@ -1688,6 +1692,26 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
);
}
if (gameState.perks.steering) {
const delta = gameState.puckPosition - gameState.lastPuckPosition;
const angle =
Math.atan2(ball.vy, ball.vx) +
((((delta / gameState.gameZoneWidth) * Math.PI) / 2) *
gameState.perks.steering *
frames) /
2;
const d = Math.sqrt(ball.vy * ball.vy + ball.vx * ball.vx);
ball.vy = Math.sin(angle) * d;
ball.vx = Math.cos(angle) * d;
console.log({
delta,
angle,
d,
});
}
// Bounces
const borderHitCode = bordersHitCheck(
gameState,
ball,

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "أصوات صفير وبلبل و برررر",
"settings.stress_test": "اختبار الإجهاد",
"settings.stress_test_help": "ابدأ لعبة يتم التحكم فيها بواسطة روبوت باستخدام عدد كبير جدًا من العملات المعدنية، لاختبار حدود أداء جهازك.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "عند بدء لعبة جديدة، ستُمنح إحدى هذه المزايا. انقر على أي ميزة لاستبعادها.",
"starting_perks.help": "اختر الترقيات الأولية الممكنة",
"starting_perks.random": "لقد تم إزالة جميع المزايا، وسيكون الاختيار عشوائيًا.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "إعادة الضبط الناعمة",
"upgrades.soft_reset.tooltip": "إعادة تعيين المجموعة تحافظ على {{percent}}%",
"upgrades.soft_reset.verbose_description": "الحد من تأثير إعادة تعيين المجموعة.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "العملات المعدنية اللاصقة",
"upgrades.sticky_coins.tooltip": "تلتصق العملات المعدنية بالطوب من نفس اللون",
"upgrades.sticky_coins.verbose_description": "في المستوى 2، يلتصقون بالطوب من أي لون",

View file

@ -8137,6 +8137,76 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>touch_delayed_start</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>touch_delayed_start_help</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>
</children>
</folder_node>
<folder_node>
@ -15082,6 +15152,116 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>steering</name>
<children>
<concept_node>
<name>name</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>tooltip</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>verbose_description</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>
</children>
</folder_node>
<folder_node>
<name>sticky_coins</name>
<children>

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Piepsen, Bloops und Brrrr",
"settings.stress_test": "Stresstest",
"settings.stress_test_help": "Starte ein Bot-gesteuertes Spiel mit einer sehr hohen Anzahl an Münzen, um die Leistungsgrenzen deines Geräts zu testen.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "Wenn du ein neues Spiel beginnst, wird dir eine dieser Vergünstigungen angeboten. Klicke auf eine Vergünstigung, um sie auszuschließen.",
"starting_perks.help": "Wähle mögliche Start-Upgrades",
"starting_perks.random": "Alle Vorteile wurden entfernt, die Auswahl erfolgt nach dem Zufallsprinzip.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Weicher Reset",
"upgrades.soft_reset.tooltip": "Combo-Rückstellungen halten {{percent}}%",
"upgrades.soft_reset.verbose_description": "Begrenzen Sie die Auswirkungen eines Combo-Resets.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "Klebrige Münzen",
"upgrades.sticky_coins.tooltip": "Münzen haften an Steinen der gleichen Farbe",
"upgrades.sticky_coins.verbose_description": "Auf Stufe 2 haften sie an Steinen jeder Farbe",

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Beeps, bloops and brrrr",
"settings.stress_test": "Stress test",
"settings.stress_test_help": "Start a bot controlled game with a very high number of coins, to test the performance limits of your device.",
"settings.touch_delayed_start": "Delayed start on mobile",
"settings.touch_delayed_start_help": "3,2,1,Go at the start of a level",
"starting_perks.checked": "When you start a new game, one of those perks will be given to you. Click a perk to exclude it. ",
"starting_perks.help": "Choose possible starting upgrades",
"starting_perks.random": "All benefits have been removed, the choice will be random.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Soft reset",
"upgrades.soft_reset.tooltip": "Keep {{percent}}% of your combo when it resets",
"upgrades.soft_reset.verbose_description": "Limit the impact of a combo reset.",
"upgrades.steering.name": "Steering",
"upgrades.steering.tooltip": "Balls turn when puck moves",
"upgrades.steering.verbose_description": "The change of puck location directly influences the direction of the balls's movement. At level 2+, you get a line showing you ball's directions.",
"upgrades.sticky_coins.name": "Sticky coins",
"upgrades.sticky_coins.tooltip": "Coins stick to bricks of the same color",
"upgrades.sticky_coins.verbose_description": "At level 2, they stick to bricks of any color",

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Pitidos, bloops y brrrr",
"settings.stress_test": "Prueba de estrés",
"settings.stress_test_help": "Inicie un juego controlado por bot con una cantidad muy alta de monedas para probar los límites de rendimiento de su dispositivo.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "Al empezar una partida nueva, recibirás una de esas ventajas. Haz clic en una ventaja para excluirla.",
"starting_perks.help": "Elija posibles actualizaciones iniciales",
"starting_perks.random": "Se han eliminado todos los beneficios, la elección será aleatoria.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Restablecimiento progresivo",
"upgrades.soft_reset.tooltip": "Al reiniciar el combo se conserva el {{percent}}% de los puntos",
"upgrades.soft_reset.verbose_description": "Limita el impacto de un reinicio de combo.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "Monedas pegajosas",
"upgrades.sticky_coins.tooltip": "Las monedas se adhieren a los ladrillos del mismo color.",
"upgrades.sticky_coins.verbose_description": "En el nivel 2, se adhieren a ladrillos de cualquier color.",

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Bips, bloops et brrrr",
"settings.stress_test": "Test de stress",
"settings.stress_test_help": "Démarrez un jeu contrôlé par un bot avec un nombre très élevé de pièces, pour tester les limites de performances de votre appareil.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "Lorsque vous démarrez une nouvelle partie, l'un de ces avantages vous sera attribué. Cliquez sur un avantage pour l'exclure.",
"starting_perks.help": "Choisissez les avantages de départ",
"starting_perks.random": "Tous les avantages ont été retirés, le choix sera aléatoire.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Réinitialisation progressive",
"upgrades.soft_reset.tooltip": "La remise à zéro du combo conserve {{percent}}% des points",
"upgrades.soft_reset.verbose_description": "Limite l'impact d'une réinitialisation du combo.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "Pièces collantes",
"upgrades.sticky_coins.tooltip": "Les pièces collent aux briques de la même couleur",
"upgrades.sticky_coins.verbose_description": "Au niveau 2, ils collent aux briques de n'importe quelle couleur",

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Бипы, блепы и брррр",
"settings.stress_test": "Стресс-тест",
"settings.stress_test_help": "Запустите игру, управляемую ботом, с очень большим количеством монет, чтобы проверить пределы производительности вашего устройства.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "Когда вы начнете новую игру, вам будет дано одно из этих преимуществ. Щелкните по перку, чтобы исключить его.",
"starting_perks.help": "Выберите возможные стартовые апгрейды",
"starting_perks.random": "Все преимущества были убраны, выбор будет случайным.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Мягкий сброс",
"upgrades.soft_reset.tooltip": "Комбо-сброс сохраняет {{percent}}%",
"upgrades.soft_reset.verbose_description": "Ограничьте влияние комбо-сброса.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "Липкие монеты",
"upgrades.sticky_coins.tooltip": "Монеты прилипают к кирпичам того же цвета.",
"upgrades.sticky_coins.verbose_description": "На уровне 2 они прилипают к кирпичам любого цвета.",

View file

@ -228,6 +228,8 @@
"settings.sounds_help": "Bipler, blooplar ve brrrr",
"settings.stress_test": "Stres testi",
"settings.stress_test_help": "Cihazınızın performans sınırlarını test etmek için çok sayıda jetonla bot kontrollü bir oyun başlatın.",
"settings.touch_delayed_start": "",
"settings.touch_delayed_start_help": "",
"starting_perks.checked": "Yeni bir oyuna başladığınızda, bu avantajlardan biri size verilecektir. Bir avantajı hariç tutmak için tıklayın.",
"starting_perks.help": "Olası başlangıç yükseltmelerini seçin",
"starting_perks.random": "Tüm avantajlar kaldırıldı, seçim rastgele olacak.",
@ -418,6 +420,9 @@
"upgrades.soft_reset.name": "Yumuşak sıfırlama",
"upgrades.soft_reset.tooltip": "Kombo sıfırlamaları % {{percent}}tutar",
"upgrades.soft_reset.verbose_description": "Bir kombo sıfırlamanın etkisini sınırlayın.",
"upgrades.steering.name": "",
"upgrades.steering.tooltip": "",
"upgrades.steering.verbose_description": "",
"upgrades.sticky_coins.name": "Yapışkan paralar",
"upgrades.sticky_coins.tooltip": "Madeni paralar aynı renkteki tuğlalara yapışıyor",
"upgrades.sticky_coins.verbose_description": "2. seviyede, herhangi bir renkteki tuğlalara yapışırlar",

View file

@ -19,6 +19,11 @@ export const options = {
name: t("settings.mobile"),
help: t("settings.mobile_help"),
},
touch_delayed_start: {
default: true,
name: t("settings.touch_delayed_start"),
help: t("settings.touch_delayed_start_help"),
},
basic: {
default: false,
name: t("settings.basic"),

View file

@ -425,7 +425,10 @@ export function render(gameState: GameState) {
ctx.setLineDash(emptyArray);
}
ctx.globalAlpha = 1;
if (gameState.perks.clairvoyant && gameState.ballStickToPuck) {
if (
(gameState.perks.clairvoyant && gameState.ballStickToPuck) ||
(gameState.perks.steering > 1 && !gameState.ballStickToPuck)
) {
ctx.strokeStyle = gameState.ballsColor;
ctx.beginPath();
ctx.moveTo(ball.x, ball.y);

View file

@ -2,8 +2,8 @@ let div = document.createElement("div");
div.classList = "hidden toast";
document.body.appendChild(div);
let timeout: NodeJS.Timeout | undefined;
export function toast(html: string) {
div.classList = "toast visible";
export function toast(html: string, className = "") {
div.classList = "toast visible " + className;
div.innerHTML = html;
if (timeout) {
clearTimeout(timeout);

View file

@ -952,4 +952,15 @@ export const rawUpgrades = [
percent: lvl * 50,
}),
},
{
category: categories.advanced,
requires: "",
threshold: 250000,
gift: false,
id: "steering",
max: 4,
name: t("upgrades.steering.name"),
help: (lvl: number) => t("upgrades.steering.tooltip"),
fullHelp: (lvl: number) => t("upgrades.steering.verbose_description"),
},
] as const;