From 082acc4451b1032e740bbf584628bc4b953cb05c Mon Sep 17 00:00:00 2001 From: Karma Riuk Date: Tue, 13 Jun 2023 13:50:07 +0200 Subject: [PATCH] Added random color generation to the polygons, also made so that the color of the vector indicating speed is the same as the color of the polygon, but a little lighter --- Makefile | 5 +-- color.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++ color.h | 17 +++++++++ main.cc | 4 +++ polygons.cc | 97 ++++++++++++++++++++++++++++++++++++++----------- polygons.h | 4 +++ vec2d.h | 5 +-- 7 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 color.cc create mode 100644 color.h diff --git a/Makefile b/Makefile index 4d4d1b3..464257a 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ CXXFLAGS=-Wall -g -O2 $(PROFILING_CFLAGS) $(GTK_CFLAGS) LIBS=$(GTK_LIBS) -lm PROGS=balls -OBJS=balls.o c_index.o game.o gravity.o spaceship.o main.o polygons.o polygon_generator.o collisions.o +OBJS=balls.o c_index.o game.o gravity.o spaceship.o main.o polygons.o polygon_generator.o collisions.o color.o # dependencies (gcc -MM *.cc) balls.o: balls.cc game.h balls.h vec2d.h gravity.h @@ -21,9 +21,10 @@ gravity.o: gravity.cc gravity.h balls.h vec2d.h game.h main.o: main.cc game.h balls.h vec2d.h c_index.h gravity.h spaceship.h spaceship.o: spaceship.cc balls.h vec2d.h game.h stats.o: stats.cc -polygons.o: polygons.cc polygons.h vec2d.h polygon_generator.h +polygons.o: polygons.cc polygons.h vec2d.h polygon_generator.h color.h polygon_generator.o: polygon_generator.cc polygon_generator.h collisions.o: collisions.cc collisions.h vec2d.h +color.o: color.cc color.h .PHONY: run diff --git a/color.cc b/color.cc new file mode 100644 index 0000000..6dfc155 --- /dev/null +++ b/color.cc @@ -0,0 +1,102 @@ +#include "color.h" + +// taken from +// https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both +hsv_t rgb2hsv(color_t in) { + hsv_t out; + double min, max, delta; + + min = in.red < in.green ? in.red : in.green; + min = min < in.blue ? min : in.blue; + + max = in.red > in.green ? in.red : in.green; + max = max > in.blue ? max : in.blue; + + out.val = max; // v + delta = max - min; + if (delta < 0.00001) { + out.sat = 0; + out.hue = 0; // undefined, maybe nan? + return out; + } + if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash + out.sat = (delta / max); // s + } else { + // if max is 0, then r = g = b = 0 + // s = 0, h is undefined + out.sat = 0.0; + out.hue = NAN; // its now undefined + return out; + } + if (in.red >= max) // > is bogus, just keeps compilor happy + out.hue = (in.green - in.blue) / delta; // between yellow & magenta + else if (in.green >= max) + out.hue = 2.0 + (in.blue - in.red) / delta; // between cyan & yellow + else + out.hue = 4.0 + (in.red - in.green) / delta; // between magenta & cyan + + out.hue *= 60.0; // degrees + + if (out.hue < 0.0) + out.hue += 360.0; + + return out; +} + +color_t hsv2rgb(hsv_t in) { + double hh, p, q, t, ff; + long i; + color_t out; + + if (in.sat <= 0.0) { // < is bogus, just shuts up warnings + out.red = in.val; + out.green = in.val; + out.blue = in.val; + return out; + } + hh = in.hue; + if (hh >= 360.0) + hh = 0.0; + hh /= 60.0; + i = (long) hh; + ff = hh - i; + p = in.val * (1.0 - in.sat); + q = in.val * (1.0 - (in.sat * ff)); + t = in.val * (1.0 - (in.sat * (1.0 - ff))); + + switch (i) { + case 0: + out.red = in.val; + out.green = t; + out.blue = p; + break; + case 1: + out.red = q; + out.green = in.val; + out.blue = p; + break; + case 2: + out.red = p; + out.green = in.val; + out.blue = t; + break; + + case 3: + out.red = p; + out.green = q; + out.blue = in.val; + break; + case 4: + out.red = t; + out.green = p; + out.blue = in.val; + break; + case 5: + default: + out.red = in.val; + out.green = p; + out.blue = q; + break; + } + return out; +} diff --git a/color.h b/color.h new file mode 100644 index 0000000..2f1e9d1 --- /dev/null +++ b/color.h @@ -0,0 +1,17 @@ +#ifndef COLOR_H_INCLUDED +#define COLOR_H_INCLUDED + +#include + +struct color_t { + double red, green, blue; +}; + +struct hsv_t { + double hue, sat, val; +}; + +extern hsv_t rgb2hsv(color_t in); +extern color_t hsv2rgb(hsv_t in); + +#endif diff --git a/main.cc b/main.cc index 6822b2c..b56df81 100644 --- a/main.cc +++ b/main.cc @@ -213,6 +213,10 @@ gint keyboard_input(GtkWidget* widget, GdkEventKey* event) { case GDK_KEY_p: game_animation_on_off(); return TRUE; + case GDK_KEY_S: + case GDK_KEY_s: + draw_speed = !draw_speed; + return TRUE; case GDK_KEY_Q: case GDK_KEY_q: gtk_main_quit(); diff --git a/polygons.cc b/polygons.cc index 16ca336..74f0f16 100644 --- a/polygons.cc +++ b/polygons.cc @@ -13,9 +13,28 @@ #include #include +#define ARROW_VAL_RATIO 1.7 + + +bool draw_speed = true; + polygon* polygons = nullptr; uint n_polygons = 0; +static double to_rad(double angle_in_deg) { + static double PI_180 = M_PI / 180.; + return angle_in_deg * PI_180; +} + +static double to_deg(double angle_in_rad) { + static double PI_180 = 180. / M_PI; + return angle_in_rad * PI_180; +} + +static double random_color_component() { + return 1.0 * (rand() % 200 + 56) / 255; +}; + void polygons_init_state() { n_polygons = 20; polygons = new polygon[n_polygons]; @@ -38,12 +57,19 @@ void polygons_init_state() { .set_mass(INFINITY) .set_center({width + wall_thickness / 2., height / 2.}); - // middle wall - polygons[n++] = poly_generate::rectangle(50, height / 2.) + // top triangle wall + polygons[n++] = poly_generate::triangle(height / 4., height / 4., 90) .set_mass(INFINITY) - .set_center({25 + width * 1. / 2, height / 2.}) - .set_angle(30); + .set_center({width / 2., height / 17.}) + .set_angle(-135); + // bottom triangle wall + polygons[n++] = poly_generate::triangle(height / 4., height / 4., 90) + .set_mass(INFINITY) + .set_center({width / 2., height - height / 17.}) + .set_angle(45); + + // ---------- Shapes flying around start here ---------- polygons[n++] = poly_generate::regular(100, 3) .set_center({100, 400}) .set_angle(0) @@ -64,24 +90,37 @@ void polygons_init_state() { polygons[n++] = poly_generate::rectangle(100, 150).set_center({600, 200}); polygons[n++] = poly_generate::regular(50, 5) .set_center({150, 150}) - .set_speed({50, -50}); - polygons[n++] = - poly_generate::general({{0, 0}, {50, 80}, {0, 160}, {-50, 80}}) - .set_center({700, 700}) - .set_speed({0, -100}); + .set_speed({100, 0}); + + polygons[n++] = poly_generate::general({{40, 20}, + {40, 40}, + {80, 40}, + {80, -40}, + {40, -40}, + {40, -20}, + {-40, -20}, + {-40, -40}, + {-80, -40}, + {-80, 40}, + {-40, 40}, + {-40, 20}}) + .set_center({700, 700}) + .set_speed({0, -100}); assert(n <= n_polygons); n_polygons = n; -} -static double to_rad(double angle_in_deg) { - static double PI_180 = M_PI / 180.; - return angle_in_deg * PI_180; -} - -static double to_deg(double angle_in_rad) { - static double PI_180 = 180. / M_PI; - return angle_in_rad * PI_180; + // Set the color of the polygons to random + for (polygon* p = polygons; p != polygons + n_polygons; ++p) { + p->color = { + random_color_component(), + random_color_component(), + random_color_component()}; + hsv_t hsv = rgb2hsv(p->color); + if (hsv.val > 0.95) + hsv.val *= .7; + p->color = hsv2rgb(hsv); + } } static bool is_point_inside_rect(rect rect, vec2d point) { @@ -252,15 +291,31 @@ void polygon::draw(cairo_t* cr) const { cairo_line_to(cr, point.x, point.y); cairo_line_to(cr, this->global_points[0].x, this->global_points[0].y); - cairo_stroke(cr); - + if (mass == INFINITY) { + cairo_set_source_rgb(cr, .5, .5, .5); + cairo_fill(cr); + } else { + cairo_set_source_rgb( + cr, + this->color.red, + this->color.green, + this->color.blue + ); + cairo_fill(cr); + } // draw centroid vec2d centroid = this->centroid(); draw_circle(cr, centroid, 1); + // draw speed - (delta * this->speed).draw(cr, centroid); + if (draw_speed && this->mass != INFINITY) { + hsv_t hsv = rgb2hsv(this->color); + hsv.val = hsv.val * ARROW_VAL_RATIO; + color_t arrow_color = hsv2rgb(hsv); + (delta * this->speed).draw(cr, centroid, arrow_color); + } } void polygons_draw(cairo_t* cr) { diff --git a/polygons.h b/polygons.h index a72ff6a..6920909 100644 --- a/polygons.h +++ b/polygons.h @@ -1,6 +1,7 @@ #ifndef POLYGONS_H_INCLUDED #define POLYGONS_H_INCLUDED +#include "color.h" #include "vec2d.h" #include @@ -22,6 +23,7 @@ class polygon { double mass; std::string label; + color_t color; std::vector global_points = points; vec2d speed; @@ -118,6 +120,8 @@ class polygon { extern polygon* polygons; extern uint n_polygons; +extern bool draw_speed; + extern void polygons_init_state(); extern void polygons_update_state(); extern void polygons_draw(cairo_t* cr); diff --git a/vec2d.h b/vec2d.h index 4be0408..869fa34 100644 --- a/vec2d.h +++ b/vec2d.h @@ -2,6 +2,7 @@ #define VEC2D_H_INCLUDED #include "cairo.h" +#include "color.h" #include #include @@ -74,7 +75,7 @@ class vec2d { return {-y, x}; } - void draw(cairo_t* cr, vec2d p) const { + void draw(cairo_t* cr, vec2d p, color_t color) const { double arrow_lenght_ = 10 * vec2d::norm(*this); double arrow_degrees_ = .5; @@ -90,7 +91,7 @@ class vec2d { double x2 = end.x + head_length * cos(angle + arrow_degrees_); double y2 = end.y + head_length * sin(angle + arrow_degrees_); - cairo_set_source_rgb(cr, 255, 0, 0); + cairo_set_source_rgb(cr, color.red, color.green, color.blue); cairo_move_to(cr, p.x, p.y); cairo_line_to(cr, end.x, end.y);