aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriceyrazor <iceyrazor@mailfence.com>2025-07-04 05:31:27 -0500
committericeyrazor <iceyrazor@mailfence.com>2025-07-04 05:31:27 -0500
commit5935d51e08668a0d6407541a9873c769f006e097 (patch)
tree12f610931a5f528b82a7623939df6bf17e7af2e9
init
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock206
-rw-r--r--Cargo.toml8
-rw-r--r--LICENSE21
-rw-r--r--README.md15
-rw-r--r--fireworks.gifbin0 -> 3043477 bytes
-rw-r--r--src/main.rs372
7 files changed, 623 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..a081228
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,206 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
+name = "c_vec"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+
+[[package]]
+name = "fireworks"
+version = "0.1.0"
+dependencies = [
+ "rand",
+ "sdl2",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.174"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "sdl2"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380"
+dependencies = [
+ "bitflags 1.3.2",
+ "c_vec",
+ "lazy_static",
+ "libc",
+ "sdl2-sys",
+]
+
+[[package]]
+name = "sdl2-sys"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "version-compare",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "version-compare"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
+
+[[package]]
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags 2.9.1",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d53a8a2
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "fireworks"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+rand = "0.9.1"
+sdl2 = { version = "0.37.0", features = ["gfx"] }
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d54d7cc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 iceyrazor
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b492d2b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# fireworks in sdl2 rust
+
+![firework gif](./fireworks.gif?raw=true)
+
+followed this video [Coding Challenge #27: Fireworks](https://youtu.be/CKeyIbT3vXI)
+but instead of p5 javascript. i did it in sdl2 rust
+
+its 4th of july so i decided to upload it. why not :p
+
+``no clue if this compiles on windows``
+
+## requirements
+
+- sdl2
+- sdl2_gfx
diff --git a/fireworks.gif b/fireworks.gif
new file mode 100644
index 0000000..03d52bf
--- /dev/null
+++ b/fireworks.gif
Binary files differ
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..b77bd93
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,372 @@
+// followed this video [Coding Challenge #27: Fireworks](https://youtu.be/CKeyIbT3vXI)
+// but instead of p5 javascript. i did it in sdl2 rust
+extern crate sdl2;
+
+use sdl2::{gfx::primitives::DrawRenderer, rect::Rect};
+use sdl2::pixels::Color;
+use sdl2::event::Event;
+use sdl2::keyboard::Keycode;
+use sdl2::render::WindowCanvas;
+use std::time::Duration;
+use rand::{rng, Rng};
+
+
+//HSV to rgv.
+//i did not make this
+//only translated it from my c version i found from a stranger
+struct HSV {
+ h: f64,
+ s: f64,
+ v: f64,
+}
+impl HSV{
+ fn new(h: f64, s: f64, v: f64) -> Self{
+ Self{
+ h: h,
+ s: s,
+ v: v,
+ }
+ }
+}
+
+#[derive(Clone,Copy)]
+struct IRGB {
+ r: f64,
+ g: f64,
+ b: f64,
+}
+impl IRGB {
+ fn new(r: f64, g: f64, b: f64) -> Self{
+ Self{
+ r: r,
+ g: g,
+ b: b,
+ }
+ }
+
+ fn hsvtorgb(&mut self, hsv: &mut HSV){
+ let mut r = 0.0;
+ let mut g = 0.0;
+ let mut b = 0.0;
+
+ if hsv.s == 0.0 {
+ r = hsv.v;
+ g = hsv.v;
+ b = hsv.v;
+ } else {
+ let mut i: f64 = 0.0;
+ let mut f: f64 = 0.0;
+ let mut p: f64 = 0.0;
+ let mut q: f64 = 0.0;
+ let mut t: f64 = 0.0;
+
+ if hsv.h == 360.0 {
+ hsv.h = 0.0;
+ } else {
+ hsv.h = hsv.h / 60.0;
+
+ i = hsv.h.trunc();
+ f = hsv.h - i;
+
+ p = hsv.v * (1.0 - hsv.s);
+ q = hsv.v * (1.0 - (hsv.s * f));
+ t = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
+
+ match i {
+ 0.0=>{
+ r = hsv.v;
+ g = t;
+ b = p;
+ },
+ 1.0=>{
+ r = q;
+ g = hsv.v;
+ b = p;
+ },
+ 2.0=>{
+ r = p;
+ g = hsv.v;
+ b = t;
+ },
+ 3.0=>{
+ r = p;
+ g = q;
+ b = hsv.v;
+ },
+ 4.0=>{
+ r = t;
+ g = p;
+ b = hsv.v;
+ },
+ _=>{
+ r = hsv.v;
+ g = p;
+ b = q;
+ },
+ }
+ }
+ }
+
+ self.r = r * 255.0;
+ self.g = g * 255.0;
+ self.b = b * 255.0;
+ }
+}
+
+fn magnitude(x: f64,y: f64) -> f64 {
+ ((x).powi(2) + (y).powi(2)).sqrt()
+}
+
+struct PointG{
+ x: f64,
+ y: f64,
+}
+impl PointG{
+ fn new(x: f64, y: f64) -> Self {
+ Self{
+ x: x,
+ y: y,
+ }
+ }
+
+ fn add(&mut self, addvec: &PointG){
+ self.x = self.x + addvec.x;
+ self.y = self.y + addvec.y;
+ }
+
+ fn mul(&mut self, addvec: &PointG){
+ self.x = self.x * addvec.x;
+ self.y = self.y * addvec.y;
+ }
+
+ fn set_mag(&mut self, mag: &f64){
+ let getmag: f64 = magnitude(self.x, self.y);
+ self.x = (self.x / getmag) * mag;
+ self.y = (self.y / getmag) * mag;
+ }
+}
+
+struct Gvars{
+ mouse: PointG,
+ screen_size: PointG,
+}
+impl Gvars{
+ fn new(sw: f64, sh: f64) -> Self{
+ Self {
+ mouse: PointG::new(0.0,0.0),
+ screen_size: PointG::new(sw,sh),
+ }
+ }
+}
+
+// Particle
+struct Particle{
+ pos: PointG,
+ vel: PointG,
+ acc: PointG,
+ firework: bool,
+ lifespan: i16,
+ hue: IRGB,
+}
+
+impl Particle{
+ fn new(x: f64, y: f64, hu: IRGB, firework: bool) -> Self{
+ let mut initvel=PointG::new(0.0,rng().random_range(-18.0..-9.0));
+ if firework==true {
+ initvel=PointG::new(rng().random_range(-1.0..1.0),rng().random_range(-1.0..1.0));
+ initvel.set_mag(&rng().random_range(1.0..10.0));
+ }
+ Self {
+ pos: PointG::new(x,y),
+ vel: initvel,
+ acc: PointG::new(0.0,0.0),
+ firework: firework,
+ lifespan: 255,
+ hue: hu,
+ }
+ }
+
+ fn apply_force(&mut self, force: &PointG){
+ self.acc.add(&force);
+ }
+
+ fn done(&mut self) -> bool{
+ if self.lifespan <= 0 {
+ return true
+ }
+ false
+ }
+
+ fn update(&mut self){
+ if self.firework {
+ self.vel.mul(&PointG::new(0.9,0.9));
+ self.lifespan = self.lifespan - 4;
+
+ if self.lifespan <= 0 {
+ self.lifespan = 0;
+ }
+ }
+ self.vel.add(&self.acc);
+ self.pos.add(&self.vel);
+
+ self.acc.x = 0.0;
+ self.acc.y = 0.0;
+ }
+
+ fn show(&mut self, canvas: &mut WindowCanvas, gvars: &mut Gvars){
+ if self.firework {
+ canvas.filled_circle(self.pos.x as i16, self.pos.y as i16, 1, Color::RGBA(self.hue.r as u8,self.hue.g as u8,self.hue.b as u8,self.lifespan as u8)).err();
+ } else {
+ canvas.filled_circle(self.pos.x as i16, self.pos.y as i16, 3, Color::RGBA(self.hue.r as u8,self.hue.g as u8,self.hue.b as u8,255)).err();
+ }
+ }
+}
+
+// Firework
+struct Firework{
+ firework: Particle,
+ exploded: bool,
+ particles: Vec<Particle>,
+ hue: IRGB,
+}
+
+impl Firework{
+ fn new(x: f64, y: f64) -> Self{
+ let mut hu = IRGB::new(0.0,0.0,0.0);
+ hu.hsvtorgb(&mut HSV::new(rng().random_range(0.0..360.0),1.0,1.0));
+ Self {
+ firework: Particle::new(x,y,hu,false),
+ exploded: false,
+ particles: Vec::new(),
+ hue: hu,
+ }
+ }
+
+ fn done(&mut self) -> bool{
+ if self.exploded && self.particles.len() == 0{
+ return true
+ }
+ false
+ }
+
+ fn update(&mut self){
+ if !self.exploded {
+ self.firework.apply_force(&PointG::new(0.0,0.2));
+ self.firework.update();
+
+ if self.firework.vel.y >= 0.0 {
+ self.exploded=true;
+ self.explode();
+ }
+ }
+
+ for i in (0..self.particles.len()).rev() {
+ self.particles[i].apply_force(&PointG::new(0.0,0.2));
+ self.particles[i].update();
+ if self.particles[i].done() {
+ self.particles.remove(i);
+ }
+ }
+ }
+
+ fn explode(&mut self){
+ for _ in 0..100{
+ let p = Particle::new(self.firework.pos.x,self.firework.pos.y,self.hue,true);
+ self.particles.push(p);
+ }
+ }
+
+ fn show(&mut self, canvas: &mut WindowCanvas, gvars: &mut Gvars){
+ if !self.exploded {
+ self.firework.show(canvas,gvars);
+ }
+
+ for obj in &mut self.particles{
+ obj.show(canvas,gvars);
+ }
+ }
+}
+
+
+// Canvas Draw
+fn draw(canvas: &mut WindowCanvas, obj_arr: &mut Vec<Firework>, gvars: &mut Gvars){
+ canvas.set_draw_color(Color::RGBA(0,0,0,50));
+
+ //swap these lines out if screen is glitchy
+ canvas.fill_rect(Rect::new(0,0,800,800)).err();
+ //canvas.clear();
+
+
+ if rng().random_range(0.0..1.0) < 0.08 {
+ let obj = Firework::new(rng().random_range(0.0..gvars.screen_size.x as f64), gvars.screen_size.y as f64);
+ obj_arr.push(obj);
+ }
+
+ for i in (0..obj_arr.len()).rev() {
+ obj_arr[i].update();
+ obj_arr[i].show(canvas,gvars);
+ if obj_arr[i].done() {
+ obj_arr.remove(i);
+ }
+ }
+
+ canvas.present();
+}
+
+
+
+fn main() {
+ let sdl2_context = sdl2::init().unwrap();
+ let video_subsystem = sdl2_context.video().unwrap();
+
+
+ let width: u32=800;
+ let height: u32=800;
+
+ let window = video_subsystem.window("fireworks", width, height)
+ .position_centered()
+ .build()
+ .unwrap();
+
+ let mut canvas = window.into_canvas().build().unwrap();
+ canvas.default_pixel_format();
+ canvas.set_blend_mode(sdl2::render::BlendMode::Blend);
+
+ let mut gvars = Gvars::new(width as f64, height as f64);
+
+ let mut obj_arr: Vec<Firework> = Vec::new();
+
+
+ let obj = Firework::new(rng().random_range(0.0..width as f64), height as f64);
+ obj_arr.push(obj);
+
+
+ canvas.set_draw_color(Color::RGB(0,0,0));
+ canvas.clear();
+
+ let mut event_pump = sdl2_context.event_pump().unwrap();
+ draw(&mut canvas, &mut obj_arr, &mut gvars);
+
+ 'running: loop {
+ draw(&mut canvas, &mut obj_arr, &mut gvars);
+ let state = event_pump.mouse_state();
+ gvars.mouse.x=state.x() as f64;
+ gvars.mouse.y=state.y() as f64;
+ //draw(&mut canvas, &mut obj, &state.x(), &state.y());
+ for event in event_pump.poll_iter() {
+ match event {
+ Event::Quit {..} |
+ Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
+ break 'running
+ },
+ _ => {}
+ }
+ }
+
+ ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
+ }
+}
+
+// *~challenges
+// shaped fireworks such as a heart
+// variable amount of particles