Most balls follow each other and become one. 🟣🟡 go their own way.
Balls and their admirers#
Let’s build a graphical simulation with lots of moving balls where they randomly follow each other, because they 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.
Warmup#
Activity 53 (How do we simulate moving shapes?)
The motion is generated by drawing many frames per second. In our code we describe the position of each shape. So if a shape moves horizontally with a velocity of x, then its position in the next frame becomes posx += x. Moreover each shape can have further properties like color and rotation etc.
Come up with at least two different data structures to implement the state of 100 shapes.
What are the trade-offs of these data structures?
Hint
Could arrays or scalar (single value) variables help?
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).Select meaningful types for these properties.
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 5-10s video of your simulation.
Optional:
Create an
unionShapewhich can represent both circles and rectangles (DrawRectangle()). Each function must be modified to cater for this, so above requirement does not apply. Each circle should follow a rectangle
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
// Ball stores state and other properties
// YOUR CODE HERE
Ball balls[BALL_COUNT];
// Initializes a ball with random values
Ball *init_ball_random(Ball *p) {
// Randomly initialize state and properties
// YOUR CODE HERE
// Find a leading ball other than the initialized ball itself.
Ball *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 *draw_ball(Ball *p) {
DrawCircle(p->posx, p->posy, p->radius, p->color);
return p;
}
// Updates the positions of balls according to their velocities
Ball *update_pos(Ball *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 *update_vel_for_following(Ball *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();
}
}