mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-21 20:46:14 -04:00
Lives just save the ball once and show as a line.
This commit is contained in:
parent
752a5713d7
commit
2b9bb30000
5 changed files with 6626 additions and 2805 deletions
|
@ -17,6 +17,7 @@ set -x
|
|||
# the version number is just a unix timestamp in minutes
|
||||
versionCode=$(($(date +%s) / 60))
|
||||
|
||||
|
||||
# Replace the version code and name in gradle for fdroid and play store
|
||||
sed -i -e "s/^[[:space:]]*versionCode = .*/ versionCode = $versionCode/" \
|
||||
-e "s/^[[:space:]]*versionName = .*/ versionName = \"$versionCode\"/" \
|
||||
|
@ -27,6 +28,9 @@ echo "\"$versionCode\"" > src/version.json
|
|||
# remove all exif metadata from pictures, because i think fdroid doesn't like that. odd
|
||||
find -name '*.jp*g' -o -name '*.png' | xargs exiftool -all=
|
||||
|
||||
# expose the git log to the app itself
|
||||
git log --pretty=format:' %s' > src/git-log.txt
|
||||
|
||||
npx prettier --write src/
|
||||
|
||||
npm run build
|
||||
|
|
3845
dist/index.html
vendored
3845
dist/index.html
vendored
File diff suppressed because one or more lines are too long
5235
src/game.ts
5235
src/game.ts
File diff suppressed because it is too large
Load diff
124
src/git-log.txt
Normal file
124
src/git-log.txt
Normal file
|
@ -0,0 +1,124 @@
|
|||
Lives just save the ball once and show as a line.
|
||||
Deduplicated backgrounds to make the game smaller
|
||||
wip
|
||||
Ignore build files
|
||||
Build and deploy of version 29028296
|
||||
Updated to use typescript strict typing
|
||||
wip
|
||||
Build and deploy of version 29022953
|
||||
Adjustments to creative mode
|
||||
Creative mode, cleanup loop fix
|
||||
Farming points with respawn should be fixed, the sapper-generated bombs no longer count as a broken brick
|
||||
Typed existing game.ts
|
||||
Tried to use ts to catch bugs, it's pretty useless for now.
|
||||
wip
|
||||
Build and deploy of version 29020191
|
||||
Build and deploy of version 29020186
|
||||
Build and deploy of version 29020162
|
||||
Build and deploy of version 29020161
|
||||
Build and deploy of version 29020161
|
||||
Build and deploy of version 29020156
|
||||
Move to parcel
|
||||
Ingnore parcel files
|
||||
When trying a perk or level, actually play the run
|
||||
Automatic deploy 29019801
|
||||
Try to get the horizontally bouncing balls unstuck, and allow ball to go fast when tethered
|
||||
Avoid caching angles of coins that look the same, more coin angles
|
||||
wip
|
||||
Automatic deploy 29019704
|
||||
Better handling of large combo
|
||||
Automatic deploy 29018692
|
||||
Automatic deploy 29017278
|
||||
Avoid fullscreen on ctrl+f
|
||||
Automatic deploy 29017275
|
||||
Added a palette for bricks color
|
||||
wip
|
||||
wip
|
||||
Automatic deploy 29017191
|
||||
Automatic deploy 29015398
|
||||
Added random patterns as background of levels instead of repeating their name
|
||||
Automatic deploy 29015054
|
||||
Fix : bg color of dollar level, puck width and coins centering
|
||||
Automatic deploy 29014379
|
||||
Automatic deploy 29014360
|
||||
Removed gif recording, increased webm recording resolution
|
||||
Feedback
|
||||
Automatic deploy 29014300
|
||||
Removed console.log that were triggering GC, and made all balls the same color to avoid another memory leak and simplify code
|
||||
Automatic deploy 29014045
|
||||
Typos
|
||||
Automatic deploy 29013936
|
||||
Explanation for perks in help, coins speed limit to avoid clipping, adapted coin spawn rate
|
||||
Automatic deploy 29011564
|
||||
Track total play time and added meta description
|
||||
Automatic deploy 29011519
|
||||
Automatic deploy 29011397
|
||||
Typo
|
||||
Automatic deploy 29011331
|
||||
Pause abuse delay, f for fullscreen toggle, keyboard support
|
||||
Automatic deploy 29010156
|
||||
Automatic deploy 29010123
|
||||
Automatic deploy 29010003
|
||||
Automatic deploy 29009984
|
||||
Automatic deploy 29009918
|
||||
Automatic deploy 29008583
|
||||
Automatic deploy 29008176
|
||||
Automatic deploy 29007858
|
||||
wip
|
||||
Automatic deploy 29007301
|
||||
Automatic deploy 29007124
|
||||
Automatic deploy 29005750
|
||||
Automatic deploy 29005697
|
||||
Added statistics (the last ones weren't actually recording anything)
|
||||
Automatic deploy 29002316
|
||||
Automatic deploy 29002312
|
||||
Automatic deploy 29002304
|
||||
Automatic deploy 29002302
|
||||
Automatic deploy 29002301
|
||||
Automatic deploy 29002295
|
||||
wip
|
||||
Automatic deploy 29000827
|
||||
Automatic deploy 29000798
|
||||
Automatic deploy 29000794
|
||||
Automatic deploy 28999986
|
||||
Wind perk
|
||||
wip
|
||||
Automatic deploy 28999931
|
||||
wip
|
||||
Automatic deploy 28999417
|
||||
wip
|
||||
wip
|
||||
Automatic deploy 28998184
|
||||
Adjusted neon effect, more screenshake after bigger_explosion perk is chosen
|
||||
Automatic deploy 28996852
|
||||
Automatic deploy 28996655
|
||||
Automatic deploy 28996651
|
||||
wip
|
||||
Automatic deploy 28996415
|
||||
Fixed small issues
|
||||
wip
|
||||
wip
|
||||
wip
|
||||
wip
|
||||
wip
|
||||
Automatic deploy 28994348
|
||||
wip
|
||||
wip
|
||||
wip
|
||||
Added some fastlane screenshots in repo for fdroid
|
||||
Automatic deploy 28994244
|
||||
Automatic deploy 28994243
|
||||
wip
|
||||
Automatic deploy 28994240
|
||||
wip
|
||||
Automatic deploy 28994204
|
||||
wip
|
||||
wip
|
||||
Automatic deploy 28994174
|
||||
wip
|
||||
Automatic deploy 28994149
|
||||
Automatic deploy 28994147
|
||||
wip
|
||||
wip
|
||||
Added GPL3 license
|
||||
Initial commit
|
223
src/sounds.ts
Normal file
223
src/sounds.ts
Normal file
|
@ -0,0 +1,223 @@
|
|||
import {gameZoneWidthRoundedUp, isSettingOn, offsetX, offsetXRoundedDown} from "./game";
|
||||
|
||||
export const sounds = {
|
||||
wallBeep: (pan: number) => {
|
||||
if (!isSettingOn("sound")) return;
|
||||
createSingleBounceSound(800, pixelsToPan(pan));
|
||||
},
|
||||
|
||||
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
||||
if (!isSettingOn("sound")) return;
|
||||
let delta = 0;
|
||||
if (!isNaN(lastComboPlayed)) {
|
||||
if (lastComboPlayed < combo) delta = 1;
|
||||
if (lastComboPlayed > combo) delta = -1;
|
||||
}
|
||||
playShepard(delta, pixelsToPan(x), volume);
|
||||
lastComboPlayed = combo;
|
||||
},
|
||||
|
||||
comboDecrease() {
|
||||
if (!isSettingOn("sound")) return;
|
||||
playShepard(-1, 0.5, 0.5);
|
||||
},
|
||||
coinBounce: (pan: number, volume: number) => {
|
||||
if (!isSettingOn("sound")) return;
|
||||
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
||||
},
|
||||
explode: (pan: number) => {
|
||||
if (!isSettingOn("sound")) return;
|
||||
createExplosionSound(pixelsToPan(pan));
|
||||
},
|
||||
lifeLost(pan:number){
|
||||
if (!isSettingOn("sound")) return;
|
||||
createShatteredGlassSound(pixelsToPan(pan))
|
||||
},
|
||||
|
||||
coinCatch(pan: number) {
|
||||
if (!isSettingOn("sound")) return;
|
||||
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
||||
},
|
||||
};
|
||||
|
||||
// How to play the code on the leftconst context = new window.AudioContext();
|
||||
let audioContext: AudioContext, audioRecordingTrack: MediaStreamAudioDestinationNode;
|
||||
|
||||
export function getAudioContext() {
|
||||
if (!audioContext) {
|
||||
if (!isSettingOn('sound')) return null
|
||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
audioRecordingTrack = audioContext.createMediaStreamDestination();
|
||||
}
|
||||
return audioContext;
|
||||
}
|
||||
|
||||
export function getAudioRecordingTrack() {
|
||||
getAudioContext()
|
||||
return audioRecordingTrack
|
||||
}
|
||||
|
||||
function createSingleBounceSound(
|
||||
baseFreq = 800,
|
||||
pan = 0.5,
|
||||
volume = 1,
|
||||
duration = 0.1,
|
||||
type: OscillatorType = "sine",
|
||||
) {
|
||||
const context = getAudioContext();
|
||||
if (!context) return
|
||||
const oscillator = createOscillator(context, baseFreq, type);
|
||||
|
||||
// Create a gain node to control the volume
|
||||
const gainNode = context.createGain();
|
||||
oscillator.connect(gainNode);
|
||||
|
||||
// Create a stereo panner node for left-right panning
|
||||
const panner = context.createStereoPanner();
|
||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||
gainNode.connect(panner);
|
||||
panner.connect(context.destination);
|
||||
panner.connect(audioRecordingTrack);
|
||||
|
||||
// Set up the gain envelope to simulate the impact and quick decay
|
||||
gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.001,
|
||||
context.currentTime + duration,
|
||||
); // Quick decay
|
||||
|
||||
// Start the oscillator
|
||||
oscillator.start(context.currentTime);
|
||||
|
||||
// Stop the oscillator after the decay
|
||||
oscillator.stop(context.currentTime + duration);
|
||||
}
|
||||
|
||||
let noiseBuffer: AudioBuffer;
|
||||
|
||||
function getNoiseBuffer(context:AudioContext) {
|
||||
|
||||
if (!noiseBuffer) {
|
||||
const bufferSize = context.sampleRate * 2; // 2 seconds
|
||||
noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
|
||||
const output = noiseBuffer.getChannelData(0);
|
||||
|
||||
// Fill the buffer with random noise
|
||||
for (let i = 0; i < bufferSize; i++) {
|
||||
output[i] = Math.random() * 2 - 1;
|
||||
}
|
||||
}
|
||||
return noiseBuffer
|
||||
}
|
||||
|
||||
function createExplosionSound(pan = 0.5) {
|
||||
const context = getAudioContext();
|
||||
if (!context) return
|
||||
// Create an audio buffer
|
||||
|
||||
|
||||
// Create a noise source
|
||||
const noiseSource = context.createBufferSource();
|
||||
noiseSource.buffer = getNoiseBuffer(context);
|
||||
|
||||
// Create a gain node to control the volume
|
||||
const gainNode = context.createGain();
|
||||
noiseSource.connect(gainNode);
|
||||
|
||||
// Create a filter to shape the explosion sound
|
||||
const filter = context.createBiquadFilter();
|
||||
filter.type = "lowpass";
|
||||
filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
|
||||
gainNode.connect(filter);
|
||||
|
||||
// Create a stereo panner node for left-right panning
|
||||
const panner = context.createStereoPanner();
|
||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
|
||||
|
||||
// Connect filter to panner and then to the destination (speakers)
|
||||
filter.connect(panner);
|
||||
panner.connect(context.destination);
|
||||
panner.connect(audioRecordingTrack);
|
||||
|
||||
// Ramp down the gain to simulate the explosion's fade-out
|
||||
gainNode.gain.setValueAtTime(1, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
|
||||
|
||||
// Lower the filter frequency over time to create the "explosive" effect
|
||||
filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
|
||||
|
||||
// Start the noise source
|
||||
noiseSource.start(context.currentTime);
|
||||
|
||||
// Stop the noise source after the sound has played
|
||||
noiseSource.stop(context.currentTime + 1);
|
||||
}
|
||||
|
||||
function pixelsToPan(pan: number) {
|
||||
return Math.max(0, Math.min(1, (pan - offsetXRoundedDown) / gameZoneWidthRoundedUp));
|
||||
}
|
||||
|
||||
let lastComboPlayed = NaN,
|
||||
shepard = 6;
|
||||
|
||||
function playShepard(delta: number, pan: number, volume: number) {
|
||||
const shepardMax = 11,
|
||||
factor = 1.05945594920268,
|
||||
baseNote = 392;
|
||||
shepard += delta;
|
||||
if (shepard > shepardMax) shepard = 0;
|
||||
if (shepard < 0) shepard = shepardMax;
|
||||
|
||||
const play = (note: number) => {
|
||||
const freq = baseNote * Math.pow(factor, note);
|
||||
const diff = Math.abs(note - shepardMax * 0.5);
|
||||
const maxDistanceToIdeal = 1.5 * shepardMax;
|
||||
const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
|
||||
createSingleBounceSound(freq, pan, vol);
|
||||
return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
|
||||
};
|
||||
|
||||
play(1 + shepardMax + shepard);
|
||||
play(shepard);
|
||||
play(-1 - shepardMax + shepard);
|
||||
}
|
||||
|
||||
function createShatteredGlassSound(pan:number) {
|
||||
const context = getAudioContext();
|
||||
if (!context) return
|
||||
const oscillators = [
|
||||
createOscillator(context, 3000, 'square'),
|
||||
createOscillator(context, 4500, 'square'),
|
||||
createOscillator(context, 6000, 'square')
|
||||
];
|
||||
const gainNode = context.createGain();
|
||||
const noiseSource = context.createBufferSource();
|
||||
noiseSource.buffer = getNoiseBuffer(context);
|
||||
|
||||
oscillators.forEach(oscillator => oscillator.connect(gainNode));
|
||||
noiseSource.connect(gainNode);
|
||||
gainNode.gain.setValueAtTime(0.2, context.currentTime);
|
||||
oscillators.forEach(oscillator => oscillator.start());
|
||||
noiseSource.start();
|
||||
oscillators.forEach(oscillator => oscillator.stop(context.currentTime + 0.2));
|
||||
noiseSource.stop(context.currentTime + 0.2);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.2);
|
||||
|
||||
|
||||
// Create a stereo panner node for left-right panning
|
||||
const panner = context.createStereoPanner();
|
||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||
gainNode.connect(panner);
|
||||
panner.connect(context.destination);
|
||||
panner.connect(audioRecordingTrack);
|
||||
|
||||
gainNode.connect(panner);
|
||||
}
|
||||
|
||||
// Helper function to create an oscillator with a specific frequency
|
||||
function createOscillator(context:AudioContext, frequency:number, type:OscillatorType) {
|
||||
const oscillator = context.createOscillator();
|
||||
oscillator.type =type
|
||||
oscillator.frequency.setValueAtTime(frequency, context.currentTime);
|
||||
return oscillator;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue