Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Particle-fountain/00-META.yaml
Normal file
2
Task/Particle-fountain/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Particle_fountain
|
||||
14
Task/Particle-fountain/00-TASK.txt
Normal file
14
Task/Particle-fountain/00-TASK.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Implement a particle fountain.
|
||||
|
||||
Emulate a fountain of water droplets in a gravitational field being sprayed up and then falling back down.
|
||||
|
||||
The particle fountain should be generally ordered but individually chaotic; the particles should be going mostly in the same direction, but should have slightly different vectors.
|
||||
|
||||
Your fountain should have at least several hundred particles in motion at any one time, and ideally several thousand.
|
||||
|
||||
It is optional to have the individual particle interact with each other.
|
||||
|
||||
If at all possible, link to a short video clip of your fountain in action.
|
||||
|
||||
[https://github.com/thundergnat/rc/blob/master/img/fountain-raku.mp4?raw=true Off-site link to a demo video]
|
||||
|
||||
237
Task/Particle-fountain/C++/particle-fountain.cpp
Normal file
237
Task/Particle-fountain/C++/particle-fountain.cpp
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
auto now() {
|
||||
using namespace std::chrono;
|
||||
auto time = system_clock::now();
|
||||
return duration_cast<milliseconds>(time.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
auto hsv_to_rgb(int h, double s, double v) {
|
||||
double hp = h / 60.0;
|
||||
double c = s * v;
|
||||
double x = c * (1 - std::abs(std::fmod(hp, 2) - 1));
|
||||
double m = v - c;
|
||||
double r = 0, g = 0, b = 0;
|
||||
if (hp <= 1) {
|
||||
r = c;
|
||||
g = x;
|
||||
} else if (hp <= 2) {
|
||||
r = x;
|
||||
g = c;
|
||||
} else if (hp <= 3) {
|
||||
g = c;
|
||||
b = x;
|
||||
} else if (hp <= 4) {
|
||||
g = x;
|
||||
b = c;
|
||||
} else if (hp <= 5) {
|
||||
r = x;
|
||||
b = c;
|
||||
} else {
|
||||
r = c;
|
||||
b = x;
|
||||
}
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
return std::make_tuple(Uint8(r * 255), Uint8(g * 255), Uint8(b * 255));
|
||||
}
|
||||
|
||||
class ParticleFountain {
|
||||
public:
|
||||
ParticleFountain(int particles, int width, int height);
|
||||
void run();
|
||||
|
||||
private:
|
||||
struct WindowDeleter {
|
||||
void operator()(SDL_Window* window) const { SDL_DestroyWindow(window); }
|
||||
};
|
||||
struct RendererDeleter {
|
||||
void operator()(SDL_Renderer* renderer) const {
|
||||
SDL_DestroyRenderer(renderer);
|
||||
}
|
||||
};
|
||||
struct PointInfo {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double vx = 0;
|
||||
double vy = 0;
|
||||
double lifetime = 0;
|
||||
};
|
||||
|
||||
void update(double df);
|
||||
bool handle_event();
|
||||
void render();
|
||||
double rand() { return dist_(rng_); }
|
||||
double reciprocate() const {
|
||||
return reciprocate_ ? range_ * std::sin(now() / 1000.0) : 0.0;
|
||||
}
|
||||
|
||||
std::unique_ptr<SDL_Window, WindowDeleter> window_;
|
||||
std::unique_ptr<SDL_Renderer, RendererDeleter> renderer_;
|
||||
int width_;
|
||||
int height_;
|
||||
std::vector<PointInfo> point_info_;
|
||||
std::vector<SDL_Point> points_;
|
||||
int num_points_ = 0;
|
||||
double saturation_ = 0.4;
|
||||
double spread_ = 1.5;
|
||||
double range_ = 1.5;
|
||||
bool reciprocate_ = false;
|
||||
std::mt19937 rng_;
|
||||
std::uniform_real_distribution<> dist_;
|
||||
};
|
||||
|
||||
ParticleFountain::ParticleFountain(int n, int width, int height)
|
||||
: width_(width), height_(height), point_info_(n), points_(n, {0, 0}),
|
||||
rng_(std::random_device{}()), dist_(0.0, 1.0) {
|
||||
window_.reset(SDL_CreateWindow(
|
||||
"C++ Particle System!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
width, height, SDL_WINDOW_RESIZABLE));
|
||||
if (window_ == nullptr)
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
|
||||
renderer_.reset(
|
||||
SDL_CreateRenderer(window_.get(), -1, SDL_RENDERER_ACCELERATED));
|
||||
if (renderer_ == nullptr)
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
}
|
||||
|
||||
void ParticleFountain::run() {
|
||||
for (double df = 0.0001;;) {
|
||||
auto start = now();
|
||||
if (!handle_event())
|
||||
break;
|
||||
update(df);
|
||||
render();
|
||||
df = (now() - start) / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleFountain::update(double df) {
|
||||
int pointidx = 0;
|
||||
for (PointInfo& point : point_info_) {
|
||||
bool willdraw = false;
|
||||
if (point.lifetime <= 0.0) {
|
||||
if (rand() < df) {
|
||||
point.lifetime = 2.5;
|
||||
point.x = width_ / 20.0;
|
||||
point.y = height_ / 10.0;
|
||||
point.vx =
|
||||
(spread_ * rand() - spread_ / 2 + reciprocate()) * 10.0;
|
||||
point.vy = (rand() - 2.9) * height_ / 20.5;
|
||||
willdraw = true;
|
||||
}
|
||||
} else {
|
||||
if (point.y > height_ / 10.0 && point.vy > 0)
|
||||
point.vy *= -0.3;
|
||||
point.vy += (height_ / 10.0) * df;
|
||||
point.x += point.vx * df;
|
||||
point.y += point.vy * df;
|
||||
point.lifetime -= df;
|
||||
willdraw = true;
|
||||
}
|
||||
if (willdraw) {
|
||||
points_[pointidx].x = std::floor(point.x * 10.0);
|
||||
points_[pointidx].y = std::floor(point.y * 10.0);
|
||||
++pointidx;
|
||||
}
|
||||
}
|
||||
num_points_ = pointidx;
|
||||
}
|
||||
|
||||
bool ParticleFountain::handle_event() {
|
||||
bool result = true;
|
||||
SDL_Event event;
|
||||
while (result && SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
result = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
width_ = event.window.data1;
|
||||
height_ = event.window.data2;
|
||||
}
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
switch (event.key.keysym.scancode) {
|
||||
case SDL_SCANCODE_UP:
|
||||
saturation_ = std::min(saturation_ + 0.1, 1.0);
|
||||
break;
|
||||
case SDL_SCANCODE_DOWN:
|
||||
saturation_ = std::max(saturation_ - 0.1, 0.0);
|
||||
break;
|
||||
case SDL_SCANCODE_PAGEUP:
|
||||
spread_ = std::min(spread_ + 0.1, 5.0);
|
||||
break;
|
||||
case SDL_SCANCODE_PAGEDOWN:
|
||||
spread_ = std::max(spread_ - 0.1, 0.2);
|
||||
break;
|
||||
case SDL_SCANCODE_RIGHT:
|
||||
range_ = std::min(range_ + 0.1, 2.0);
|
||||
break;
|
||||
case SDL_SCANCODE_LEFT:
|
||||
range_ = std::max(range_ - 0.1, 0.1);
|
||||
break;
|
||||
case SDL_SCANCODE_SPACE:
|
||||
reciprocate_ = !reciprocate_;
|
||||
break;
|
||||
case SDL_SCANCODE_Q:
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParticleFountain::render() {
|
||||
SDL_Renderer* renderer = renderer_.get();
|
||||
SDL_SetRenderDrawColor(renderer, 0x0, 0x0, 0x0, 0xff);
|
||||
SDL_RenderClear(renderer);
|
||||
auto [red, green, blue] = hsv_to_rgb((now() % 5) * 72, saturation_, 1);
|
||||
SDL_SetRenderDrawColor(renderer, red, green, blue, 0x7f);
|
||||
SDL_RenderDrawPoints(renderer, points_.data(), num_points_);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Use UP and DOWN arrow keys to modify the saturation of the "
|
||||
"particle colors.\n"
|
||||
"Use PAGE UP and PAGE DOWN keys to modify the \"spread\" of "
|
||||
"the particles.\n"
|
||||
"Toggle reciprocation off / on with the SPACE bar.\n"
|
||||
"Use LEFT and RIGHT arrow keys to modify angle range for "
|
||||
"reciprocation.\n"
|
||||
"Press the \"q\" key to quit.\n";
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
std::cerr << "ERROR: " << SDL_GetError() << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
try {
|
||||
ParticleFountain pf(3000, 800, 800);
|
||||
pf.run();
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "ERROR: " << ex.what() << '\n';
|
||||
SDL_Quit();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
126
Task/Particle-fountain/Julia/particle-fountain.julia
Normal file
126
Task/Particle-fountain/Julia/particle-fountain.julia
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
using Dates, Colors, SimpleDirectMediaLayer.LibSDL2
|
||||
|
||||
mutable struct ParticleFountain
|
||||
particlenum::Int
|
||||
positions::Vector{Float64}
|
||||
velocities::Vector{Float64}
|
||||
lifetimes::Vector{Float64}
|
||||
points::Vector{SDL_Point}
|
||||
numpoints::Int
|
||||
saturation::Float64
|
||||
spread::Float64
|
||||
range::Float64
|
||||
reciprocate::Bool
|
||||
ParticleFountain(N) = new(N, zeros(2N), zeros(2N), zeros(N), fill(SDL_Point(0, 0), N),
|
||||
0, 0.4, 1.5, 1.5, false)
|
||||
end
|
||||
|
||||
function update(pf, w, h, df)
|
||||
xidx, yidx, pointidx = 1, 2, 0
|
||||
recip() = pf.reciprocate ? pf.range * sin(Dates.value(now()) / 1000) : 0.0
|
||||
for idx in 1:pf.particlenum
|
||||
willdraw = false
|
||||
if pf.lifetimes[idx] <= 0.0
|
||||
if rand() < df
|
||||
pf.lifetimes[idx] = 2.5; # time to live
|
||||
pf.positions[xidx] = (w / 20) # starting position x
|
||||
pf.positions[yidx] = (h / 10) # and y
|
||||
pf.velocities[xidx] = 10 * (pf.spread * rand() - pf.spread / 2 + recip()) # starting velocity x
|
||||
pf.velocities[yidx] = (rand() - 2.9) * h / 20.5; # and y (randomized slightly so points reach different heights)
|
||||
willdraw = true
|
||||
end
|
||||
else
|
||||
if pf.positions[yidx] > h / 10 && pf.velocities[yidx] > 0
|
||||
pf.velocities[yidx] *= -0.3 # "bounce"
|
||||
end
|
||||
pf.velocities[yidx] += df * h / 10 # adjust velocity
|
||||
pf.positions[xidx] += pf.velocities[xidx] * df # adjust position x
|
||||
pf.positions[yidx] += pf.velocities[yidx] * df # and y
|
||||
pf.lifetimes[idx] -= df
|
||||
willdraw = true
|
||||
end
|
||||
|
||||
if willdraw # gather all of the points that are going to be rendered
|
||||
pointidx += 1
|
||||
pf.points[pointidx] = SDL_Point(Cint(floor(pf.positions[xidx] * 10)),
|
||||
Cint(floor(pf.positions[yidx] * 10)))
|
||||
end
|
||||
xidx += 2
|
||||
yidx = xidx + 1
|
||||
pf.numpoints = pointidx
|
||||
end
|
||||
return pf
|
||||
end
|
||||
|
||||
function fountain(particlenum = 3000, w = 800, h = 800)
|
||||
SDL_Init(SDL_INIT_VIDEO)
|
||||
window = SDL_CreateWindow("Julia Particle System!", SDL_WINDOWPOS_CENTERED_MASK,
|
||||
SDL_WINDOWPOS_CENTERED_MASK, w, h, SDL_WINDOW_RESIZABLE)
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED)
|
||||
SDL_ClearError()
|
||||
df = 0.0001
|
||||
pf = ParticleFountain(3000)
|
||||
overallstart, close, frames = now(), false, 0
|
||||
while !close
|
||||
dfstart = now()
|
||||
event_ref = Ref{SDL_Event}()
|
||||
while Bool(SDL_PollEvent(event_ref))
|
||||
event_type = event_ref[].type
|
||||
evt = event_ref[]
|
||||
if event_type == SDL_QUIT
|
||||
close = true
|
||||
break
|
||||
end
|
||||
if event_type == SDL_WINDOWEVENT
|
||||
if evt.window.event == 5
|
||||
w = evt.window.data1
|
||||
h = evt.window.data2
|
||||
end
|
||||
end
|
||||
if event_type == SDL_KEYDOWN
|
||||
comm = evt.key.keysym.scancode
|
||||
if comm == SDL_SCANCODE_UP
|
||||
saturation = min(pf.saturation + 0.1, 1.0)
|
||||
elseif comm == SDL_SCANCODE_DOWN
|
||||
saturation = max(pf.saturation - 0.1, 0.0)
|
||||
elseif comm == SDL_SCANCODE_PAGEUP
|
||||
spread = min(pf.spread + 1, 50.0)
|
||||
elseif comm == SDL_SCANCODE_PAGEDOWN
|
||||
spread = max(pf.spread - 0.1, 0.2)
|
||||
elseif comm == SDL_SCANCODE_LEFT
|
||||
range = min(pf.range + 0.1, 12.0)
|
||||
elseif comm == SDL_SCANCODE_RIGHT
|
||||
range = max(pf.range - 0.1, 0.1)
|
||||
elseif comm == SDL_SCANCODE_SPACE
|
||||
pf.reciprocate = !pf.reciprocate
|
||||
elseif comm == SDL_SCANCODE_Q
|
||||
close = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
pf = update(pf, w, h, df)
|
||||
SDL_SetRenderDrawColor(renderer, 0x0, 0x0, 0x0, 0xff)
|
||||
SDL_RenderClear(renderer)
|
||||
rgb = parse(UInt32, hex(HSL((Dates.value(now()) % 5) * 72, pf.saturation, 0.5)), base=16)
|
||||
red, green, blue = rgb & 0xff, (rgb >> 8) & 0xff, (rgb >>16) & 0xff
|
||||
SDL_SetRenderDrawColor(renderer, red, green, blue, 0x7f)
|
||||
SDL_RenderDrawPoints(renderer, pf.points, pf.numpoints)
|
||||
SDL_RenderPresent(renderer)
|
||||
frames += 1
|
||||
df = Float64(Dates.value(now()) - Dates.value(dfstart)) / 1000
|
||||
elapsed = Float64(Dates.value(now()) - Dates.value(overallstart)) / 1000
|
||||
elapsed > 0.5 && print("\r", ' '^20, "\rFPS: ", round(frames / elapsed, digits=1))
|
||||
end
|
||||
SDL_Quit()
|
||||
end
|
||||
|
||||
println("""
|
||||
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 LEFT and RIGHT arrow keys to modify angle range for reciprocation.
|
||||
Press the "q" key to quit.
|
||||
""")
|
||||
|
||||
fountain()
|
||||
140
Task/Particle-fountain/Nim/particle-fountain.nim
Normal file
140
Task/Particle-fountain/Nim/particle-fountain.nim
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
import std/[lenientops, math, monotimes, random, times]
|
||||
import sdl2
|
||||
|
||||
type ParticleFountain[N: static Positive] = object
|
||||
positions: array[1..2 * N, float]
|
||||
velocities: array[1..2 * N, float]
|
||||
lifetimes: array[1..N, float]
|
||||
points: array[1..N, Point]
|
||||
numPoints: int
|
||||
saturation: float
|
||||
spread: float
|
||||
range: float
|
||||
reciprocate: bool
|
||||
|
||||
proc initParticleFountain[N: static Positive](): ParticleFountain[N] =
|
||||
ParticleFountain[N](saturation: 0.4, spread: 1.5, range: 1.5)
|
||||
|
||||
proc update(pf: var ParticleFountain; w, h: cint; df: float) =
|
||||
var
|
||||
xidx = 1
|
||||
yidx = 2
|
||||
pointidx = 0
|
||||
|
||||
template recip(pf: ParticleFountain): float =
|
||||
if pf.reciprocate: pf.range * sin(epochTime() / 1000) else: 0.0
|
||||
|
||||
for idx in 1..pf.N:
|
||||
var willDraw = false
|
||||
if pf.lifetimes[idx] <= 0:
|
||||
if rand(1.0) < df:
|
||||
pf.lifetimes[idx] = 2.5 # Time to live.
|
||||
# Starting position.
|
||||
pf.positions[xidx] = w / 20
|
||||
pf.positions[yidx] = h / 10
|
||||
# Starting velocity.
|
||||
pf.velocities[xidx] = 10 * (pf.spread * rand(1.0) - pf.spread / 2 + pf.recip())
|
||||
pf.velocities[yidx] = (rand(1.0) - 2.9) * h / 20.5
|
||||
willDraw = true
|
||||
else:
|
||||
if pf.positions[yidx] > h / 10 and pf.velocities[yidx] > 0:
|
||||
pf.velocities[yidx] *= -0.3 # "Bounce".
|
||||
pf.velocities[yidx] += df * h / 10 # Adjust velocity.
|
||||
pf.positions[xidx] += pf.velocities[xidx] * df # Adjust position x.
|
||||
pf.positions[yidx] += pf.velocities[yidx] * df # Adjust position y.
|
||||
pf.lifetimes[idx] -= df
|
||||
willDraw = true
|
||||
|
||||
if willDraw:
|
||||
# Gather all of the points that are going to be rendered.
|
||||
inc pointIdx
|
||||
pf.points[pointidx] = (cint(pf.positions[xidx] * 10), cint(pf.positions[yidx] * 10))
|
||||
inc xidx, 2
|
||||
yidx = xidx + 1
|
||||
pf.numPoints = pointidx
|
||||
|
||||
func hsvToRgb(h, s, v: float): (byte, byte, byte) =
|
||||
let hp = h / 60.0
|
||||
let c = s * v
|
||||
let x = c * (1 - abs(hp mod 2 - 1))
|
||||
let m = v - c
|
||||
var (r, g, b) = if hp <= 1: (c, x, 0.0)
|
||||
elif hp <= 2: (x, c, 0.0)
|
||||
elif hp <= 3: (0.0, c, x)
|
||||
elif hp <= 4: (0.0, x, c)
|
||||
elif hp <= 5: (x, 0.0, c)
|
||||
else: (c, 0.0, x)
|
||||
r += m
|
||||
g += m
|
||||
b += m
|
||||
result = (byte(r * 255), byte(g * 255), byte(b * 255))
|
||||
|
||||
proc fountain(particleNum = 3000; w = 800; h = 800) =
|
||||
var w = w.cint
|
||||
var h = h.cint
|
||||
discard sdl2.init(INIT_VIDEO or INIT_EVENTS)
|
||||
let window = createWindow("Nim Particle System!", SDL_WINDOWPOS_CENTERED_MASK,
|
||||
SDL_WINDOWPOS_CENTERED_MASK, w, h, SDL_WINDOW_RESIZABLE)
|
||||
let renderer = createRenderer(window, -1, 0)
|
||||
clearError()
|
||||
var df = 0.0001
|
||||
var pf = initParticleFountain[3000]()
|
||||
var close = false
|
||||
var frames = 0
|
||||
block Simulation:
|
||||
while not close:
|
||||
let dfStart = getMonoTime()
|
||||
var event: Event
|
||||
while bool(pollEvent(event)):
|
||||
case event.kind
|
||||
of QuitEvent:
|
||||
break Simulation
|
||||
of WindowEvent:
|
||||
if event.window.event == WindowEvent_Resized:
|
||||
w = event.window.data1
|
||||
h = event.window.data2
|
||||
of KeyDown:
|
||||
let comm = event.key.keysym.sym
|
||||
case comm
|
||||
of K_UP:
|
||||
pf.saturation = min(pf.saturation + 0.1, 1.0)
|
||||
of K_DOWN:
|
||||
pf.saturation = max(pf.saturation - 0.1, 0.0)
|
||||
of K_PAGEUP:
|
||||
pf.spread = min(pf.spread + 1.0, 50.0)
|
||||
of K_PAGEDOWN:
|
||||
pf.spread = max(pf.spread - 0.1, 0.2)
|
||||
of K_LEFT:
|
||||
pf.range = min(pf.range + 0.1, 12.0)
|
||||
of K_RIGHT:
|
||||
pf.range = max(pf.range - 0.1, 0.1)
|
||||
of K_SPACE:
|
||||
pf.reciprocate = not pf.reciprocate
|
||||
of K_Q:
|
||||
break Simulation
|
||||
else:
|
||||
discard
|
||||
else:
|
||||
discard
|
||||
|
||||
pf.update(w, h, df)
|
||||
renderer.setDrawColor(0x0, 0x0, 0x0, 0xff)
|
||||
renderer.clear()
|
||||
let (red, green, blue) = hsvToRgb(epochTime() mod 5 * 72, pf.saturation, 1.0)
|
||||
renderer.setDrawColor(red, green, blue, 0x7f)
|
||||
renderer.drawPoints(pf.points[1].addr, pf.numPoints.cint)
|
||||
renderer.present()
|
||||
inc frames
|
||||
df = (getMonoTime() - dfStart).inMilliseconds.float / 1000
|
||||
|
||||
sdl2.quit()
|
||||
|
||||
randomize()
|
||||
echo """
|
||||
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 LEFT and RIGHT arrow keys to modify angle range for reciprocation.
|
||||
Press the "q" key to quit.
|
||||
"""
|
||||
fountain()
|
||||
48
Task/Particle-fountain/Perl/particle-fountain.pl
Normal file
48
Task/Particle-fountain/Perl/particle-fountain.pl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict; # https://rosettacode.org/wiki/Particle_fountain
|
||||
use warnings;
|
||||
use Tk;
|
||||
|
||||
my $size = 900;
|
||||
my @particles;
|
||||
my $maxparticles = 500;
|
||||
my @colors = qw( red green blue yellow cyan magenta orange white );
|
||||
|
||||
my $mw = MainWindow->new;
|
||||
my $c = $mw->Canvas( -width => $size, -height => $size, -bg => 'black',
|
||||
)->pack;
|
||||
$mw->Button(-text => 'Exit', -command => sub {$mw->destroy},
|
||||
)->pack(-fill => 'x');
|
||||
|
||||
step();
|
||||
MainLoop;
|
||||
-M $0 < 0 and exec $0;
|
||||
|
||||
sub step
|
||||
{
|
||||
$c->delete('all');
|
||||
$c->createLine($size / 2 - 10, $size, $size / 2, $size - 10,
|
||||
$size / 2 + 10, $size, -fill => 'white' );
|
||||
for ( @particles )
|
||||
{
|
||||
my ($ox, $oy, $vx, $vy, $color) = @$_;
|
||||
my $x = $ox + $vx;
|
||||
my $y = $oy + $vy;
|
||||
$c->createRectangle($ox, $oy, $x, $y, -fill => $color, -outline => $color);
|
||||
if( $y < $size )
|
||||
{
|
||||
$_->[0] = $x;
|
||||
$_->[1] = $y;
|
||||
$_->[3] += 0.006; # gravity :)
|
||||
}
|
||||
else { $_ = undef }
|
||||
}
|
||||
@particles = grep defined, @particles;
|
||||
if( @particles < $maxparticles and --$| )
|
||||
{
|
||||
push @particles, [ $size >> 1, $size - 10,
|
||||
(1 - rand 2) / 2.5 , -3 - rand 0.05, $colors[rand @colors] ];
|
||||
}
|
||||
$mw->after(1 => \&step);
|
||||
}
|
||||
126
Task/Particle-fountain/Phix/particle-fountain.phix
Normal file
126
Task/Particle-fountain/Phix/particle-fountain.phix
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\rosetta\Particle_fountain.exw
|
||||
-- ==================================
|
||||
--</span>
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
|
||||
|
||||
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
|
||||
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Particle fountain"</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">help_text</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
|
||||
Uparrow increases the saturation of the particle colors,
|
||||
downarrow decreases saturation until they all become white.
|
||||
PageUp sprays the particles out at a wider angle/spread,
|
||||
PageDown makes the jet narrower.
|
||||
Space toggles reciprocation (wobble) on and off (straight up).
|
||||
Left arrow decreases the angle range for reciprocation,
|
||||
right arrow increases the angle range for reciprocation.
|
||||
Press the "q" key to quit.
|
||||
"""</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">particlenum</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3000</span>
|
||||
<span style="color: #000080;font-style:italic;">-- each particle is {x,y,color,life,dx,dy}</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">particles</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">particlenum</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #004080;">bool</span> <span style="color: #000000;">reciprocate</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">range</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1.5</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">spread</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1.5</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">saturation</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.4</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
|
||||
<span style="color: #000000;">df</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0001</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">particles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">color</span><span style="color: #0000FF;">,</span><span style="color: #000000;">life</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">particles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">life</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">cdCanvasPixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">-</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">color</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_BLACK</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">timer_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">fps</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">df</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">start</span>
|
||||
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">particlenum</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">color</span><span style="color: #0000FF;">,</span><span style="color: #000000;">life</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">particles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">life</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()<</span><span style="color: #000000;">df</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">life</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2.5</span> <span style="color: #000080;font-style:italic;">-- time to live</span>
|
||||
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- starting position x</span>
|
||||
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">-- and y
|
||||
-- randomize velocity so points reach different heights:</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">reciprocate</span><span style="color: #0000FF;">?</span><span style="color: #000000;">range</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()):</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">dx</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">spread</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">spread</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">50</span> <span style="color: #000080;font-style:italic;">-- starting velocity x</span>
|
||||
<span style="color: #000000;">dy</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">2.9</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">20.5</span> <span style="color: #000080;font-style:italic;">-- and y </span>
|
||||
<span style="color: #000000;">color</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">hsv_to_rgb</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">saturation</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">></span><span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span> <span style="color: #008080;">and</span> <span style="color: #000000;">dy</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">dy</span> <span style="color: #0000FF;">*=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">0.3</span> <span style="color: #000080;font-style:italic;">-- "bounce"</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">dy</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">df</span> <span style="color: #000080;font-style:italic;">-- adjust velocity</span>
|
||||
<span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">df</span> <span style="color: #000080;font-style:italic;">-- adjust position x</span>
|
||||
<span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">df</span><span style="color: #0000FF;">*</span><span style="color: #000000;">8</span> <span style="color: #000080;font-style:italic;">-- and y</span>
|
||||
<span style="color: #000000;">life</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">df</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">particles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">color</span><span style="color: #0000FF;">,</span><span style="color: #000000;">life</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">IupRedraw</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()></span><span style="color: #000000;">t1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s (%d, %d fps/s [%dx%d])"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">title</span><span style="color: #0000FF;">,</span><span style="color: #000000;">particlenum</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fps</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">fps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*dlg*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)=</span><span style="color: #008000;">'q'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_F1</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">IupMessage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">title</span><span style="color: #0000FF;">,</span><span style="color: #000000;">help_text</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_UP</span> <span style="color: #008080;">then</span> <span style="color: #000000;">saturation</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">saturation</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_DOWN</span> <span style="color: #008080;">then</span> <span style="color: #000000;">saturation</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">saturation</span><span style="color: #0000FF;">-</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_PGUP</span> <span style="color: #008080;">then</span> <span style="color: #000000;">spread</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">spread</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_PGDN</span> <span style="color: #008080;">then</span> <span style="color: #000000;">spread</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">spread</span><span style="color: #0000FF;">-</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_RIGHT</span> <span style="color: #008080;">then</span> <span style="color: #000000;">range</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_LEFT</span> <span style="color: #008080;">then</span> <span style="color: #000000;">range</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range</span><span style="color: #0000FF;">-</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_SP</span> <span style="color: #008080;">then</span> <span style="color: #000000;">reciprocate</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">reciprocate</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGLCanvas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RASTERSIZE=400x300"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupSetCallbacks</span><span style="color: #0000FF;">({</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="%s"`</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">title</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"KEY_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">timer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupTimer</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"timer_cb"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">1000</span><span style="color: #0000FF;">/</span><span style="color: #000000;">25</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupShowXY</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #004600;">IUP_CENTER</span><span style="color: #0000FF;">,</span><span style="color: #004600;">IUP_CENTER</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
|
||||
<!--
|
||||
178
Task/Particle-fountain/Raku/particle-fountain.raku
Normal file
178
Task/Particle-fountain/Raku/particle-fountain.raku
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
use NativeCall;
|
||||
use SDL2::Raw;
|
||||
|
||||
my int ($w, $h) = 800, 800;
|
||||
my SDL_Window $window;
|
||||
my SDL_Renderer $renderer;
|
||||
|
||||
my int $particlenum = 3000;
|
||||
|
||||
|
||||
SDL_Init(VIDEO);
|
||||
$window = SDL_CreateWindow(
|
||||
"Raku Particle System!",
|
||||
SDL_WINDOWPOS_CENTERED_MASK, SDL_WINDOWPOS_CENTERED_MASK,
|
||||
$w, $h,
|
||||
RESIZABLE
|
||||
);
|
||||
$renderer = SDL_CreateRenderer( $window, -1, ACCELERATED );
|
||||
|
||||
SDL_ClearError();
|
||||
|
||||
my num @positions = 0e0 xx ($particlenum * 2);
|
||||
my num @velocities = 0e0 xx ($particlenum * 2);
|
||||
my num @lifetimes = 0e0 xx $particlenum;
|
||||
|
||||
my CArray[int32] $points .= new;
|
||||
my int $numpoints;
|
||||
my Num $saturation = 4e-1;
|
||||
my Num $spread = 15e-1;
|
||||
my &reciprocate = sub { 0 }
|
||||
my $range = 1.5;
|
||||
|
||||
sub update (num \df) {
|
||||
my int $xidx = 0;
|
||||
my int $yidx = 1;
|
||||
my int $pointidx = 0;
|
||||
loop (my int $idx = 0; $idx < $particlenum; $idx = $idx + 1) {
|
||||
my int $willdraw = 0;
|
||||
if (@lifetimes[$idx] <= 0e0) {
|
||||
if (rand < df) {
|
||||
@lifetimes[$idx] = 25e-1; # time to live
|
||||
@positions[$xidx] = ($w / 20e0).Num; # starting position x
|
||||
@positions[$yidx] = ($h / 10).Num; # and y
|
||||
@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;
|
||||
}
|
||||
} else {
|
||||
if @positions[$yidx] > $h / 10 && @velocities[$yidx] > 0 {
|
||||
@velocities[$yidx] = @velocities[$yidx] * -0.3e0; # "bounce"
|
||||
}
|
||||
|
||||
@velocities[$yidx] = @velocities[$yidx] + $h/10.Num * df; # adjust velocity
|
||||
@positions[$xidx] = @positions[$xidx] + @velocities[$xidx] * df; # adjust position x
|
||||
@positions[$yidx] = @positions[$yidx] + @velocities[$yidx] * df; # and y
|
||||
|
||||
@lifetimes[$idx] = @lifetimes[$idx] - df;
|
||||
$willdraw = 1;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
$xidx = $xidx + 2;
|
||||
$yidx = $xidx + 1;
|
||||
}
|
||||
$numpoints = ($pointidx - 1) div 2;
|
||||
}
|
||||
|
||||
sub render {
|
||||
SDL_SetRenderDrawColor($renderer, 0x0, 0x0, 0x0, 0xff);
|
||||
SDL_RenderClear($renderer);
|
||||
|
||||
SDL_SetRenderDrawColor($renderer, |hsv2rgb(((now % 5) / 5).round(.01), $saturation, 1), 0x7f);
|
||||
SDL_RenderDrawPoints($renderer, $points, $numpoints);
|
||||
|
||||
SDL_RenderPresent($renderer);
|
||||
}
|
||||
|
||||
enum KEY_CODES (
|
||||
K_UP => 82,
|
||||
K_DOWN => 81,
|
||||
K_LEFT => 80,
|
||||
K_RIGHT => 79,
|
||||
K_SPACE => 44,
|
||||
K_PGUP => 75,
|
||||
K_PGDN => 78,
|
||||
K_Q => 20,
|
||||
);
|
||||
|
||||
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 LEFT and RIGHT arrow keys to modify angle range for reciprocation.
|
||||
Press the "q" key to quit.
|
||||
DOCS
|
||||
|
||||
my $event = SDL_Event.new;
|
||||
|
||||
my num $df = 0.0001e0;
|
||||
|
||||
main: loop {
|
||||
my $start = now;
|
||||
|
||||
while SDL_PollEvent($event) {
|
||||
my $casted_event = SDL_CastEvent($event);
|
||||
|
||||
given $casted_event {
|
||||
when *.type == QUIT {
|
||||
last main;
|
||||
}
|
||||
when *.type == WINDOWEVENT {
|
||||
if .event == RESIZED {
|
||||
$w = .data1;
|
||||
$h = .data2;
|
||||
}
|
||||
}
|
||||
when *.type == KEYDOWN {
|
||||
if KEY_CODES(.scancode) -> $comm {
|
||||
given $comm {
|
||||
when 'K_UP' { $saturation = (($saturation + .1) min 1e0) }
|
||||
when 'K_DOWN' { $saturation = (($saturation - .1) max 0e0) }
|
||||
when 'K_PGUP' { $spread = (($spread + .1) min 5e0) }
|
||||
when 'K_PGDN' { $spread = (($spread - .1) max 2e-1) }
|
||||
when 'K_RIGHT' { $range = (($range + .1) min 2e0) }
|
||||
when 'K_LEFT' { $range = (($range - .1) max 1e-1) }
|
||||
when 'K_SPACE' { &reciprocate = reciprocate() == 0 ?? sub { $range * sin(now) } !! sub { 0 } }
|
||||
when 'K_Q' { last main }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update($df);
|
||||
|
||||
render();
|
||||
|
||||
$df = (now - $start).Num;
|
||||
|
||||
print fps();
|
||||
}
|
||||
|
||||
say '';
|
||||
|
||||
sub fps {
|
||||
state $fps-frames = 0;
|
||||
state $fps-now = now;
|
||||
state $fps = '';
|
||||
$fps-frames++;
|
||||
if now - $fps-now >= 1 {
|
||||
$fps = [~] "\r", ' ' x 20, "\r",
|
||||
sprintf "FPS: %5.1f ", ($fps-frames / (now - $fps-now));
|
||||
$fps-frames = 0;
|
||||
$fps-now = now;
|
||||
}
|
||||
$fps
|
||||
}
|
||||
|
||||
sub hsv2rgb ( $h, $s, $v ){
|
||||
state %cache;
|
||||
%cache{"$h|$s|$v"} //= do {
|
||||
my $c = $v * $s;
|
||||
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
|
||||
my $m = $v - $c;
|
||||
[(do given $h {
|
||||
when 0..^1/6 { $c, $x, 0 }
|
||||
when 1/6..^1/3 { $x, $c, 0 }
|
||||
when 1/3..^1/2 { 0, $c, $x }
|
||||
when 1/2..^2/3 { 0, $x, $c }
|
||||
when 2/3..^5/6 { $x, 0, $c }
|
||||
when 5/6..1 { $c, 0, $x }
|
||||
} ).map: ((*+$m) * 255).Int]
|
||||
}
|
||||
}
|
||||
139
Task/Particle-fountain/Wren/particle-fountain.wren
Normal file
139
Task/Particle-fountain/Wren/particle-fountain.wren
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
import "dome" for Window, Platform, Process
|
||||
import "graphics" for Canvas, Color
|
||||
import "math" for Math, Point
|
||||
import "random" for Random
|
||||
import "input" for Keyboard
|
||||
import "./dynamic" for Struct
|
||||
|
||||
var Start = Platform.time
|
||||
var Rand = Random.new()
|
||||
|
||||
var fields = [
|
||||
"particleNum",
|
||||
"positions",
|
||||
"velocities",
|
||||
"lifetimes",
|
||||
"points",
|
||||
"numPoints",
|
||||
"saturation",
|
||||
"spread",
|
||||
"range",
|
||||
"reciprocate"
|
||||
]
|
||||
var ParticleFountain = Struct.create("ParticleFountain", fields)
|
||||
|
||||
class ParticleDisplay {
|
||||
construct new(particleNum, width, height) {
|
||||
Window.resize(width, height)
|
||||
Canvas.resize(width, height)
|
||||
Window.title = "Wren Particle System!"
|
||||
_pn = particleNum
|
||||
_w = width
|
||||
_h = height
|
||||
_df = 1 / 200 // say
|
||||
_pf = ParticleFountain.new(
|
||||
_pn, // particleNum
|
||||
List.filled(_pn * 2, 0), // positions
|
||||
List.filled(_pn * 2, 0), // velocities
|
||||
List.filled(_pn, 0), // lifetimes
|
||||
List.filled(_pn, null), // points
|
||||
0, // numPoints
|
||||
0.4, // saturation
|
||||
1.5, // spread
|
||||
1.5, // range
|
||||
false // reciprocate
|
||||
)
|
||||
for (i in 0..._pn) _pf.points[i] = Point.new(0, 0)
|
||||
}
|
||||
|
||||
init() {
|
||||
Canvas.cls()
|
||||
_frames = 0
|
||||
}
|
||||
|
||||
updatePF() {
|
||||
var xidx = 0
|
||||
var yidx = 1
|
||||
var pointIdx = 0
|
||||
var recip = Fn.new { _pf.reciprocate ? _pf.range * Math.sin(Platform.time/1000) : 0 }
|
||||
for (idx in 0..._pf.particleNum) {
|
||||
var willDraw = false
|
||||
if (_pf.lifetimes[idx] <= 0) {
|
||||
if (Rand.float() < _df) {
|
||||
_pf.lifetimes[idx] = 2.5 // time to live
|
||||
_pf.positions[xidx] = _w / 20 // starting position x
|
||||
_pf.positions[yidx] = _h / 10 // and y
|
||||
|
||||
// starting velocities x and y
|
||||
// randomized slightly so points reach different heights
|
||||
_pf.velocities[xidx] = 10 * (_pf.spread * Rand.float() - _pf.spread / 2 + recip.call())
|
||||
_pf.velocities[yidx] = (Rand.float() - 2.9) * _h / 20.5
|
||||
_willDraw = true
|
||||
}
|
||||
} else {
|
||||
if (_pf.positions[yidx] > _h/10 && _pf.velocities[yidx] > 0) {
|
||||
_pf.velocities[yidx] = _pf.velocities[yidx] * (-0.3) // bounce
|
||||
}
|
||||
_pf.velocities[yidx] = _pf.velocities[yidx] + _df * _h / 10 // adjust velocity
|
||||
_pf.positions[xidx] = _pf.positions[xidx] + _pf.velocities[xidx] * _df // adjust position x
|
||||
_pf.positions[yidx] = _pf.positions[yidx] + _pf.velocities[yidx] * _df // and y
|
||||
_pf.lifetimes[idx] = _pf.lifetimes[idx] - _df
|
||||
willDraw = true
|
||||
}
|
||||
if (willDraw) { // gather all the points that are going to be rendered
|
||||
_pf.points[pointIdx] = Point.new((_pf.positions[xidx] * 10).floor,
|
||||
(_pf.positions[yidx] * 10).floor)
|
||||
pointIdx = pointIdx + 1
|
||||
}
|
||||
xidx = xidx + 2
|
||||
yidx = xidx + 1
|
||||
_pf.numPoints = pointIdx
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
if (Keyboard["Up"].justPressed) {
|
||||
_pf.saturation = Math.min(_pf.saturation + 0.1, 1)
|
||||
} else if (Keyboard["Down"].justPressed) {
|
||||
_pf.saturation = Math.max(_pf.saturation - 0.1, 0)
|
||||
} else if (Keyboard["PageUp"].justPressed) {
|
||||
_pf.spread = Math.min(_pf.spread + 1, 50)
|
||||
} else if (Keyboard["PageDown"].justPressed) {
|
||||
_pf.spread = Math.max(_pf.spread - 0.1, 0.2)
|
||||
} else if (Keyboard["Left"].justPressed) {
|
||||
_pf.range = Math.min(_pf.range + 0.1, 12)
|
||||
} else if (Keyboard["Right"].justPressed) {
|
||||
_pf.range = Math.max(_pf.range - 0.1, 0.1)
|
||||
} else if (Keyboard["Space"].justPressed) {
|
||||
_pf.reciprocate = !_pf.reciprocate
|
||||
} else if (Keyboard["Q"].justPressed) {
|
||||
Process.exit()
|
||||
}
|
||||
updatePF()
|
||||
}
|
||||
|
||||
draw(alpha) {
|
||||
var c = Color.hsv((Platform.time % 5) * 72, _pf.saturation, 0.5, 0x7f)
|
||||
for (i in 0..._pf.numPoints) {
|
||||
Canvas.pset(_pf.points[i].x, _pf.points[i].y, c)
|
||||
}
|
||||
_frames = _frames + 1
|
||||
var now = Platform.time
|
||||
if (now - Start >= 1) {
|
||||
Start = now
|
||||
Window.title = "Wren Particle System! (FPS = %(_frames))"
|
||||
_frames = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.print("""
|
||||
|
||||
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 LEFT and RIGHT arrow keys to modify angle range for reciprocation.
|
||||
Press the "q" key to quit.
|
||||
""")
|
||||
|
||||
var Game = ParticleDisplay.new(3000, 800, 800)
|
||||
Loading…
Add table
Add a link
Reference in a new issue