generated from rpuzonas/raylib-cpp-template
add panning and zooming
This commit is contained in:
parent
dc34800fac
commit
b47d6235fd
@ -64,6 +64,8 @@ struct Visuals {
|
||||
Color boid_color = BLACK;
|
||||
Color bg_color = RAYWHITE;
|
||||
|
||||
Camera2D camera;
|
||||
|
||||
bool show_control_panel = true;
|
||||
|
||||
bool draw_boid_direction = false;
|
||||
|
@ -25,6 +25,8 @@ static World g_world;
|
||||
static Visuals g_visuals;
|
||||
static UI g_ui;
|
||||
|
||||
// TODO: Add controls window
|
||||
|
||||
// TODO: Make boids form specific shapes defined by user, options:
|
||||
// Circles, triangles, by image, text.
|
||||
|
||||
@ -41,7 +43,7 @@ int main() {
|
||||
int screen_height = 720;
|
||||
|
||||
raylib::Window window(screen_width, screen_height, "Boid Playground");
|
||||
window.SetState(FLAG_VSYNC_HINT);
|
||||
window.SetState(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE);
|
||||
|
||||
GuiLoadStyleDefault();
|
||||
|
||||
@ -56,6 +58,7 @@ int main() {
|
||||
g_world.boids.push_back(boid);
|
||||
}
|
||||
g_ui.target_boid_count = g_world.boids.size();
|
||||
visuals_init(&g_world, &g_visuals);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
|
||||
@ -111,6 +114,9 @@ static void profiling_test() {
|
||||
void UpdateDrawFrame() {
|
||||
float dt = GetFrameTime();
|
||||
|
||||
g_world.size.x = GetScreenWidth();
|
||||
g_world.size.y = GetScreenHeight();
|
||||
|
||||
RPROF_START("Update");
|
||||
#ifdef PLATFORM_WEB
|
||||
// If user goes to another tab and comes back, the time that the user was gone needs to be ignored.
|
||||
@ -121,6 +127,7 @@ void UpdateDrawFrame() {
|
||||
#else
|
||||
world_update(&g_world, dt);
|
||||
#endif
|
||||
visuals_update(&g_world, &g_visuals);
|
||||
RPROF_STOP();
|
||||
|
||||
// Draw
|
||||
|
@ -117,6 +117,11 @@ static void world_init(World *world, float width, float height) {
|
||||
world->size = { width, height };
|
||||
}
|
||||
|
||||
static void visuals_init(World *world, Visuals *visuals) {
|
||||
visuals->camera = { 0 };
|
||||
visuals->camera.zoom = 1;
|
||||
}
|
||||
|
||||
static void world_free(World *world) {
|
||||
arena_free(&world->frame_arena);
|
||||
}
|
||||
@ -305,7 +310,7 @@ static void world_compute_local_boids(BoidList *local_boids, World *world, Chunk
|
||||
int boid_count = world->boids.size();
|
||||
MemoryArena *arena = &world->frame_arena;
|
||||
|
||||
boid_pair b2b_cmps[B2B_CAPACITY + SIMD_32B_LANES];
|
||||
boid_pair *b2b_cmps = (boid_pair*)arena_malloc(arena, (B2B_CAPACITY + SIMD_32B_LANES)*sizeof(boid_pair));
|
||||
int b2b_cmps_count = 0;
|
||||
|
||||
RPROF_START("Move chunk data to static arrays");
|
||||
@ -415,6 +420,27 @@ static BoidList* world_compute_local_boids(World *world) {
|
||||
return all_local_boids;
|
||||
}
|
||||
|
||||
static void aggregate_flock_modifiers(World *world, BoidList *flock, Boid *boid, Vector2 *center, Vector2 *heading, Vector2 *separation_force) {
|
||||
*center = { 0, 0 };
|
||||
*heading = { 0, 0 };
|
||||
*separation_force = { 0, 0 };
|
||||
|
||||
uboid_t boid_id;
|
||||
BoidsListNodeIterator it = boid_list_get_iterator(flock);
|
||||
while (boid_list_iterator_next(&it, &boid_id)) {
|
||||
Boid *flock_boid = &world->boids[boid_id];
|
||||
*heading = Vector2Add(*heading, flock_boid->dir);
|
||||
*center = Vector2Add(*center , flock_boid->pos);
|
||||
|
||||
Vector2 pos_diff = Vector2Subtract(boid->pos, flock_boid->pos);
|
||||
float dist_sqr = Vector2LengthSqr(pos_diff);
|
||||
if (dist_sqr <= world->separation_radius * world->separation_radius) {
|
||||
*separation_force = Vector2Add(*separation_force, vector2_div_value(pos_diff, dist_sqr));
|
||||
}
|
||||
}
|
||||
*center = vector2_div_value(*center, flock->count);
|
||||
}
|
||||
|
||||
static void world_update(World *world, float dt) {
|
||||
if (world->freeze) return;
|
||||
|
||||
@ -422,7 +448,7 @@ static void world_update(World *world, float dt) {
|
||||
|
||||
Boid *boids = world->boids.data();
|
||||
int boid_count = world->boids.size();
|
||||
assert(boid_count <= MAX_BOIDS);
|
||||
DEBUG_ASSERT(boid_count <= MAX_BOIDS);
|
||||
|
||||
BoidList *list_of_local_boids = world_compute_local_boids(world);
|
||||
|
||||
@ -438,24 +464,8 @@ static void world_update(World *world, float dt) {
|
||||
BoidList *local_boids = &list_of_local_boids[i];
|
||||
|
||||
if (local_boids->count > 0) {
|
||||
Vector2 separation_force = { 0, 0 };
|
||||
Vector2 flock_center = { 0, 0 };
|
||||
Vector2 flock_heading = { 0, 0 };
|
||||
|
||||
uboid_t local_boid_id;
|
||||
BoidsListNodeIterator it = boid_list_get_iterator(local_boids);
|
||||
while (boid_list_iterator_next(&it, &local_boid_id)) {
|
||||
Boid *local_boid = &boids[local_boid_id];
|
||||
flock_heading = Vector2Add(flock_heading, local_boid->dir);
|
||||
flock_center = Vector2Add(flock_center , local_boid->pos);
|
||||
|
||||
Vector2 pos_diff = Vector2Subtract(boid->pos, local_boid->pos);
|
||||
float dist_sqr = Vector2LengthSqr(pos_diff);
|
||||
if (dist_sqr <= world->separation_radius * world->separation_radius) {
|
||||
separation_force = Vector2Add(separation_force, vector2_div_value(pos_diff, dist_sqr));
|
||||
}
|
||||
}
|
||||
flock_center = vector2_div_value(flock_center, local_boids->count);
|
||||
Vector2 separation_force, flock_center, flock_heading;
|
||||
aggregate_flock_modifiers(world, local_boids, boid, &flock_center, &flock_heading, &separation_force);
|
||||
|
||||
Vector2 alignment_force = Vector2Normalize(flock_heading);
|
||||
acc = Vector2Add(acc, vector2_mul_value(alignment_force, world->alignment_strength));
|
||||
@ -633,11 +643,55 @@ static void draw_boids(World *world, Visuals *visuals) {
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
static void visuals_update(World *world, Visuals *visuals) {
|
||||
Camera2D *camera = &visuals->camera;
|
||||
|
||||
if (IsKeyPressed(KEY_R)) {
|
||||
*camera = { 0 };
|
||||
camera->zoom = 1;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)) {
|
||||
Vector2 delta = GetMouseDelta();
|
||||
delta = Vector2Scale(delta, -1.0f/camera->zoom);
|
||||
|
||||
camera->target = Vector2Add(camera->target, delta);
|
||||
}
|
||||
|
||||
float wheel = GetMouseWheelMove();
|
||||
if (wheel != 0) {
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), *camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera->offset = GetMousePosition();
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera->target = mouseWorldPos;
|
||||
|
||||
// Zoom increment
|
||||
const float zoom_speed = 0.125f;
|
||||
|
||||
camera->zoom = camera->zoom*(1+zoom_speed*wheel);
|
||||
if (camera->zoom < zoom_speed) camera->zoom = zoom_speed;
|
||||
}
|
||||
}
|
||||
|
||||
static void world_draw(World *world, Visuals *visuals) {
|
||||
BeginMode2D(visuals->camera);
|
||||
for (int i = 0; i < world->obstacles.size(); i++) {
|
||||
draw_obstacle(&world->obstacles[i], GRAY);
|
||||
}
|
||||
|
||||
Color border_color = RED;
|
||||
float world_width = world->size.x;
|
||||
float world_height = world->size.y;
|
||||
DrawLine(0, -1, world_width, -1, RED);
|
||||
DrawLine(-1, 0, -1, world_height, RED);
|
||||
DrawLine(0, world_height+1, world_width, world_height+1, RED);
|
||||
DrawLine(world_width+1, 0, world_width+1, world_height, RED);
|
||||
|
||||
if (visuals->draw_view_cone) {
|
||||
Color view_cone_color = Fade(GRAY, 0.4);
|
||||
for (int i = 0; i < world->boids.size(); i++) {
|
||||
@ -673,4 +727,5 @@ static void world_draw(World *world, Visuals *visuals) {
|
||||
DrawLine(boid->pos.x, boid->pos.y, look_pos.x, look_pos.y, RED);
|
||||
}
|
||||
}
|
||||
EndMode2D();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user