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
This commit is contained in:
Karma Riuk 2023-06-13 13:50:07 +02:00
parent 79ac43f05c
commit 082acc4451
7 changed files with 209 additions and 25 deletions

View File

@ -11,7 +11,7 @@ CXXFLAGS=-Wall -g -O2 $(PROFILING_CFLAGS) $(GTK_CFLAGS)
LIBS=$(GTK_LIBS) -lm LIBS=$(GTK_LIBS) -lm
PROGS=balls 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) # dependencies (gcc -MM *.cc)
balls.o: balls.cc game.h balls.h vec2d.h gravity.h 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 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 spaceship.o: spaceship.cc balls.h vec2d.h game.h
stats.o: stats.cc 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 polygon_generator.o: polygon_generator.cc polygon_generator.h
collisions.o: collisions.cc collisions.h vec2d.h collisions.o: collisions.cc collisions.h vec2d.h
color.o: color.cc color.h
.PHONY: run .PHONY: run

102
color.cc Normal file
View File

@ -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;
}

17
color.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef COLOR_H_INCLUDED
#define COLOR_H_INCLUDED
#include <cmath>
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

View File

@ -213,6 +213,10 @@ gint keyboard_input(GtkWidget* widget, GdkEventKey* event) {
case GDK_KEY_p: case GDK_KEY_p:
game_animation_on_off(); game_animation_on_off();
return TRUE; return TRUE;
case GDK_KEY_S:
case GDK_KEY_s:
draw_speed = !draw_speed;
return TRUE;
case GDK_KEY_Q: case GDK_KEY_Q:
case GDK_KEY_q: case GDK_KEY_q:
gtk_main_quit(); gtk_main_quit();

View File

@ -13,9 +13,28 @@
#include <iostream> #include <iostream>
#include <utility> #include <utility>
#define ARROW_VAL_RATIO 1.7
bool draw_speed = true;
polygon* polygons = nullptr; polygon* polygons = nullptr;
uint n_polygons = 0; 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() { void polygons_init_state() {
n_polygons = 20; n_polygons = 20;
polygons = new polygon[n_polygons]; polygons = new polygon[n_polygons];
@ -38,12 +57,19 @@ void polygons_init_state() {
.set_mass(INFINITY) .set_mass(INFINITY)
.set_center({width + wall_thickness / 2., height / 2.}); .set_center({width + wall_thickness / 2., height / 2.});
// middle wall // top triangle wall
polygons[n++] = poly_generate::rectangle(50, height / 2.) polygons[n++] = poly_generate::triangle(height / 4., height / 4., 90)
.set_mass(INFINITY) .set_mass(INFINITY)
.set_center({25 + width * 1. / 2, height / 2.}) .set_center({width / 2., height / 17.})
.set_angle(30); .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) polygons[n++] = poly_generate::regular(100, 3)
.set_center({100, 400}) .set_center({100, 400})
.set_angle(0) .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::rectangle(100, 150).set_center({600, 200});
polygons[n++] = poly_generate::regular(50, 5) polygons[n++] = poly_generate::regular(50, 5)
.set_center({150, 150}) .set_center({150, 150})
.set_speed({50, -50}); .set_speed({100, 0});
polygons[n++] =
poly_generate::general({{0, 0}, {50, 80}, {0, 160}, {-50, 80}}) 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_center({700, 700})
.set_speed({0, -100}); .set_speed({0, -100});
assert(n <= n_polygons); assert(n <= n_polygons);
n_polygons = n; n_polygons = n;
}
static double to_rad(double angle_in_deg) { // Set the color of the polygons to random
static double PI_180 = M_PI / 180.; for (polygon* p = polygons; p != polygons + n_polygons; ++p) {
return angle_in_deg * PI_180; p->color = {
} random_color_component(),
random_color_component(),
static double to_deg(double angle_in_rad) { random_color_component()};
static double PI_180 = 180. / M_PI; hsv_t hsv = rgb2hsv(p->color);
return angle_in_rad * PI_180; if (hsv.val > 0.95)
hsv.val *= .7;
p->color = hsv2rgb(hsv);
}
} }
static bool is_point_inside_rect(rect rect, vec2d point) { 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, point.x, point.y);
cairo_line_to(cr, this->global_points[0].x, this->global_points[0].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 // draw centroid
vec2d centroid = this->centroid(); vec2d centroid = this->centroid();
draw_circle(cr, centroid, 1); draw_circle(cr, centroid, 1);
// draw speed // 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) { void polygons_draw(cairo_t* cr) {

View File

@ -1,6 +1,7 @@
#ifndef POLYGONS_H_INCLUDED #ifndef POLYGONS_H_INCLUDED
#define POLYGONS_H_INCLUDED #define POLYGONS_H_INCLUDED
#include "color.h"
#include "vec2d.h" #include "vec2d.h"
#include <cmath> #include <cmath>
@ -22,6 +23,7 @@ class polygon {
double mass; double mass;
std::string label; std::string label;
color_t color;
std::vector<vec2d> global_points = points; std::vector<vec2d> global_points = points;
vec2d speed; vec2d speed;
@ -118,6 +120,8 @@ class polygon {
extern polygon* polygons; extern polygon* polygons;
extern uint n_polygons; extern uint n_polygons;
extern bool draw_speed;
extern void polygons_init_state(); extern void polygons_init_state();
extern void polygons_update_state(); extern void polygons_update_state();
extern void polygons_draw(cairo_t* cr); extern void polygons_draw(cairo_t* cr);

View File

@ -2,6 +2,7 @@
#define VEC2D_H_INCLUDED #define VEC2D_H_INCLUDED
#include "cairo.h" #include "cairo.h"
#include "color.h"
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
@ -74,7 +75,7 @@ class vec2d {
return {-y, x}; 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_lenght_ = 10 * vec2d::norm(*this);
double arrow_degrees_ = .5; double arrow_degrees_ = .5;
@ -90,7 +91,7 @@ class vec2d {
double x2 = end.x + head_length * cos(angle + arrow_degrees_); double x2 = end.x + head_length * cos(angle + arrow_degrees_);
double y2 = end.y + head_length * sin(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_move_to(cr, p.x, p.y);
cairo_line_to(cr, end.x, end.y); cairo_line_to(cr, end.x, end.y);