commit 668df50c1aeb24bafe3fc66e4b81b0458ff35ad3
parent d184871cba902bde048ad1e56752ae451cafc2c3
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Mon, 24 Jun 2024 00:25:18 +0100
sdl-gl: Make stars have random colour and spin
Diffstat:
M | src/sdl-gl.cpp | | | 98 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
1 file changed, 75 insertions(+), 23 deletions(-)
diff --git a/src/sdl-gl.cpp b/src/sdl-gl.cpp
@@ -14,6 +14,8 @@
#include <memory>
#include <numbers>
#include <print>
+#include <random>
+#include <ranges>
#include <vector>
extern "C" char const* __asan_default_options() { return "detect_leaks=0"; }
@@ -82,7 +84,7 @@ void initSDL(void)
if (SDL_Init(SDL_INIT_VIDEO) < 0)
errx(1, "Couldn't initialize SDL: %s\n", SDL_GetError());
- window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, windowFlags);
+ window = SDL_CreateWindow("SDL OpenGL example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, windowFlags);
if (!window)
errx(1, "Failed to open %d x %d window: %s\n", screen_width, screen_height, SDL_GetError());
@@ -94,11 +96,30 @@ void initSDL(void)
errx(1, "Failed to make OpenGL context current: %s", SDL_GetError());
}
+std::mt19937 gen;
+std::lognormal_distribution<float> dis(-1, .75);
+std::normal_distribution<float> norm_dis;
struct rgb
{
float r,g,b;
+
+ rgb operator + (rgb const& rhs) const
+ {
+ return {r + rhs.r, g + rhs.g, b + rhs.b};
+ }
+
+ static rgb random()
+ {
+ return {dis(gen), dis(gen), dis(gen)};
+ }
};
+void glColor(rgb const& c)
+{
+ glColor3f(c.r, c.g, c.b);
+}
+
+
struct coord
{
int x, y;
@@ -178,36 +199,37 @@ struct object
{
point pos;
rgb col;
+ float spin;
+ float rotation;
};
std::vector<std::shared_ptr<object>> objs = {
- std::make_shared<object>(point{0, 0}, rgb{.7,.2,.2}),
- std::make_shared<object>(point{4, 0}, rgb{.2,.7,.2}),
- std::make_shared<object>(point{0, 5}, rgb{.2,.2,.7}),
+ std::make_shared<object>(point{0, 0}, rgb{.7,.2,.2}, .2),
+ std::make_shared<object>(point{4, 0}, rgb{.2,.7,.2}, 0),
+ std::make_shared<object>(point{0, 5}, rgb{.2,.2,.7}, -.2),
};
std::vector<point> shape;
+constexpr auto deref = std::views::transform([](auto const& p) -> auto& { return *p; });
+
void presentScene(void)
{
- static double turns = 0;
- turns += 1./60/4;
- rotor r = rotor::angle(turns);
-
float x_scale = (float)screen_height / screen_width;
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
circle mouse_area{mouse_pos, 1};
- for (auto& optr : objs) {
- auto& op = *optr;
- if (mouse_area.colliding(op.pos))
- glColor3d(op.col.r + .25,op.col.g + .25,op.col.b + .25);
+ for (auto& o : objs | deref) {
+ o.rotation += o.spin / 60;
+ rotor r = rotor::angle(o.rotation);
+ if (mouse_area.colliding(o.pos))
+ glColor(o.col + rgb{.25f, .25f, .25f,});
else
- glColor3f(op.col.r, op.col.g, op.col.b);
+ glColor(o.col);
glBegin(GL_TRIANGLE_FAN);
for (auto& p : shape) {
- auto pp = (p * r + pan + op.pos) * scale;
+ auto pp = (p * r + pan + o.pos) * scale;
glVertex2f(pp.x * x_scale, pp.y);
}
glEnd();
@@ -218,6 +240,8 @@ void presentScene(void)
void key(SDL_KeyboardEvent& e)
{
+ if (e.repeat)
+ return;
static uint8_t ctrls;
switch (e.keysym.sym)
{
@@ -233,7 +257,7 @@ void key(SDL_KeyboardEvent& e)
case SDLK_a:
if (e.state)
- objs.push_back(std::make_shared<object>(mouse_pos, rgb{.5, .5, .2}));
+ objs.push_back(std::make_shared<object>(mouse_pos, rgb::random(), norm_dis(gen), 0));
break;
case SDLK_d:
@@ -244,6 +268,31 @@ void key(SDL_KeyboardEvent& e)
}
break;
+ case SDLK_r:
+ if (e.state)
+ {
+ circle mouse_area{mouse_pos, 1};
+ for (auto& obj : objs | deref)
+ if (mouse_area.colliding(obj.pos))
+ {
+ std::swap(obj.col.r, obj.col.g);
+ std::swap(obj.col.g, obj.col.b);
+ }
+
+ }
+ break;
+
+ case SDLK_s:
+ if (e.state)
+ {
+ circle mouse_area{mouse_pos, 1};
+ for (auto& obj : objs | deref)
+ if (mouse_area.colliding(obj.pos))
+ obj.spin *= -1;
+
+ }
+ break;
+
case SDLK_ESCAPE:
exit(0);
}
@@ -295,15 +344,17 @@ coroutine_task mouse_task()
auto it = std::ranges::find_if(objs, [drag_pos, mouse_area](auto const& o){return mouse_area.colliding(o->pos);});
if (it == std::end(objs))
break;
- auto obj = *it;
- std::swap(obj->col.r, obj->col.g);
- std::swap(obj->col.g, obj->col.b);
- drag_pos = obj->pos - mouse_to_local(e.x, e.y);
+
+ drag_pos = (*it)->pos - mouse_to_local(e.x, e.y);
+ std::weak_ptr<object> wp = *it;
+
for (;;)
{
SDL_Event const& e2 = co_await motion_or_release_event;
- if (e2.type == SDL_MOUSEMOTION)
- obj->pos = drag_pos + mouse_to_local(e2.motion.x, e2.motion.y);
+ if (wp.expired())
+ break;
+ else if (e2.type == SDL_MOUSEMOTION)
+ wp.lock()->pos = drag_pos + mouse_to_local(e2.motion.x, e2.motion.y);
else if (auto& b = e2.button; b.button == SDL_BUTTON_LEFT)
break;
}
@@ -371,9 +422,10 @@ void doInput()
void init_shape()
{
+ constexpr int n = 10;
shape.emplace_back(0,0);
- for (int i = 0; i <= 8; ++i)
- shape.push_back(point{1, 0} * rotor::angle((float)i / 8));
+ for (int i = 0; i <= n; ++i)
+ shape.push_back(point{0, (.65f + i % 2) / -1.65f} * rotor::angle((float)i / n));
}
int main()