diff --git a/balls.cc b/balls.cc index fc9d25b..a514d1b 100644 --- a/balls.cc +++ b/balls.cc @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include #include "game.h" #include "balls.h" @@ -15,10 +15,10 @@ unsigned int v_min = 0; unsigned int v_angle_min = 0; unsigned int v_angle_max = 100; -struct ball * balls = 0; +ball * balls = nullptr; unsigned int n_balls = 50; -static void random_velocity(struct ball * p) { +static void random_velocity(ball * p) { double r2; do { p->v_x = v_min + rand() % (v_max + 1 - v_min); @@ -47,7 +47,7 @@ void balls_init_state () { } } -void ball_update_state (struct ball * p) { +void ball_update_state (ball * p) { struct gravity_vector g; gravity_get_vector (&g, p); @@ -87,7 +87,7 @@ void ball_update_state (struct ball * p) { p->angle += 2*M_PI; } -void ball_elastic_collision (struct ball * p, struct ball * q) { +void ball_elastic_collision (ball * p, ball * q) { double dx = q->x - p->x; double dy = q->y - p->y; double d2 = dx*dx + dy*dy; @@ -112,7 +112,7 @@ void ball_elastic_collision (struct ball * p, struct ball * q) { } } -void ball_reposition (struct ball * b) { +void ball_reposition (ball * b) { if (b->x < b->radius) b->x = b->radius; else if (b->x + b->radius > width) @@ -128,38 +128,35 @@ int face_rotation = 0; static const double linear_rotation_unit = 2.0; -static unsigned int faces_count; -static struct ball_face ** faces; +static std::vector faces; -struct ball_face { +class ball_face { +public: + ball_face (unsigned int radius, cairo_surface_t * face, int rotation); + ~ball_face (); + cairo_surface_t * get_surface (double angle) const; +private: unsigned int rotations; - cairo_surface_t ** c_faces; + std::vector c_faces; }; static double random_color_component() { return 1.0*(rand() % 200 + 56)/255; }; -static struct ball_face * new_ball_face(unsigned int radius, cairo_surface_t * face, int rotation) { - struct ball_face * f = (struct ball_face *)malloc(sizeof(struct ball_face)); - if (!f) - return 0; +ball_face::ball_face (unsigned int radius, cairo_surface_t * face, int rotation) { if (face && rotation) { - f->rotations = 2*M_PI * radius / linear_rotation_unit; + rotations = 2*M_PI * radius / linear_rotation_unit; } else { - f->rotations = 1; + rotations = 1; } - f->c_faces = (cairo_surface_t **)malloc(sizeof(cairo_surface_t *)*f->rotations); - if (!f->c_faces) { - free(f); - return 0; - } - for (unsigned int i = 0; i < f->rotations; ++i) { - f->c_faces[i] = gdk_window_create_similar_surface(gtk_widget_get_window(canvas), - CAIRO_CONTENT_COLOR_ALPHA, - 2*radius, 2*radius); - assert(f->c_faces[i]); - cairo_t * ball_cr = cairo_create(f->c_faces[i]); + c_faces.resize(rotations); + for (unsigned int i = 0; i < rotations; ++i) { + c_faces[i] = gdk_window_create_similar_surface(gtk_widget_get_window(canvas), + CAIRO_CONTENT_COLOR_ALPHA, + 2*radius, 2*radius); + assert(c_faces[i]); + cairo_t * ball_cr = cairo_create(c_faces[i]); cairo_translate(ball_cr, radius, radius); cairo_arc(ball_cr, 0.0, 0.0, radius, 0, 2 * M_PI); cairo_clip(ball_cr); @@ -167,7 +164,7 @@ static struct ball_face * new_ball_face(unsigned int radius, cairo_surface_t * f if (face) { int face_x_offset = cairo_image_surface_get_width (face) / 2; int face_y_offset = cairo_image_surface_get_height (face) / 2; - cairo_rotate(ball_cr, i*2*M_PI/f->rotations); + cairo_rotate(ball_cr, i*2*M_PI/rotations); cairo_scale (ball_cr, 1.0 * radius / face_x_offset, 1.0 * radius / face_y_offset); cairo_set_source_surface(ball_cr, face, -face_x_offset, -face_y_offset); cairo_paint(ball_cr); @@ -185,10 +182,27 @@ static struct ball_face * new_ball_face(unsigned int radius, cairo_surface_t * f cairo_fill (ball_cr); cairo_pattern_destroy (pat); } - cairo_surface_flush(f->c_faces[i]); + cairo_surface_flush(c_faces[i]); cairo_destroy(ball_cr); } - return f; +} + +ball_face::~ball_face() { + for (auto f : c_faces) + cairo_surface_destroy(f); +} + +cairo_surface_t * ball_face::get_surface (double angle) const { + unsigned int face_id; + if (rotations == 1) + face_id = 0; + else { + face_id = rotations*angle/(2*M_PI); + assert(face_id < rotations); + if (face_id >= rotations) + face_id %= rotations; + } + return c_faces[face_id]; } static void balls_init_faces () { @@ -203,69 +217,48 @@ static void balls_init_faces () { } } if (face_surface) { - faces_count = radius_max + 1 - radius_min; - faces = (struct ball_face **)malloc(sizeof(struct ball_face *)*faces_count); - for (unsigned int i = 0; i < faces_count; ++i) - faces[i] = 0; - for(struct ball * b = balls; b != balls + n_balls; ++b) { + faces.assign(radius_max + 1 - radius_min, nullptr); + for(ball * b = balls; b != balls + n_balls; ++b) { unsigned int r_idx = b->radius - radius_min; - if (!faces[r_idx]) - faces[r_idx] = new_ball_face(b->radius, face_surface, face_rotation); + if (faces[r_idx] == nullptr) + faces[r_idx] = new ball_face (b->radius, face_surface, face_rotation); b->face = faces[r_idx]; } cairo_surface_destroy (face_surface); } else { - faces_count = n_balls; - faces = (struct ball_face **)malloc(sizeof(struct ball_face *)*faces_count); + faces.resize(n_balls); for (unsigned int i = 0; i < n_balls; ++i) - balls[i].face = faces[i] = new_ball_face(balls[i].radius, 0, face_rotation); + balls[i].face = faces[i] = new ball_face (balls[i].radius, 0, face_rotation); } } +void ball::draw (cairo_t * cr) const { + cairo_save (cr); + cairo_translate (cr, x - radius, y - radius); + cairo_set_source_surface(cr, face->get_surface (angle), 0, 0); + cairo_paint(cr); + cairo_restore(cr); +} + void balls_draw (cairo_t * cr) { - for (const struct ball * b = balls; b != balls + n_balls; ++b) { - cairo_save(cr); - cairo_translate(cr, b->x - b->radius, b->y - b->radius); - unsigned int face_id; - if (b->face->rotations == 1) - face_id = 0; - else { - face_id = b->face->rotations*b->angle/(2*M_PI); - assert(face_id < b->face->rotations); - if (face_id >= b->face->rotations) - face_id %= b->face->rotations; - } - cairo_set_source_surface(cr, b->face->c_faces[face_id], 0, 0); - cairo_paint(cr); - cairo_restore(cr); - } + for (const ball * b = balls; b != balls + n_balls; ++b) + b->draw(cr); } static void balls_destroy_faces () { - if (!faces) - return; - for (unsigned int i = 0; i < faces_count; ++i) { - if (faces[i]) { - if (faces[i]->c_faces) { - for (unsigned int j = 0; j < faces[i]->rotations; ++j) - cairo_surface_destroy(faces[i]->c_faces[j]); - free(faces[i]->c_faces); - } - free(faces[i]); - } - } - free (faces); - faces = 0; - faces_count = 0; + for (ball_face * f : faces) + if (f) + delete (f); + faces.clear(); } void balls_destroy () { balls_destroy_faces (); - free (balls); + delete [] (balls); } void balls_init () { - balls = (struct ball *)malloc(sizeof(struct ball)*n_balls); + balls = new ball[n_balls]; assert(balls); balls_init_state (); balls_init_faces (); diff --git a/balls.h b/balls.h index 880f3d3..a8015b0 100644 --- a/balls.h +++ b/balls.h @@ -3,9 +3,10 @@ #include -struct ball_face; +class ball_face; -struct ball { +class ball { +public: double x; double y; unsigned int radius; @@ -16,10 +17,12 @@ struct ball { double angle; double v_angle; - struct ball_face * face; + ball_face * face; + + void draw (cairo_t * cr) const; }; -extern struct ball * balls; +extern ball * balls; extern unsigned int n_balls; extern unsigned int radius_min; @@ -36,9 +39,9 @@ extern int face_rotation; extern void balls_init (); extern void balls_destroy (); -extern void ball_update_state (struct ball * p); -extern void ball_elastic_collision (struct ball * p, struct ball * q); -extern void ball_reposition (struct ball * b); +extern void ball_update_state (ball * p); +extern void ball_elastic_collision (ball * p, ball * q); +extern void ball_reposition (ball * b); extern void balls_draw (cairo_t * cr); #endif diff --git a/c_index.h b/c_index.h index fb979f9..1d5087d 100644 --- a/c_index.h +++ b/c_index.h @@ -4,7 +4,7 @@ #include "balls.h" void c_index_build(); -void c_index_check_collisions(void (*collision)(struct ball *, struct ball *)); +void c_index_check_collisions(void (*collision)(ball *, ball *)); int c_index_init(); void c_index_destroy(); diff --git a/gravity.h b/gravity.h index 4620a9e..17a7964 100644 --- a/gravity.h +++ b/gravity.h @@ -11,12 +11,12 @@ struct gravity_vector { extern void gravity_constant_field (double x, double y); extern void gravity_newton_field (double r, double g); -extern void gravity_get_vector (struct gravity_vector * v, const struct ball * b); +extern void gravity_get_vector (gravity_vector * v, const ball * b); extern void gravity_draw (cairo_t * cr); extern void gravity_change (double dx, double dy); extern void gravity_show (); -extern void gravity_collisions (struct ball * begin, struct ball * end); +extern void gravity_collisions (ball * begin, ball * end); #endif diff --git a/spaceship.h b/spaceship.h index 91f6796..556fe98 100644 --- a/spaceship.h +++ b/spaceship.h @@ -1,7 +1,7 @@ #ifndef SPACESHIP_H_INCLUDED #define SPACESHIP_H_INCLUDED -extern struct ball spaceship; +extern ball spaceship; extern void spaceship_init_state (); extern void spaceship_update_state ();