GTK: Oops. Add particle files.

This commit is contained in:
Brandon Wright 2019-11-10 12:46:40 -06:00
parent 19f7423f42
commit 0258422be8
2 changed files with 244 additions and 0 deletions

View File

@ -0,0 +1,192 @@
#include "background_particles.h"
#include <cstring>
#include <cmath>
#include <cstdio>
#include <random>
static const double pi = 3.141592;
namespace Background
{
Particles::Particles(enum Mode mode)
{
this->mode = Invalid;
setmode(mode);
}
Particles::~Particles()
{
}
void Particles::setmode(enum Mode mode)
{
if (mode == this->mode)
return;
std::random_device device;
mt.seed(device());
output.resize(256 * 224 * 2);
gameimage.resize(256 * 224 * 2);
uint16_t r, g, b;
if (mode == Snow)
{
r = 0; g = 2; b = 6;
}
else
{
r = 0; g = 0; b = 0;
}
for (int i = 0; i < 256 * 224; i++)
{
output[i] = (r << 11) | (g << 6) | (b);
}
particles.clear();
this->mode = mode;
std::uniform_real_distribution<double> real(-0.8, 0.8);
wind = real(mt);
for (int l = 0; l < 32; l++)
{
int mixr = r + (l / 31.0) * (31 - r);
int mixg = g + (l / 31.0) * (31 - g);
int mixb = b + (l / 31.0) * (31 - b);
color_table[l] = (mixr << 11) | (mixg << 6) | mixb;
}
}
void Particles::copyto(uint16_t *dst, int pitch)
{
for (int y = 0; y < 224; y++)
{
memcpy((uint8_t *)dst + y * pitch, &output[y * 256], 512);
}
}
void Particles::set_game_image(uint16_t *src, int pitch)
{
for (int y = 0; y < 224; y++)
memcpy(&gameimage[y * 256], &src[y * pitch / 2], 512);
}
void Particles::advance()
{
if (mode == Snow)
advance_snow();
else
advance_starfield();
}
inline void Particles::setpixel(int x, int y, uint16_t l)
{
output[x + (y << 8)] = color_table[l];
}
void Particles::advance_starfield()
{
rate = 0.5;
std::uniform_real_distribution<double> realrand(0.0, 1.0);
if (realrand(mt) <= rate)
{
Particle pt;
double angle = realrand(mt) * 2 * pi;
pt.dx = cos(angle);
pt.dy = sin(angle) * 0.7;
pt.x = 128.5 + pt.dx * 5.0;
pt.y = 112.5 + pt.dy * 5.0;
pt.intensity = 0;
particles.push_back(pt);
}
for (auto p = particles.begin(); p != particles.end(); p++)
{
setpixel(p->x - 0.5, p->y - 0.5, 0);
setpixel(p->x + 0.5, p->y + 0.5, 0);
setpixel(p->x + 0.5, p->y - 0.5, 0);
setpixel(p->x - 0.5, p->y + 0.5, 0);
p->x += p->dx;
p->y += p->dy;
if ((int)p->x < 1 || (int)p->x > 255 || (int)p->y < 1 || (int)p->y > 223)
{
p = particles.erase(p);
continue;
}
p->intensity = (p->intensity + 1);
if (p->intensity > 63)
p->intensity = 63;
uint16_t lum = p->intensity >> 1;
// primitive bilinear filter effect
double dx = p->x - 0.5;
dx = dx - floor(dx);
double dy = p->y - 0.5;
dy = dy - floor(dy);
uint16_t cul = (1.0 - dx) * (1.0 - dy) * lum;
uint16_t cur = (dx) * (1.0 - dy) * lum;
uint16_t cll = (1.0 - dx) * (dy)*lum;
uint16_t clr = (dx) * (dy)*lum;
setpixel(p->x - 0.5, p->y - 0.5, cul);
setpixel(p->x + 0.5, p->y - 0.5, cur);
setpixel(p->x - 0.5, p->y + 0.5, cll);
setpixel(p->x + 0.5, p->y + 0.5, clr);
}
}
void Particles::advance_snow()
{
rate = 1.0;
std::uniform_real_distribution<double> realrand;
realrand = std::uniform_real_distribution<double>(-0.01, std::nextafter(0.01, 1.0));
wind += realrand(mt);
if (wind < -0.8)
wind = -0.8;
if (wind > 0.8)
wind = 0.8;
for (double new_snowflakes = rate; new_snowflakes >= 1.0; new_snowflakes -= 1.0)
{
Particle pt;
realrand = std::uniform_real_distribution<double>(0.0, 1.0);
pt.x = ((wind + 0.8) / 1.6) * -192.0 + realrand(mt) * 384.0;
pt.y = 0.0;
pt.dx = 0.0;
pt.dy = 0.6 + (realrand(mt) * 0.8);
std::uniform_int_distribution<int> intrand(8, 31);
pt.intensity = intrand(mt);
particles.push_back(pt);
}
for (auto p = particles.begin(); p != particles.end(); p++)
{
if (p->x > 0.0 && p->x < 256.0)
setpixel(p->x, p->y, 0);
p->x += wind;
p->y += p->dy;
if ((int)p->y > 223)
{
p = particles.erase(p);
}
else if (p->x > 0.0 && p->x < 256.0)
setpixel(p->x, p->y, p->intensity);
}
}
} // namespace Background

View File

@ -0,0 +1,52 @@
#pragma once
#include <vector>
#include <list>
#include <cstdint>
#include <random>
namespace Background
{
class Particles
{
public:
double rate = 0.5;
enum Mode
{
Stars,
Snow,
Invalid
};
struct Particle
{
double x, y, dx, dy;
unsigned int intensity;
};
Particles(enum Mode = Stars);
~Particles();
void advance();
void copyto(uint16_t *dst, int pitch);
enum Mode getmode();
void setmode(enum Mode);
void set_game_image(uint16_t *src, int pitch);
std::vector<uint16_t> output;
private:
inline void setpixel(int x, int y, uint16_t l);
void advance_snow();
void advance_starfield();
std::minstd_rand mt;
std::uniform_real_distribution<double> dis;
std::vector<uint16_t> gameimage;
std::list<Particle> particles;
enum Mode mode;
double wind;
uint16_t color_table[32];
};
} // namespace Background