Balls start to follow each other until they become one.
Balls and their admirers#
Let’s build a graphical simulation with lots of moving balls where they randomly follow each other, i.e., like or admire each other.
Because the balls follow each other, at some point they should end up at the same position.
Note
For this problem you need raylib.
Requirements#
A ball has a two-dimensional position (
posxandposy), a velocity (velxandvely), a radius (radius), a color (Color color, whereColoris defined byraylib) and a pointer to another leading ball (follows).Each ball starts at a random position, with a random velocity, random color and a random ball to follow. A ball should not follow itself.
Use the template and only fill the missing parts.
Include a flowchart.
Do not include
rayliblibrary in your repository.Record a max 5-10s video of your simulation.
Template#
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define WIDTH 400
#define HEIGHT 400
#define TITLE "Balls and their admirers"
#define BALL_COUNT 100
#define FPS 60
#define VEL_MAX 5
#define RADIUS_MAX 20
#define RADIUS_MIN 5
Color COLORS[] = {
LIGHTGRAY, GRAY, DARKGRAY, YELLOW, GOLD, ORANGE, PINK,
RED, MAROON, GREEN, LIME, DARKGREEN, SKYBLUE, BLUE,
DARKBLUE, PURPLE, VIOLET, DARKPURPLE, BEIGE, BROWN, DARKBROWN,
};
// Definition of ball_t
// ball_t stores state and other properties
// YOUR CODE HERE
ball_t balls[BALL_COUNT];
// Initializes a ball with random values
ball_t *init_ball_random(ball_t *p) {
// Randomly initialize state and properties
// YOUR CODE HERE
// Find a leading ball other than the initialized ball itself.
ball_t *leader; // Represents the leading ball that this ball will follow
// YOUR CODE HERE
return p;
}
// Initialize all `balls`
void init_balls_random() {
// YOUR CODE HERE
}
ball_t *draw_ball(ball_t *p) {
DrawCircle(p->posx, p->posy, p->radius, p->color);
return p;
}
// Updates the positions of balls according to their velocities
ball_t *update_pos(ball_t *p) {
p->posx = (WIDTH + p->posx + p->velx) %
WIDTH; // `WIDTH +` because C uses truncated division
p->posy = (HEIGHT + p->posy + p->vely) % HEIGHT;
return p;
}
// Updates the velocity of a ball so that it follows the leading ball
ball_t *update_vel_for_following(ball_t *p) {
int errx = p->follows->posx - p->posx;
int erry = p->follows->posy - p->posy;
p->velx = errx > 0 ? 1 : -1;
p->vely = erry > 0 ? 1 : -1;
return p;
}
// Update all elements
void update_elements() {
for (size_t i = 0; i < _Countof balls; ++i) {
draw_ball(update_pos(update_vel_for_following(&balls[i])));
}
}
int main() {
InitWindow(WIDTH, HEIGHT, TITLE);
SetTargetFPS(FPS);
init_balls_random();
while (!WindowShouldClose()) // Detect window close button or ESC key
{
BeginDrawing();
update_elements();
ClearBackground(RAYWHITE);
EndDrawing();
}
}