A kódot röviden és egyszerűen tartjuk, így a tűzijátékaink nem lesznek túl flancosak vagy valósághűek - valójában inkább azokhoz fognak hasonlítani, amiket húsz évvel ezelőtt a Geocities-en látott. De azért ez még mindig egy jó kódolási gyakorlat.
A fő program [5-31. sor] először deklarálja a változókat, majd létrehoz egy tömböt a tűzijáték objektumokból. Minden tűzijátéknak saját x és y koordinátája, kora (a robbanás óta eltelt idő), fázisa (repülés/robbanás) és egy szikrákból álló tömbje lesz.
Minden szikrának van saját vízszintes (vx) és függőleges (vy) sebessége, súlya, amely meghatározza, milyen gyorsan esik, és egy színe (amelyet a vörös, zöld és kék komponensek határoznak meg).
A [31]-es sorban indítjuk el a fő animációs függvényt - explode [40-75].
Ez a függvény frissíti és rajzolja ki az egyes tűzijátékok minden szikráját.
A [44-62] a robbanási fázis. Ebben a fázisban minden szikrának van egy 10 téglalapból álló csóvája. Minden téglalap pozícióját [45-48] a tűzijáték koordinátái, a szikra sebessége, a robbanás 'kora' és a téglalap indexe alapján számoljuk ki. Nem használtam semmilyen ballisztikai képletet, helyette ezt a furcsaságot [48] találtam ki próbálgatással.
A [49-52] kiszámítja az egyes téglalapok színét, figyelembe véve a halványulási tényezőt, amely a robbanás 'korából' származik - minél régebbi a robbanás, annál sötétebb a szín.
Az [53-56] kirajzolja a téglalapot.
A [60-61]-ben 5% esély van a tűzijáték visszaállítására, ha a robbanás régebbi, mint 100 képkocka.
A visszaállító függvény [33-37] a tűzijátékot egy véletlenszerű helyre teszi a képernyő alján, és a 'repülés' fázis újra kezdődik.
Ebben a fázisban [64-71] a tűzijáték felfelé mozog a képernyőn [64], és egy rendkívül kezdetleges szikracsóva kerül kirajzolásra [65-69].

Van 0,001 esély arra, hogy a tűzijáték felrobban (a fázisa megváltozik) egy adott képkockán [71]. Biztosan felrobban, amint az y koordináta eléri a 200-at.
Jó szórakozást!
| <html> |
| <body style='background-color:black'> |
| <canvas id='myCanvas' width='800' height='800'></canvas> |
| <script> |
| const max_fireworks = 5, |
| max_sparks = 50; |
| let canvas = document.getElementById('myCanvas'); |
| let context = canvas.getContext('2d'); |
| let fireworks = []; |
| |
| for (let i = 0; i < max_fireworks; i++) { |
| let firework = { |
| sparks: [] |
| }; |
| for (let n = 0; n < max_sparks; n++) { |
| let spark = { |
| vx: Math.random() * 5 + .5, |
| vy: Math.random() * 5 + .5, |
| weight: Math.random() * .3 + .03, |
| red: Math.floor(Math.random() * 2), |
| green: Math.floor(Math.random() * 2), |
| blue: Math.floor(Math.random() * 2) |
| }; |
| if (Math.random() > .5) spark.vx = -spark.vx; |
| if (Math.random() > .5) spark.vy = -spark.vy; |
| firework.sparks.push(spark); |
| } |
| fireworks.push(firework); |
| resetFirework(firework); |
| } |
| window.requestAnimationFrame(explode); |
| |
| function resetFirework(firework) { |
| firework.x = Math.floor(Math.random() * canvas.width); |
| firework.y = canvas.height; |
| firework.age = 0; |
| firework.phase = 'fly'; |
| } |
| |
| function explode() { |
| context.clearRect(0, 0, canvas.width, canvas.height); |
| fireworks.forEach((firework,index) => { |
| if (firework.phase == 'explode') { |
| firework.sparks.forEach((spark) => { |
| for (let i = 0; i < 10; i++) { |
| let trailAge = firework.age + i; |
| let x = firework.x + spark.vx * trailAge; |
| let y = firework.y + spark.vy * trailAge + spark.weight * trailAge * spark.weight * trailAge; |
| let fade = i * 20 - firework.age * 2; |
| let r = Math.floor(spark.red * fade); |
| let g = Math.floor(spark.green * fade); |
| let b = Math.floor(spark.blue * fade); |
| context.beginPath(); |
| context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',1)'; |
| context.rect(x, y, 4, 4); |
| context.fill(); |
| } |
| }); |
| firework.age++; |
| if (firework.age > 100 && Math.random() < .05) { |
| resetFirework(firework); |
| } |
| } else { |
| firework.y = firework.y - 10; |
| for (let spark = 0; spark < 15; spark++) { |
| context.beginPath(); |
| context.fillStyle = 'rgba(' + index * 50 + ',' + spark * 17 + ',0,1)'; |
| context.rect(firework.x + Math.random() * spark - spark / 2, firework.y + spark * 4, 4, 4); |
| context.fill(); |
| } |
| if (Math.random() < .001 || firework.y < 200) firework.phase = 'explode'; |
| } |
| }); |
| window.requestAnimationFrame(explode); |
| } |
| </script> |
| </body> |
| </html> |
Egy újabb JavaScript oktatóanyag:
Buborékrendezés vizualizáció