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:
parent
79ac43f05c
commit
082acc4451
5
Makefile
5
Makefile
@ -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
102
color.cc
Normal 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
17
color.h
Normal 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
|
4
main.cc
4
main.cc
@ -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();
|
||||||
|
93
polygons.cc
93
polygons.cc
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
5
vec2d.h
5
vec2d.h
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user