Automatic deploy 29010123

This commit is contained in:
Renan LE CARO 2025-02-26 23:03:12 +01:00
parent df04c652db
commit 1eae36efcb
5 changed files with 61 additions and 35 deletions

View file

@ -175,7 +175,7 @@ The "engine" could be better
- escape to close menu - escape to close menu
- see how to do fullscreen on ios, or at least explain to do aA/hide toolbars - see how to do fullscreen on ios, or at least explain to do aA/hide toolbars
- experiment with showing the combo somewhere else, maybe top center, maybe instead of score. - experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
- make coins look,sound and roll like coins - make coins look,sound and roll like coins. Back to colored when coins stain bricks is active
- limit GC by reusing coins and particles - limit GC by reusing coins and particles
- convert captures to mp4 unsing ffmpeg wasm because reddit refuses webm files - convert captures to mp4 unsing ffmpeg wasm because reddit refuses webm files
- few puck bounces = more choices / upgrades - few puck bounces = more choices / upgrades

View file

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

View file

@ -890,7 +890,17 @@ canvas.addEventListener("touchmove", (e) => {
let lastTick = performance.now(); let lastTick = performance.now();
function brickIndex(x, y) { function brickIndex(x, y) {
return getRowColIndex(Math.floor(y / brickWidth), Math.floor((x - offsetX) / brickWidth),); //this worked great but coins got stuck in corner between bricks, will need to rework it
// if(!currentLevelInfo().squared){
//
// const offsetToLeftSide = (x - offsetX) % brickWidth
// const offsetToTopSide = y % brickWidth
// const bricksMargin=12/(12+120)*brickWidth/2
// if(offsetToLeftSide< bricksMargin || offsetToLeftSide>brickWidth-bricksMargin || offsetToTopSide< bricksMargin || offsetToTopSide>brickWidth-bricksMargin ){return -1}
//
// }
//
return getRowColIndex(Math.floor(y / brickWidth), Math.floor((x - offsetX) / brickWidth))
} }
function hasBrick(index) { function hasBrick(index) {
@ -1061,6 +1071,7 @@ function tick() {
coin.vy *= ratio; coin.vy *= ratio;
coin.vx *= ratio; coin.vx *= ratio;
coin.a+=coin.sa
// Gravity // Gravity
coin.vy += delta * coin.weight * 0.8; coin.vy += delta * coin.weight * 0.8;
@ -1090,7 +1101,7 @@ function tick() {
if (typeof hitBrick !== "undefined" || hitBorder) { if (typeof hitBrick !== "undefined" || hitBorder) {
coin.vx *= 0.8; coin.vx *= 0.8;
coin.vy *= 0.8; coin.vy *= 0.8;
coin.sa*=0.9
if (speed > 20 && !playedCoinBounce) { if (speed > 20 && !playedCoinBounce) {
playedCoinBounce = true; playedCoinBounce = true;
sounds.coinBounce(coin.x, 0.2); sounds.coinBounce(coin.x, 0.2);
@ -1585,7 +1596,8 @@ function explodeBrick(index, ball, isExplosion) {
coins.push({ coins.push({
points: 1, points: 1,
color, ...coord, color:perks.metamorphosis ? color: 'gold',
...coord,
previousx: coord.x, previousx: coord.x,
previousy: coord.y, previousy: coord.y,
@ -1594,6 +1606,8 @@ function explodeBrick(index, ball, isExplosion) {
vy: ball.previousvy * (0.5 + Math.random()), vy: ball.previousvy * (0.5 + Math.random()),
sx: 0, sx: 0,
sy: 0, sy: 0,
a:Math.random()*Math.PI*2,
sa:Math.random()-0.5,
weight: 0.8 + Math.random() * 0.2 weight: 0.8 + Math.random() * 0.2
}); });
} }
@ -1826,7 +1840,7 @@ function render() {
ctx.globalAlpha = Math.max(0, Math.min(1, 2 - (elapsed / duration) * 2)); ctx.globalAlpha = Math.max(0, Math.min(1, 2 - (elapsed / duration) * 2));
if (type === "text") { if (type === "text") {
ctx.globalCompositeOperation = "source-over"; ctx.globalCompositeOperation = "source-over";
drawText(ctx, text, color, size, {x, y: y - elapsed / 10}); drawText(ctx, text, color, size, x, y - elapsed / 10);
} else if (type === "particle") { } else if (type === "particle") {
ctx.globalCompositeOperation = "screen"; ctx.globalCompositeOperation = "screen";
drawBall(ctx, color, size, x, y); drawBall(ctx, color, size, x, y);
@ -1838,7 +1852,7 @@ function render() {
ctx.globalAlpha = 1; ctx.globalAlpha = 1;
ctx.globalCompositeOperation = "source-over"; ctx.globalCompositeOperation = "source-over";
coins.forEach((coin) => { coins.forEach((coin) => {
if (!coin.destroyed) drawCoin(ctx, coin.color, coinSize, coin, level.color || 'black'); if (!coin.destroyed) drawCoin(ctx, coin.color, coinSize, coin.x,coin.y, level.color || 'black', coin.a);
}); });
@ -1872,9 +1886,9 @@ function render() {
if (combo > 1) { if (combo > 1) {
ctx.globalCompositeOperation = "source-over"; ctx.globalCompositeOperation = "source-over";
drawText(ctx, "x " + combo, !level.black_puck ? '#000' : '#FFF', puckHeight, { drawCoin(ctx, 'gold', coinSize, puck-coinSize, gameZoneHeight - puckHeight / 2, !level.black_puck ? '#FFF' : '#000', 0 )
x: puck, y: gameZoneHeight - puckHeight / 2, drawText(ctx, "x " + combo, !level.black_puck ? '#000' : '#FFF', puckHeight,
}); puck, gameZoneHeight - puckHeight / 2,true);
} }
// Borders // Borders
ctx.fillStyle = puckColor; ctx.fillStyle = puckColor;
@ -1887,9 +1901,9 @@ function render() {
if (isSettingOn("mobile-mode")) { if (isSettingOn("mobile-mode")) {
ctx.fillRect(offsetXRoundedDown, gameZoneHeight, gameZoneWidthRoundedUp, 1); ctx.fillRect(offsetXRoundedDown, gameZoneHeight, gameZoneWidthRoundedUp, 1);
if (!running) { if (!running) {
drawText(ctx, "Press and hold here to play", puckColor, puckHeight, { drawText(ctx, "Press and hold here to play", puckColor, puckHeight,
x: canvas.width / 2, y: gameZoneHeight + (canvas.height - gameZoneHeight) / 2, canvas.width / 2, gameZoneHeight + (canvas.height - gameZoneHeight) / 2,
}); );
} }
} }
@ -1981,10 +1995,11 @@ function drawBall(ctx, color, width, x, y) {
ctx.drawImage(cachedGraphics[key], Math.round(x - width / 2), Math.round(y - width / 2),); ctx.drawImage(cachedGraphics[key], Math.round(x - width / 2), Math.round(y - width / 2),);
} }
function drawCoin(ctx, color, width, ball, bg) { function drawCoin(ctx, color, size, x,y, bg,rawAngle) {
const key = "coin with halo" + "_" + color + "_" + width + '_' + bg; if(isNaN(rawAngle)) debugger
const angle= Math.round(((rawAngle%(Math.PI*2))+Math.PI*2 )% Math.PI*2 * 16) / 16
const key = "coin with halo" + "_" + color + "_" + size + '_' + bg + '_'+angle;
const size = width * 3;
if (!cachedGraphics[key]) { if (!cachedGraphics[key]) {
const can = document.createElement("canvas"); const can = document.createElement("canvas");
can.width = size; can.width = size;
@ -1994,16 +2009,29 @@ function drawCoin(ctx, color, width, ball, bg) {
// coin // coin
canctx.beginPath(); canctx.beginPath();
canctx.arc(size / 2, size / 2, width / 2, 0, 2 * Math.PI); canctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
canctx.fillStyle = color; canctx.fillStyle = color;
canctx.fill(); canctx.fill();
canctx.strokeStyle = bg; canctx.strokeStyle = bg;
canctx.stroke(); canctx.stroke();
canctx.beginPath();
canctx.arc(size / 2, size / 2, size / 2 * 0.6, 0, 2 * Math.PI);
canctx.fillStyle = 'rgba(255,255,255,0.5)';
canctx.fill();
canctx.translate(size / 2, size / 2);
canctx.rotate(angle);
canctx.translate(-size / 2, -size / 2);
canctx.globalCompositeOperation='multiply'
drawText(canctx, '$', color, size-2,size / 2, size / 2)
drawText(canctx, '$', color, size-2,size / 2, size / 2)
cachedGraphics[key] = can; cachedGraphics[key] = can;
} }
ctx.drawImage(cachedGraphics[key], Math.round(ball.x - size / 2), Math.round(ball.y - size / 2),); ctx.drawImage(cachedGraphics[key], Math.round(x - size / 2), Math.round(y - size / 2));
} }
function drawFuzzyBall(ctx, color, width, x, y) { function drawFuzzyBall(ctx, color, width, x, y) {
@ -2034,8 +2062,6 @@ function drawBrick(ctx, color, x, y, squared) {
const width = brx - tlx, height = bry - tly; const width = brx - tlx, height = bry - tly;
const key = "brick" + color + "_" + width + "_" + height + '_' + squared const key = "brick" + color + "_" + width + "_" + height + '_' + squared
// "_" +
// isSettingOn("rounded-bricks");
if (!cachedGraphics[key]) { if (!cachedGraphics[key]) {
const can = document.createElement("canvas"); const can = document.createElement("canvas");
@ -2107,8 +2133,8 @@ function drawIMG(ctx, img, size, x, y) {
ctx.drawImage(cachedGraphics[key], Math.round(x - size / 2), Math.round(y - size / 2),); ctx.drawImage(cachedGraphics[key], Math.round(x - size / 2), Math.round(y - size / 2),);
} }
function drawText(ctx, text, color, fontSize, {x, y}) { function drawText(ctx, text, color, fontSize, x, y,left=false) {
const key = "text" + text + "_" + color + "_" + fontSize; const key = "text" + text + "_" + color + "_" + fontSize+'_'+left;
if (!cachedGraphics[key]) { if (!cachedGraphics[key]) {
const can = document.createElement("canvas"); const can = document.createElement("canvas");
@ -2116,15 +2142,15 @@ function drawText(ctx, text, color, fontSize, {x, y}) {
can.height = fontSize; can.height = fontSize;
const canctx = can.getContext("2d"); const canctx = can.getContext("2d");
canctx.fillStyle = color; canctx.fillStyle = color;
canctx.textAlign = "center"; canctx.textAlign = left ? 'left':"center"
canctx.textBaseline = "middle"; canctx.textBaseline = "middle";
canctx.font = fontSize + "px monospace"; canctx.font = fontSize + "px monospace";
canctx.fillText(text, can.width / 2, can.height / 2, can.width); canctx.fillText(text, left ? 0 : can.width / 2, can.height / 2, can.width);
cachedGraphics[key] = can; cachedGraphics[key] = can;
} }
ctx.drawImage(cachedGraphics[key], Math.round(x - cachedGraphics[key].width / 2), Math.round(y - cachedGraphics[key].height / 2),); ctx.drawImage(cachedGraphics[key], left ? x:Math.round(x - cachedGraphics[key].width / 2), Math.round(y - cachedGraphics[key].height / 2),);
} }
function pixelsToPan(pan) { function pixelsToPan(pan) {
@ -2176,7 +2202,7 @@ const sounds = {
}, },
coinBounce: (pan, volume) => { coinBounce: (pan, volume) => {
if (!isSettingOn("sound")) return; if (!isSettingOn("sound")) return;
createSingleBounceSound(1200, pixelsToPan(pan), volume); createSingleBounceSound(1200, pixelsToPan(pan), volume,0.1,'triangle');
}, explode: (pan) => { }, explode: (pan) => {
if (!isSettingOn("sound")) return; if (!isSettingOn("sound")) return;
createExplosionSound(pixelsToPan(pan)); createExplosionSound(pixelsToPan(pan));
@ -2185,7 +2211,7 @@ const sounds = {
createRevivalSound(500); createRevivalSound(500);
}, coinCatch(pan) { }, coinCatch(pan) {
if (!isSettingOn("sound")) return; if (!isSettingOn("sound")) return;
createSingleBounceSound(440, pixelsToPan(pan), .8) createSingleBounceSound(900, pixelsToPan(pan), .8,0.1,'triangle')
} }
}; };
@ -2200,14 +2226,14 @@ function getAudioContext() {
return audioContext; return audioContext;
} }
function createSingleBounceSound(baseFreq = 800, pan = 0.5, volume = 1, duration = 0.1,) { function createSingleBounceSound(baseFreq = 800, pan = 0.5, volume = 1, duration = 0.1, type = "sine") {
const context = getAudioContext(); const context = getAudioContext();
// Frequency for the metal "ping" // Frequency for the metal "ping"
const baseFrequency = baseFreq; // Hz const baseFrequency = baseFreq; // Hz
// Create an oscillator for the impact sound // Create an oscillator for the impact sound
const oscillator = context.createOscillator(); const oscillator = context.createOscillator();
oscillator.type = "sine"; oscillator.type=type;
oscillator.frequency.setValueAtTime(baseFrequency, context.currentTime); oscillator.frequency.setValueAtTime(baseFrequency, context.currentTime);
// Create a gain node to control the volume // Create a gain node to control the volume

View file

@ -8,17 +8,17 @@
/> />
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Breakout 71</title> <title>Breakout 71</title>
<link rel="stylesheet" href="style.css?v=29010003" /> <link rel="stylesheet" href="style.css?v=29010123" />
<link rel="icon" href="./icon.svg" /> <link rel="icon" href="./icon.svg" />
</head> </head>
<body> <body>
<button id="menu"><span> menu</span></button> <button id="menu"><span> menu</span></button>
<button id="score"></button> <button id="score"></button>
<canvas id="game"></canvas> <canvas id="game"></canvas>
<script>window.appVersion="?v=29010003".slice(3)</script> <script>window.appVersion="?v=29010123".slice(3)</script>
<script src="gif.js"></script> <script src="gif.js"></script>
<script src="levels.js?v=29010003"></script> <script src="levels.js?v=29010123"></script>
<script src="game.js?v=29010003"></script> <script src="game.js?v=29010123"></script>
</body> </body>

View file

@ -272,7 +272,7 @@ body.black_puck #menu {
position: absolute; position: absolute;
top: 40px; top: 40px;
left: 40px; left: 40px;
max-width: calc((100vw - 450px )/2 - 80px);
} }
} }