Skip to content

Instantly share code, notes, and snippets.

@jinjor
Created May 6, 2023 16:54
Show Gist options
  • Save jinjor/e70aca41d1e6582baa953b239fa507e1 to your computer and use it in GitHub Desktop.
Save jinjor/e70aca41d1e6582baa953b239fa507e1 to your computer and use it in GitHub Desktop.
上から落ちてきたボールがぶつかったら音が出る的な
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.min.js"></script>
</head>
<body>
<script>
document.onclick = () => {
const synth = new Tone.PolySynth(Tone.FMSynth).toDestination();
const Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Bodies = Matter.Bodies,
Composite = Matter.Composite,
Events = Matter.Events;
const engine = Engine.create();
const render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
wireframes: false,
},
});
const drops = [];
const pins = [];
const sounds = new WeakMap();
const dropClasses = [
{
position: [160, 0],
radius: 30,
options: {
density: 0.05,
restitution: 0.8,
friction: 0.1,
render: { fillStyle: "#a66" },
},
tone: {
note: "C3",
duration: "2n",
timing: 1,
},
},
{
position: [250, 0],
radius: 20,
options: {
restitution: 0.8,
render: { fillStyle: "#6a6" },
},
tone: {
note: "G4",
duration: "16n",
timing: 2,
},
},
{
position: [520, 0],
radius: 20,
options: {
restitution: 0.4,
render: { fillStyle: "#66a" },
},
tone: {
note: "D5",
duration: "16n",
timing: 2,
},
},
{
position: [650, 0],
radius: 10,
options: {
restitution: 0.8,
render: { fillStyle: "#6aa" },
},
tone: {
note: "Bb5",
duration: "8n",
timing: 1,
},
},
];
const pinClasses = [
{
position: [200, 500],
radius: 100,
options: {
render: { fillStyle: "#666" },
isStatic: true,
restitution: 0.6,
},
tone: null,
},
{
position: [500, 300],
radius: 80,
options: {
render: { fillStyle: "#666" },
isStatic: true,
restitution: 0.6,
},
tone: {
note: "E5",
duration: "16n",
},
},
];
Events.on(engine, "collisionStart", function (event) {
// console.log("collisionStart", event, event.pairs[0]);
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i];
for (const body of [pair.bodyA, pair.bodyB]) {
const sound = sounds.get(body);
if (sound) {
synth.triggerAttackRelease(sound.note, sound.duration);
}
}
// pair.bodyA.render.fillStyle = "#999";
// pair.bodyB.render.fillStyle = "#999";
}
});
Events.on(engine, "collisionEnd", function (event) {
// console.log("collisionEnd", event);
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i];
// pair.bodyA.render.fillStyle = "#666";
// pair.bodyB.render.fillStyle = "#666";
}
});
for (const c of pinClasses) {
const pin = Bodies.circle(...c.position, c.radius, c.options);
pins.push(pin);
if (c.tone) {
sounds.set(pin, c.tone);
}
}
let count = 0;
setInterval(() => {
if (document.hidden) {
return;
}
for (const c of dropClasses) {
if ((count % 16) % (16 / c.tone.timing) === 0) {
const drop = Bodies.circle(...c.position, c.radius, c.options);
drops.push(drop);
sounds.set(drop, c.tone);
Composite.add(engine.world, drop);
}
}
count++;
}, 2000 / 16);
setInterval(() => {
if (document.hidden) {
return;
}
const time = 2000;
Matter.Body.setPosition(pins[1], {
x: 600 + 100 * Math.sin(2 * Math.PI * ((Date.now() % time) / time)),
y: 400,
});
}, 10);
Composite.add(engine.world, [...pins]);
Render.run(render);
const runner = Runner.create();
Runner.run(runner, engine);
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment