Particle fountain: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
m (→‎{{header|Raku}}: Undo bizarre single space indent than somebody found necessary to do)
Line 571: Line 571:


Has options to vary the direction at which the fountain sprays, the "spread" angle and the color of the emitted particles.
Has options to vary the direction at which the fountain sprays, the "spread" angle and the color of the emitted particles.
<syntaxhighlight lang="raku" line>
<syntaxhighlight lang="raku" line>use NativeCall;
use NativeCall;
use SDL2::Raw;

use SDL2::Raw;
my int ($w, $h) = 800, 800;
my SDL_Window $window;
my int ($w, $h) = 800, 800;
my SDL_Window $window;
my SDL_Renderer $renderer;

my SDL_Renderer $renderer;
my int $particlenum = 3000;

my int $particlenum = 3000;

SDL_Init(VIDEO);
$window = SDL_CreateWindow(
SDL_Init(VIDEO);
"Raku Particle System!",
$window = SDL_CreateWindow(
SDL_WINDOWPOS_CENTERED_MASK, SDL_WINDOWPOS_CENTERED_MASK,
"Raku Particle System!",
$w, $h,
SDL_WINDOWPOS_CENTERED_MASK, SDL_WINDOWPOS_CENTERED_MASK,
$w, $h,
RESIZABLE
);
RESIZABLE
$renderer = SDL_CreateRenderer( $window, -1, ACCELERATED );
);

$renderer = SDL_CreateRenderer( $window, -1, ACCELERATED );
SDL_ClearError();

SDL_ClearError();
my num @positions = 0e0 xx ($particlenum * 2);
my num @positions = 0e0 xx ($particlenum * 2);
my num @velocities = 0e0 xx ($particlenum * 2);
my num @velocities = 0e0 xx ($particlenum * 2);
my num @lifetimes = 0e0 xx $particlenum;

my num @lifetimes = 0e0 xx $particlenum;
my CArray[int32] $points .= new;
my int $numpoints;
my CArray[int32] $points .= new;
my int $numpoints;
my Num $saturation = 4e-1;
my Num $saturation = 4e-1;
my Num $spread = 15e-1;
my Num $spread = 15e-1;
my &reciprocate = sub { 0 }
my &reciprocate = sub { 0 }
my $range = 1.5;

my $range = 1.5;
sub update (num \df) {
my int $xidx = 0;
sub update (num \df) {
my int $xidx = 0;
my int $yidx = 1;
my int $yidx = 1;
my int $pointidx = 0;
my int $pointidx = 0;
loop (my int $idx = 0; $idx < $particlenum; $idx = $idx + 1) {
loop (my int $idx = 0; $idx < $particlenum; $idx = $idx + 1) {
my int $willdraw = 0;
my int $willdraw = 0;
if (@lifetimes[$idx] <= 0e0) {
if (@lifetimes[$idx] <= 0e0) {
if (rand < df) {
@lifetimes[$idx] = 25e-1; # time to live
if (rand < df) {
@lifetimes[$idx] = 25e-1; # time to live
@positions[$xidx] = ($w / 20e0).Num; # starting position x
@positions[$xidx] = ($w / 20e0).Num; # starting position x
@positions[$yidx] = ($h / 10).Num; # and y
@positions[$yidx] = ($h / 10).Num; # and y
@velocities[$xidx] = ($spread * rand - $spread/2 + reciprocate()) * 10; # starting velocity x
@velocities[$xidx] = ($spread * rand - $spread/2 + reciprocate()) * 10; # starting velocity x
@velocities[$yidx] = (rand - 2.9e0) * $h / 20.5; # and y (randomized slightly so points reach different heights)
$willdraw = 1;
@velocities[$yidx] = (rand - 2.9e0) * $h / 20.5; # and y (randomized slightly so points reach different heights)
$willdraw = 1;
}
}
} else {
if @positions[$yidx] > $h / 10 && @velocities[$yidx] > 0 {
} else {
if @positions[$yidx] > $h / 10 && @velocities[$yidx] > 0 {
@velocities[$yidx] = @velocities[$yidx] * -0.3e0; # "bounce"
}
@velocities[$yidx] = @velocities[$yidx] * -0.3e0; # "bounce"

}
@velocities[$yidx] = @velocities[$yidx] + $h/10.Num * df; # adjust velocity
@velocities[$yidx] = @velocities[$yidx] + $h/10.Num * df; # adjust velocity
@positions[$xidx] = @positions[$xidx] + @velocities[$xidx] * df; # adjust position x
@positions[$xidx] = @positions[$xidx] + @velocities[$xidx] * df; # adjust position x
@positions[$yidx] = @positions[$yidx] + @velocities[$yidx] * df; # and y

@positions[$yidx] = @positions[$yidx] + @velocities[$yidx] * df; # and y
@lifetimes[$idx] = @lifetimes[$idx] - df;
@lifetimes[$idx] = @lifetimes[$idx] - df;
$willdraw = 1;
$willdraw = 1;
}

}
if ($willdraw) {
$points[$pointidx++] = (@positions[$xidx] * 10).floor; # gather all of the points that
if ($willdraw) {
$points[$pointidx++] = (@positions[$xidx] * 10).floor; # gather all of the points that
$points[$pointidx++] = (@positions[$yidx] * 10).floor; # are still going to be rendered
}
$points[$pointidx++] = (@positions[$yidx] * 10).floor; # are still going to be rendered

}
$xidx = $xidx + 2;
$xidx = $xidx + 2;
$yidx = $xidx + 1;
}
$yidx = $xidx + 1;
$numpoints = ($pointidx - 1) div 2;
}
}
$numpoints = ($pointidx - 1) div 2;

}
sub render {
SDL_SetRenderDrawColor($renderer, 0x0, 0x0, 0x0, 0xff);
sub render {
SDL_SetRenderDrawColor($renderer, 0x0, 0x0, 0x0, 0xff);
SDL_RenderClear($renderer);

SDL_RenderClear($renderer);
SDL_SetRenderDrawColor($renderer, |hsv2rgb(((now % 5) / 5).round(.01), $saturation, 1), 0x7f);
SDL_SetRenderDrawColor($renderer, |hsv2rgb(((now % 5) / 5).round(.01), $saturation, 1), 0x7f);
SDL_RenderDrawPoints($renderer, $points, $numpoints);

SDL_RenderDrawPoints($renderer, $points, $numpoints);
SDL_RenderPresent($renderer);
}
SDL_RenderPresent($renderer);

}
enum KEY_CODES (
K_UP => 82,
enum KEY_CODES (
K_UP => 82,
K_DOWN => 81,
K_DOWN => 81,
K_LEFT => 80,
K_LEFT => 80,
K_RIGHT => 79,
K_RIGHT => 79,
K_SPACE => 44,
K_SPACE => 44,
K_PGUP => 75,
K_PGUP => 75,
K_PGDN => 78,
K_PGDN => 78,
K_Q => 20,
);
K_Q => 20,

);
say q:to/DOCS/;
Use UP and DOWN arrow keys to modify the saturation of the particle colors.
say q:to/DOCS/;
Use UP and DOWN arrow keys to modify the saturation of the particle colors.
Use PAGE UP and PAGE DOWN keys to modify the "spread" of the particles.
Toggle reciprocation off / on with the SPACE bar.
Use PAGE UP and PAGE DOWN keys to modify the "spread" of the particles.
Use LEFT and RIGHT arrow keys to modify angle range for reciprocation.
Toggle reciprocation off / on with the SPACE bar.
Press the "q" key to quit.
Use LEFT and RIGHT arrow keys to modify angle range for reciprocation.
DOCS
Press the "q" key to quit.

DOCS
my $event = SDL_Event.new;

my $event = SDL_Event.new;
my num $df = 0.0001e0;

my num $df = 0.0001e0;
main: loop {
my $start = now;
main: loop {

my $start = now;
while SDL_PollEvent($event) {
while SDL_PollEvent($event) {
my $casted_event = SDL_CastEvent($event);

my $casted_event = SDL_CastEvent($event);
given $casted_event {
given $casted_event {
when *.type == QUIT {
when *.type == QUIT {
last main;
last main;
}
}
when *.type == WINDOWEVENT {
when *.type == WINDOWEVENT {
if .event == RESIZED {
if .event == RESIZED {
$w = .data1;
$w = .data1;
$h = .data2;
$h = .data2;
}
}
}
}
when *.type == KEYDOWN {
when *.type == KEYDOWN {
if KEY_CODES(.scancode) -> $comm {
if KEY_CODES(.scancode) -> $comm {
given $comm {
given $comm {
when 'K_UP' { $saturation = (($saturation + .1) min 1e0) }
when 'K_UP' { $saturation = (($saturation + .1) min 1e0) }
when 'K_DOWN' { $saturation = (($saturation - .1) max 0e0) }
when 'K_DOWN' { $saturation = (($saturation - .1) max 0e0) }
when 'K_PGUP' { $spread = (($spread + .1) min 5e0) }
when 'K_PGUP' { $spread = (($spread + .1) min 5e0) }
when 'K_PGDN' { $spread = (($spread - .1) max 2e-1) }
when 'K_PGDN' { $spread = (($spread - .1) max 2e-1) }
when 'K_RIGHT' { $range = (($range + .1) min 2e0) }
when 'K_RIGHT' { $range = (($range + .1) min 2e0) }
when 'K_LEFT' { $range = (($range - .1) max 1e-1) }
when 'K_LEFT' { $range = (($range - .1) max 1e-1) }
when 'K_SPACE' { &reciprocate = reciprocate() == 0 ?? sub { $range * sin(now) } !! sub { 0 } }
when 'K_SPACE' { &reciprocate = reciprocate() == 0 ?? sub { $range * sin(now) } !! sub { 0 } }
when 'K_Q' { last main }
when 'K_Q' { last main }
}
}
}
}
}
}
}
}
}

}
update($df);

update($df);
render();

render();
$df = (now - $start).Num;

$df = (now - $start).Num;
print fps();
}
print fps();

}
say '';

say '';
sub fps {
state $fps-frames = 0;
sub fps {
state $fps-frames = 0;
state $fps-now = now;
state $fps-now = now;
state $fps = '';
state $fps = '';
$fps-frames++;
$fps-frames++;
if now - $fps-now >= 1 {
if now - $fps-now >= 1 {
$fps = [~] "\r", ' ' x 20, "\r",
$fps = [~] "\r", ' ' x 20, "\r",
sprintf "FPS: %5.1f ", ($fps-frames / (now - $fps-now));
sprintf "FPS: %5.1f ", ($fps-frames / (now - $fps-now));
$fps-frames = 0;
$fps-frames = 0;
$fps-now = now;
}
$fps-now = now;
}
$fps
}
$fps

}
sub hsv2rgb ( $h, $s, $v ){
state %cache;
sub hsv2rgb ( $h, $s, $v ){
state %cache;
%cache{"$h|$s|$v"} //= do {
%cache{"$h|$s|$v"} //= do {
my $c = $v * $s;
my $c = $v * $s;
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $m = $v - $c;
my $m = $v - $c;
[(do given $h {
[(do given $h {
when 0..^1/6 { $c, $x, 0 }
when 0..^1/6 { $c, $x, 0 }
when 1/6..^1/3 { $x, $c, 0 }
when 1/6..^1/3 { $x, $c, 0 }
when 1/3..^1/2 { 0, $c, $x }
when 1/3..^1/2 { 0, $c, $x }
when 1/2..^2/3 { 0, $x, $c }
when 1/2..^2/3 { 0, $x, $c }
when 2/3..^5/6 { $x, 0, $c }
when 2/3..^5/6 { $x, 0, $c }
when 5/6..1 { $c, 0, $x }
when 5/6..1 { $c, 0, $x }
} ).map: ((*+$m) * 255).Int]
}
} ).map: ((*+$m) * 255).Int]
}
}
}
</syntaxhighlight>
</syntaxhighlight>