Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 205 additions & 0 deletions fireworks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Colorful Fireworks with p5.js!</title>
<style>
body {
margin: 0;
padding: 0;
background: #000;
overflow: hidden;
font-family: Arial, sans-serif;
}

#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
}

canvas {
display: block;
}
</style>
</head>
<body>
<div id="info">
クリックして花火を打ち上げよう!<br>
Click to launch fireworks!
</div>

<script src="https://cdn.jsdelivr.net/npm/p5@1.11.8/lib/p5.js"></script>
<script>
let fireworks = [];
let gravity;

function setup() {
createCanvas(windowWidth, windowHeight);
gravity = createVector(0, 0.2);
Comment on lines +41 to +46
Copy link

Copilot AI Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Magic numbers such as gravity magnitude, drag factor (0.9), and velocity multipliers appear without context—consider extracting them into named constants to improve readability and ease tuning.

Suggested change
let fireworks = [];
let gravity;
function setup() {
createCanvas(windowWidth, windowHeight);
gravity = createVector(0, 0.2);
const GRAVITY_MAGNITUDE = 0.2; // Gravity magnitude for fireworks
let fireworks = [];
let gravity;
function setup() {
createCanvas(windowWidth, windowHeight);
gravity = createVector(0, GRAVITY_MAGNITUDE);

Copilot uses AI. Check for mistakes.

colorMode(HSB, 360, 100, 100, 100);

// 初期の花火をいくつか自動で打ち上げ
for (let i = 0; i < 3; i++) {
setTimeout(() => {
fireworks.push(new Firework());
}, i * 1000);
}
}

function draw() {
background(0, 0, 0, 25); // トレイル効果のために半透明の黒い背景

// 自動で花火を打ち上げ(ランダムな間隔)
if (random(1) < 0.03) {
fireworks.push(new Firework());
}

// 花火の更新と描画
for (let i = fireworks.length - 1; i >= 0; i--) {
fireworks[i].update();
fireworks[i].show();

if (fireworks[i].done()) {
fireworks.splice(i, 1);
}
}
}

function mousePressed() {
// マウスクリック位置に向かって花火を打ち上げ
fireworks.push(new Firework(createVector(mouseX, mouseY)));
}

function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}

class Firework {
constructor(target) {
this.firework = new Particle(random(width), height, true);
this.exploded = false;
this.particles = [];

if (target) {
this.firework.target = target.copy();
} else {
this.firework.target = createVector(random(width/4, 3*width/4), random(height/4, height/2));
}

// 打ち上げ花火の初期速度を計算
this.firework.vel = p5.Vector.sub(this.firework.target, this.firework.pos);
this.firework.vel.mult(0.02);

// 花火の色を決定
this.hue = random(360);
}

update() {
if (!this.exploded) {
this.firework.applyForce(gravity);
this.firework.update();

// 目標地点に近づいたら爆発
if (this.firework.vel.y >= 0) {
this.exploded = true;
this.explode();
}
}

// 爆発した粒子の更新
for (let i = this.particles.length - 1; i >= 0; i--) {
this.particles[i].applyForce(gravity);
this.particles[i].update();

if (this.particles[i].done()) {
this.particles.splice(i, 1);
}
}
}

explode() {
// 爆発時に多数の粒子を生成
for (let i = 0; i < random(80, 120); i++) {
Copy link

Copilot AI Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

random(80, 120) returns a float, which causes the loop bound to be fractional. Use an integer cast like floor(random(80, 120)) for predictable iteration counts.

Suggested change
for (let i = 0; i < random(80, 120); i++) {
for (let i = 0; i < floor(random(80, 120)); i++) {

Copilot uses AI. Check for mistakes.

let p = new Particle(this.firework.pos.x, this.firework.pos.y, false, this.hue);
this.particles.push(p);
}
}

show() {
if (!this.exploded) {
this.firework.show();
}

for (let particle of this.particles) {
particle.show();
}
}

done() {
return this.exploded && this.particles.length === 0;
}
}

class Particle {
constructor(x, y, firework, hu) {
this.pos = createVector(x, y);
this.firework = firework;
this.lifespan = 255;
this.acc = createVector(0, 0);

if (this.firework) {
// 打ち上げ花火の場合
this.vel = createVector(0, random(-12, -8));
this.hu = 60; // 黄色っぽい色
} else {
// 爆発粒子の場合
this.vel = p5.Vector.random2D();
this.vel.mult(random(2, 10));
this.hu = hu + random(-30, 30);
if (this.hu < 0) this.hu += 360;
if (this.hu > 360) this.hu -= 360;
}
}

applyForce(force) {
this.acc.add(force);
}

update() {
if (!this.firework) {
this.vel.mult(0.9); // 空気抵抗
this.lifespan -= 4;
}

this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
}

done() {
return this.lifespan < 0;
}

show() {
if (!this.firework) {
strokeWeight(2);
stroke(this.hu, 100, 100, this.lifespan);
} else {
strokeWeight(4);
stroke(this.hu, 100, 100);
}

point(this.pos.x, this.pos.y);
}
}
</script>
</body>
</html>