Refactoring from project template
This commit is contained in:
parent
d1e893859f
commit
c22e97dbdf
1 changed files with 0 additions and 0 deletions
276
main.c
Normal file
276
main.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely.
|
||||
*/
|
||||
#include <SDL3/SDL_rect.h>
|
||||
#include <SDL3/SDL_render.h>
|
||||
#include <SDL3/SDL_surface.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
|
||||
#include "SDL_FPSCounter.h"
|
||||
|
||||
#include "submodules/utilitiec/src/QuadTree/QuadTree.h"
|
||||
#include "submodules/utilitiec/src/rand/xoshiro256.h"
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_Renderer *renderer = NULL;
|
||||
static QuadTree tree;
|
||||
static SDL_FPSCounter fps_counter;
|
||||
static scalar view_angle = 0.25 * M_PI;
|
||||
|
||||
typedef struct Particle_s {
|
||||
QuadTreeLeaf position;
|
||||
double velocity;
|
||||
double direction;
|
||||
} Particle;
|
||||
|
||||
static Particle particles[500];
|
||||
|
||||
scalar QuadTreeLeaf_norm(QuadTreeLeaf* vector)
|
||||
{
|
||||
return sqrt(pow(vector->x, 2) + pow(vector->y, 2));
|
||||
}
|
||||
|
||||
scalar Particle_AngleTo(Particle* this, QuadTreeLeaf* other)
|
||||
{
|
||||
QuadTreeLeaf distance_vector = {other->x - this->position.x, other->y - this->position.y};
|
||||
QuadTreeLeaf direction_vector = {cos(this->direction), sin(this->direction)};
|
||||
scalar distance_norm = QuadTreeLeaf_norm(&distance_vector);
|
||||
if (distance_norm == 0) return 0;
|
||||
scalar angle = acos((distance_vector.x * direction_vector.x + distance_vector.y * direction_vector.y) / distance_norm);
|
||||
if (isnan(angle)) return M_PI - 0.01;
|
||||
return angle;
|
||||
}
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_Color color = { 255, 255, 255, SDL_ALPHA_OPAQUE };
|
||||
SDL_Surface *text;
|
||||
|
||||
/* Create the window */
|
||||
if (!SDL_CreateWindowAndRenderer("Swarm Simulation", 600, 600, 0, &window, &renderer)) {
|
||||
SDL_Log("Couldn't create window and renderer: %s\n", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!TTF_Init()) {
|
||||
SDL_Log("Couldn't initialise SDL_ttf: %s\n", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
QuadTree_Create(&tree, 600, 600, NULL);
|
||||
|
||||
Xoshiro256State rand_state = { 0, 10, 10, 10 };
|
||||
|
||||
for (size_t i = 0; i < sizeof(particles) / sizeof(particles[0]); i++) {
|
||||
particles[i].position.x = xoshiro256_next(&rand_state) % 600;
|
||||
particles[i].position.y = xoshiro256_next(&rand_state) % 600;
|
||||
particles[i].velocity = 5;
|
||||
particles[i].direction = 1;
|
||||
QuadTree_Insert(&tree, &particles[i].position);
|
||||
}
|
||||
|
||||
SDL_CreateFPSCounter(&fps_counter, 60);
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
|
||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||||
{
|
||||
if (event->type == SDL_EVENT_KEY_DOWN ||
|
||||
event->type == SDL_EVENT_QUIT) {
|
||||
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
||||
}
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
int QuadTree_DrawTree(void* context, QuadSubTree* tree, QuadTreeDimension dimension)
|
||||
{
|
||||
SDL_FRect render_rect;
|
||||
render_rect.x = dimension.left;
|
||||
render_rect.y = dimension.top;
|
||||
render_rect.h = dimension.bottom - dimension.top;
|
||||
render_rect.w = dimension.right - dimension.left;
|
||||
SDL_RenderRect(renderer, &render_rect);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void Particle_Move(Particle* self)
|
||||
{
|
||||
double frame_rate = SDL_FPSCounterFPS(&fps_counter);
|
||||
if (frame_rate == 0) {
|
||||
frame_rate = 60;
|
||||
}
|
||||
printf("%lu\n", SDL_FPSCounterFPS(&fps_counter));
|
||||
|
||||
Particle copy = *self;
|
||||
|
||||
self->position.x += 1.0/frame_rate * 50 * self->velocity * cos(self->direction);
|
||||
self->position.y += 1.0/frame_rate * 50 * self->velocity * sin(self->direction);
|
||||
|
||||
if (self->position.x < 0) {
|
||||
self->position.x *= -1;
|
||||
self->direction -= 2 * (self->direction - M_PI_2);
|
||||
}
|
||||
if (self->position.y < 0) {
|
||||
self->position.y *= -1;
|
||||
self->direction -= 2 * (self->direction - M_PI);
|
||||
}
|
||||
if (self->position.x > 600) {
|
||||
self->position.x -= self->position.x - 600;
|
||||
self->direction -= 2 * (self->direction - M_PI_2);
|
||||
}
|
||||
if (self->position.y > 600) {
|
||||
self->position.y -= self->position.y - 600;
|
||||
self->direction -= 2 * (self->direction - M_PI);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
self->position.x = self->position.x > 600 ? self->position.x - 600 : self->position.x;
|
||||
self->position.x = self->position.x < 0 ? self->position.x + 600 : self->position.x;
|
||||
self->position.y = self->position.y > 600 ? self->position.y - 600 : self->position.y;
|
||||
self->position.y = self->position.y < 0 ? self->position.y + 600 : self->position.y;
|
||||
*/
|
||||
|
||||
if(isnan(self->position.x) || isnan(self->position.y)) {
|
||||
printf("Before %f, %f, direction %f, velocity %f\n", copy.position.x, copy.position.y, copy.direction, copy.velocity);
|
||||
}
|
||||
}
|
||||
|
||||
struct InteractionContext {
|
||||
int count;
|
||||
double angleSum;
|
||||
QuadTreeLeaf positionSum;
|
||||
Particle* self;
|
||||
};
|
||||
|
||||
void Particle_ApplyInteraction(Particle* self, struct InteractionContext* interaction_context)
|
||||
{
|
||||
self->direction += interaction_context->angleSum;
|
||||
self->direction /= (interaction_context->count + 1);
|
||||
|
||||
QuadTreeLeaf vectorToPositionSum = {
|
||||
.x = interaction_context->positionSum.x / (interaction_context->count + 1),
|
||||
.y = interaction_context->positionSum.y / (interaction_context->count + 1),
|
||||
};
|
||||
|
||||
|
||||
scalar angleToPositionSum = Particle_AngleTo(self, &vectorToPositionSum);
|
||||
|
||||
if(isnan(angleToPositionSum)) {
|
||||
printf("self: %f, %f, direction: %f\n", self->position.x, self->position.y, self->direction);
|
||||
printf("vectorToPosSum: %f, %f\n", vectorToPositionSum.x, vectorToPositionSum.y);
|
||||
}
|
||||
|
||||
self->direction += angleToPositionSum / 2;
|
||||
}
|
||||
|
||||
int InteractionContext_NearbyLeafCallback(void* _context, QuadTreeLeaf* leaf)
|
||||
{
|
||||
struct InteractionContext* interaction_context = (struct InteractionContext*) _context;
|
||||
Particle* particle = (Particle*) leaf;
|
||||
if (particle == interaction_context->self) return EXIT_SUCCESS;
|
||||
scalar angle = Particle_AngleTo(interaction_context->self, &particle->position);
|
||||
if (fabs(angle) <= view_angle) {
|
||||
interaction_context->angleSum += angle;
|
||||
interaction_context->count++;
|
||||
}
|
||||
|
||||
interaction_context->positionSum.x += leaf->x;
|
||||
interaction_context->positionSum.y += leaf->y;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int QuadTreeCallBack_ColorLeaf(void* context, QuadTreeLeaf* leaf)
|
||||
{
|
||||
SDL_FRect render_rect;
|
||||
render_rect.x = leaf->x - 5;
|
||||
render_rect.y = leaf->y - 5;
|
||||
render_rect.h = 10;
|
||||
render_rect.w = 10;
|
||||
SDL_RenderRect(renderer, &render_rect);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* This function runs once per frame, and is the heart of the program. */
|
||||
SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
{
|
||||
|
||||
SDL_FPSCounterTick(&fps_counter);
|
||||
//printf("%lu\n", SDL_FPSCounterFPS(&fps_counter));
|
||||
|
||||
// clear screen
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
|
||||
QuadTree new_tree;
|
||||
QuadTree_Create(&new_tree, 600, 600, tree.allocator);
|
||||
|
||||
QuadTreeLeaf sumPosition = {0, 0};
|
||||
|
||||
struct InteractionContext interactionContext = {0, 0, sumPosition, NULL};
|
||||
|
||||
for (size_t i = 0; i < sizeof(particles) / sizeof(particles[0]); i++) {
|
||||
sumPosition = particles[i].position;
|
||||
interactionContext = (struct InteractionContext) {0, 0, sumPosition, &particles[i]};
|
||||
QuadTree_ForEachLeafInRadius(&tree, InteractionContext_NearbyLeafCallback, &interactionContext, particles[i].position, 50);
|
||||
Particle_ApplyInteraction(&particles[i], &interactionContext);
|
||||
|
||||
Particle_Move(particles + i);
|
||||
|
||||
QuadTree_Insert(&new_tree, &particles[i].position);
|
||||
|
||||
SDL_RenderPoint(renderer, particles[i].position.x, particles[i].position.y);
|
||||
}
|
||||
|
||||
QuadTree_ForEachLeafInRadius(&tree, QuadTreeCallBack_ColorLeaf, &interactionContext, particles[0].position, 50);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
|
||||
|
||||
SDL_FRect render_rect;
|
||||
render_rect.x = particles[0].position.x - 5;
|
||||
render_rect.y = particles[0].position.y - 5;
|
||||
render_rect.h = 10;
|
||||
render_rect.w = 10;
|
||||
SDL_RenderRect(renderer, &render_rect);
|
||||
|
||||
QuadTree_Destroy(&tree);
|
||||
tree = new_tree;
|
||||
QuadTree_ForEachTree(&tree, QuadTree_DrawTree, NULL);
|
||||
|
||||
// swap
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
/* This function runs once at shutdown. */
|
||||
void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
||||
{
|
||||
QuadTree_Destroy(&tree);
|
||||
TTF_Quit();
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue