Generate sound effects and background music for good old-fashioned mini-games

Overview

good-old-game-sound-generator (DEMO)

Generate sound effects and background music for good old-fashioned mini-games. Powered by magenta.js and jsfx.

How to generate background music

  1. Open the DEMO page.

  2. (Optional) Input the base music for the generation in MML (Music Macro Language) at the bottom of the screen.

  3. Click the 'Generate' button.

How to use the generated music in your game

  1. On the Demo page, click the 'Copy to clipboard' button to copy the MML JSON data to your clipboard.

  2. Load dist/ggg.umd.js. See a template html file for details.

  3. Call the ggg.playMml function with the JSON in the clipboard as the first argument.

Sample game

Sample code

BALL TOUR source code

{ s.pos.x += player.vx; s.pos.y += s.vy; if (s.pos.y < 10 || s.pos.y > 80) { s.vy *= -1; } if (text("*", s.pos).isColliding.char.d) { return true; } return s.pos.x > 103; }); const py = player.pos.y; player.yAngle += difficulty * 0.05; player.pos.y = sin(player.yAngle) * 30 + 50; player.ticks += clamp((py - player.pos.y) * 9 + 1, 0, 9); if (input.isJustPressed) { // Play the `select` sound effect. ggg.playSoundEffect("select"); } player.vx = (input.isPressed ? 1 : 0.1) * difficulty; char(addWithCharCode("a", floor(player.ticks / 50) % 2), player.pos); color("red"); if (char("c", player.pos.x, player.pos.y - 6).isColliding.text["*"]) { // Play the `explosion` sound effect. ggg.playSoundEffect("explosion"); gameOver(); } nextBallDist -= player.vx; if (nextBallDist < 0) { const p = vec(-3, rnd(20, 70)); color("transparent"); if (char("c", p).isColliding.text["*"]) { nextBallDist += 9; } else { balls.push(p); nextBallDist += rnd(25, 64); } } color("green"); remove(balls, (b) => { b.x += player.vx; const c = char("c", b).isColliding.char; if (c.a || c.b || c.c) { addScore(floor(multiplier), player.pos); multiplier += 10; // Play the `coin` sound effect. ggg.playSoundEffect("coin"); return true; } return b.x > 103; }); multiplier = clamp(multiplier - 0.02 * difficulty, 1, 999); color("black"); text(`x${floor(multiplier)}`, 3, 9); // The `update` function needs to be called at regular intervals. ggg.update(); } function gameOver() { // Stop BGM at the end of the game. ggg.stopMml(); end(); } function init() { // Initialize the library by giving a random number seed for // sound effect generation as an argument. ggg.init(6); ["mousedown", "touchstart", "mouseup", "touchend", "keydown"].forEach((e) => { window.addEventListener(e, () => { // Calling the `startAudio` function from within the event handler of // a user operation will enable audio. ggg.startAudio(); }); }); } window.addEventListener("load", init); // MML JSON data for BGM. const bgm = { // ... snip ....">
title = "BALL TOUR";
// ... snip ....
options = {
  // Disable the audio feature of `crisp-game-lib`.
  isSoundEnabled: false,
  theme: "dark",
  isReplayEnabled: true,
};

/** @type {{pos: Vector, yAngle: number, vx: number, ticks: number}} */
let player;
/** @type {{pos: Vector, vy: number}[]} */
let spikes;
let nextSpikeDist;
/** @type {Vector[]} */
let balls;
let nextBallDist;
let multiplier;

function update() {
  if (!ticks) {
    if (!isReplaying) {
      // Play BGM at the start of the game.
      // The 'bgm' variable is assigned the JSON data copied from the clipboard.
      // The volume can be specified with the second argument. (default = 0.1)
      ggg.playMml(bgm, 0.2);
    }
    player = { pos: vec(90, 50), yAngle: 0, vx: 0, ticks: 0 };
    spikes = [];
    nextSpikeDist = 0;
    balls = [];
    nextBallDist = 9;
    multiplier = 1;
  }
  color("blue");
  rect(0, 90, 99, 9);
  nextSpikeDist -= player.vx;
  if (nextSpikeDist < 0) {
    spikes.push({
      pos: vec(-3, rnd(10, 80)),
      vy: rnd() < 0.2 ? rnds(1, difficulty) * 0.3 : 0,
    });
    nextSpikeDist += rnd(9, 49);
  }
  color("black");
  remove(spikes, (s) => {
    s.pos.x += player.vx;
    s.pos.y += s.vy;
    if (s.pos.y < 10 || s.pos.y > 80) {
      s.vy *= -1;
    }
    if (text("*", s.pos).isColliding.char.d) {
      return true;
    }
    return s.pos.x > 103;
  });
  const py = player.pos.y;
  player.yAngle += difficulty * 0.05;
  player.pos.y = sin(player.yAngle) * 30 + 50;
  player.ticks += clamp((py - player.pos.y) * 9 + 1, 0, 9);
  if (input.isJustPressed) {
    // Play the `select` sound effect.
    ggg.playSoundEffect("select");
  }
  player.vx = (input.isPressed ? 1 : 0.1) * difficulty;
  char(addWithCharCode("a", floor(player.ticks / 50) % 2), player.pos);
  color("red");
  if (char("c", player.pos.x, player.pos.y - 6).isColliding.text["*"]) {
    // Play the `explosion` sound effect.
    ggg.playSoundEffect("explosion");
    gameOver();
  }
  nextBallDist -= player.vx;
  if (nextBallDist < 0) {
    const p = vec(-3, rnd(20, 70));
    color("transparent");
    if (char("c", p).isColliding.text["*"]) {
      nextBallDist += 9;
    } else {
      balls.push(p);
      nextBallDist += rnd(25, 64);
    }
  }
  color("green");
  remove(balls, (b) => {
    b.x += player.vx;
    const c = char("c", b).isColliding.char;
    if (c.a || c.b || c.c) {
      addScore(floor(multiplier), player.pos);
      multiplier += 10;
      // Play the `coin` sound effect.
      ggg.playSoundEffect("coin");
      return true;
    }
    return b.x > 103;
  });
  multiplier = clamp(multiplier - 0.02 * difficulty, 1, 999);
  color("black");
  text(`x${floor(multiplier)}`, 3, 9);
  // The `update` function needs to be called at regular intervals.
  ggg.update();
}

function gameOver() {
  // Stop BGM at the end of the game.
  ggg.stopMml();
  end();
}

function init() {
  // Initialize the library by giving a random number seed for
  // sound effect generation as an argument.
  ggg.init(6);
  ["mousedown", "touchstart", "mouseup", "touchend", "keydown"].forEach((e) => {
    window.addEventListener(e, () => {
      // Calling the `startAudio` function from within the event handler of
      // a user operation will enable audio.
      ggg.startAudio();
    });
  });
}

window.addEventListener("load", init);

// MML JSON data for BGM.
const bgm = {
// ... snip ....

Functions

// Play music described in MML JSON data
function playMml(mmlData: MmlData, volume?: number): void;
// Stop music
function stopMml(): void;
// Play the sound effect
function playSoundEffect(
  type:
    | "coin"
    | "laser"
    | "explosion"
    | "powerUp"
    | "hit"
    | "jump"
    | "select"
    | "synth"
    | "tone"
    | "click"
    | "random",
  seed?: number,
  count?: number,
  volume?: number,
  freq?: number
): void;
// The update function needs to be called every
// certain amount of time (typically 60 times per second)
function update(): void;
// Initialize the library (baseRandomSeed represents
// the seed of the random number used to generate the sound effect)
function init(baseRandomSeed?: number, audioContext?: AudioContext): void;
// The startAudio function needs to be called from within
// the user operation event handler to enable audio playback in the browser.
function startAudio(): void;
// Set the tempo of the music
function setTempo(tempo?: number): void;
// Set the quantize timing of sound effects by the length of the note
function setQuantize(noteLength?: number): void;
You might also like...

Wordle2Townscaper is meant to convert Wordle tweets into Townscaper houses using yellow and green building blocks.

Wordle2Townscaper is meant to convert Wordle tweets into Townscaper houses using yellow and green building blocks.

Wordle2Townscaper Wordle2Townscaper is meant to convert Wordle tweets into Townscaper houses using yellow and green building blocks. You can download

Nov 2, 2022

The Snake Game implemented using HTML, CSS, and JavaScript

The Snake Game implemented using HTML, CSS, and JavaScript

The Snake Game implemented using HTML, CSS, and JavaScript

Mar 2, 2022

A trivia website game based on origin of objects and concepts from around the world

Origin guesser is a quiz/trivia game in which the user is presented a word, object, or flag and offered a series of multiple choice answers to choose from as to the origin of that concept. Unlike other trivia games, this is concentrated only on origin of objects and concepts questions.

Feb 12, 2022

'Neko Mezashi Attack' - a simple but cute action game made with Vite and TypeScript

'Neko Mezashi Attack' is a simple but cute action game made with Vite and TypeScript. This app is packed all resources including style, graphics and audio into 4KB(4096 chars) JS. No runtime libraries or external resources are required.

Dec 1, 2022

I created Worlde with ReactJS, and Tailwind CSS

I created Worlde with ReactJS, and Tailwind CSS

I made Wordle XD Hello everyone 👋 , I am glad to see you here I know it ain't much but this is the game wordle (popular in twitter recently!) I made

Nov 30, 2022

How to build a multiplayer Wordle clone with Liveblocks, Vue, and Vite

How to build a multiplayer Wordle clone with Liveblocks, Vue, and Vite

Wordle Wars This repo shows how to build a multiplayer Wordle clone with Liveblocks, Vue, and Vite. Try it out It's forked from VVowrdle created by Ev

Dec 8, 2022

A recreation of the popular game Wordle with additional modes and features. Made with Svelte in Typescript.

A recreation of the popular game Wordle with additional modes and features. Made with Svelte in Typescript.

A recreation of the popular game Wordle by Josh Wardle (now purchased by the New York Times), with additional modes and features. Hosted on GitHub pag

Dec 11, 2022

Open apps directly in GNOME Software by clicking Install from Flathub and apps.gnome.

Flatline Open apps directly in GNOME Software by clicking Install from Flathub and apps.gnome. Instalation Enable Epiphany extension. Optional if not

Sep 2, 2022

A system for sharing tests between students. In RepoProvas anyone can look up old tests for their subjects and teachers or send old tests to help other students!

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

May 10, 2022

I’m a very useful music bot that can make you play a music with a simple command! I have a lot of good commands that you can have a better experience playing your favorites songs!

I’m a very useful music bot that can make you play a music with a simple command! I have a lot of good commands that you can have a better experience playing your favorites songs!

I’m a very useful music bot that can make you play a music with a simple command! I have a lot of good commands that you can have a better experience playing your favorites songs!

Aug 16, 2022

React-Mini-Projects - Simple React mini-applications

React Mini Projects A Fully Responsive React Application contain these mini apps : Todo App Movie App Budget App Flash Card App Factor App This app wa

Jan 1, 2022

Make friends through music. Discover great sound tracks on Solana and play them with your buddies :dancer:.

Make friends through music. Discover great sound tracks on Solana and play them with your buddies :dancer:.

Acoustic Licious COVID-19 has significantly impacted the mental health of children and adults alike. Globally, the population suffering from lonelines

Oct 28, 2022

Only 90's kids remember... well not really, but these beloved effects that would follow your mouse around will always be classic reminders of the old, beloved internet.

90's Cursor Effects "Knowing the codes" used to be all the rage, I want to bring a few back. A repo of the old effects that inspired creativity and th

Jan 9, 2023

Happy Birthday is a web-based party live background generated by CANVAS powered by JavaScript. This show a lot of random colorize particles in the background.

Happy Birthday is a web-based party live background generated by CANVAS powered by JavaScript. This show a lot of random colorize particles in the background.

Happy BirthDay JS Happy Birthday is a web-based party live background generated by CANVAS powered by JavaScript. This show a lot of random colorize pa

Oct 29, 2022

🟢 Music player app with a modern homepage, fully-fledged music player, search, lyrics, song exploration features, search, popular music around you, worldwide top charts, and much more.

🟢 Music player app with a modern homepage, fully-fledged music player, search, lyrics, song exploration features, search, popular music around you, worldwide top charts, and much more.

Music-player-app see the project here. 1. Key Features 2. Technologies I've used Key Features: 🟢 Fully responsive clean UI. 🟢 Entirely mobile respo

Nov 16, 2022

Advanced Music Bot It is an advance type of discord music bot which plays high quality of music with spotify

Advanced Music Bot It is an advance type of discord music bot which plays high quality of music with spotify, apple music support . You can save your songs and play it. It also has DJ mode system.

Dec 25, 2022

Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

May 18, 2022

Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

May 3, 2022

Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

Jan 3, 2023
Owner
ABA Games
ABA Games
A simple app to show NBA games and scores/details.

NBA Remix A simple app to show NBA games and scores/details. Deployment After having run the create-remix command and selected "Vercel" as a deploymen

Willian Justen 195 Dec 9, 2022
Excalibur.js 1.3k Dec 30, 2022
Typescript based monte-carlo acyclic graph search algorithm for multiplayer games

Typescript based monte-carlo acyclic graph search algorithm for multiplayer games. It can be used in any turn-based strategic multiplayer games.

null 3 Jul 11, 2022
🟩 in case you want to cheat on your wordle games

Wordle Solver How to use Enter each right guess in the first grid Enter all letters that you know aren't in a certain position in the second grid For

James Zhang 2 Feb 7, 2022
Wordle but for music.

?? Soundle ?? A "Wordle for Music" ?? Links ?? ?? Repo · ?? Got Issue . Website ?? Features ?? Built with Axios Express React API Documentation ?? Fut

null 4 Oct 23, 2022
Created by Hashlips! In this repository, Hashlips and ScrawnyViking teach you how to create your unique randomly generated NFTs and launch them on to a free Github Domain where people can buy your NFTs from

Thank You HashLips ?? Upgraded and Articulated by ScrawnyViking aka TWECryptoDev All the code in these repos was created and explained by HashLips - P

TomorrowWontExist 16 Dec 14, 2022
Snake game using pure HTML, CSS and JavaScript with GameBoy look and feel using Nano editor

Snake game using pure HTML, CSS and JavaScript with GameBoy look and feel using Nano editor. 100% commented code in Portuguese

Gabriel Martins 2 Jul 2, 2022
Latin Wordle is a free and open-source project that aims to provide a fun and interactive way to learn Latin.

Latin Wordle Live Game Here Inspiration Latin Wordle is a free and open-source project that aims to provide a fun and interactive way to learn Latin.

null 15 Dec 16, 2022
Quizpetitive - A quiz game to learn new knowledge and terms in the field of project management.

Quizpetitive A quiz game to learn new knowledge and terms in the field of project management. The key element to the success of this project was the c

LMF 1 May 16, 2022
A clone of the popular game Wordle made using React, Typescript, and Tailwind

Wordle Clone Go play the real Wordle here Read the story behind it here Try a demo of this clone project here Inspiration: This game is an open source

Hannah Park 2.4k Jan 8, 2023