commit 2e9bfe3bdd3e94ae939e8f51bc0d5075278ac3e7
parent 6941f174461494903945cd66df2485c5d914415d
Author: amin <dev@aminmesbah.com>
Date: Tue, 25 Apr 2017 05:45:12 +0000
Switch to C.
I was basically using C syntax anyway, and I'm more interested in
learning C than C++. Also, the Makefile is fancy now!
FossilOrigin-Name: 9bb193a9441f692eb32c02d03e36dcbfadf2d244f7db11cb9830ce669850b127
Diffstat:
M | .gitignore | | | 3 | ++- |
M | Makefile | | | 41 | +++++++++++++++++++++++++++++++++++++---- |
M | barnes_hut.h | | | 20 | ++++++++++---------- |
A | main.c | | | 368 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | main.cpp | | | 363 | ------------------------------------------------------------------------------- |
M | star.h | | | 14 | +++++++++----- |
6 files changed, 426 insertions(+), 383 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1,3 @@
-star-garden
*.swp
+debug/*
+release/*
diff --git a/Makefile b/Makefile
@@ -1,7 +1,40 @@
-build:
- g++ -std=c++11 -Wall -Wextra -g main.cpp -o star-garden `sdl2-config --cflags --libs`
+CC = gcc
+CFLAGS = -std=c99 -Wall -Wextra -Wpedantic -Wshadow
+LDFLAGS = $(SDL_LDFLAGS) -lm
+
+SDL_CFLAGS := $(shell sdl2-config --cflags)
+SDL_LDFLAGS := $(shell sdl2-config --libs)
+
+override CFLAGS += $(SDL_CFLAGS)
+
+SRC = main.c
+EXE = star-garden
+
+DBGDIR = debug
+DBGEXE = $(DBGDIR)/$(EXE)
+DBGCFLAGS = -g -Og -Werror
+
+RELDIR = release
+RELEXE = $(RELDIR)/$(EXE)
+RELCFLAGS = -O2 -Os
+
+.PHONY: all clean debug prep release run test
+
+all: debug
+
+clean:
+ rm -f $(RELEXE) $(DBGEXE)
+
+debug: prep
+ $(CC) $(CFLAGS) $(DBGCFLAGS) $(SRC) -o $(DBGEXE) $(LDFLAGS)
+
+prep:
+ @mkdir -p $(DBGDIR) $(RELDIR)
+
+release: prep
+ $(CC) $(CFLAGS) $(RELCFLAGS) $(SRC) -o $(RELEXE) $(LDFLAGS)
run:
- ./star-garden
+ ./$(DBGEXE)
-test: build run
+test: debug run
diff --git a/barnes_hut.h b/barnes_hut.h
@@ -19,14 +19,14 @@ struct Cell
struct QuadTreeNode
{
- Cell *cell;
- QuadTreeNode *children[4];
+ struct Cell *cell;
+ struct QuadTreeNode *children[4];
};
-Cell* cell_init(float center_x, float center_y, float distance_x, float distance_y)
+struct Cell* cell_init(float center_x, float center_y, float distance_x, float distance_y)
{
- Cell *cell = (Cell*)malloc(sizeof(Cell));
+ struct Cell *cell = (struct Cell*)malloc(sizeof(struct Cell));
if (cell)
{
cell->center_x = center_x;
@@ -37,7 +37,7 @@ Cell* cell_init(float center_x, float center_y, float distance_x, float distance
return cell;
}
-int cell_count_stars_contained(Cell *c, Star stars[], int num_stars)
+int cell_count_stars_contained(struct Cell *c, struct Star stars[], int num_stars)
{
int count = 0;
for (int i = 0; i < num_stars; ++i)
@@ -53,21 +53,21 @@ int cell_count_stars_contained(Cell *c, Star stars[], int num_stars)
return count;
}
-QuadTreeNode* quad_tree_node_init(float center_x, float center_y, float distance_x, float distance_y)
+struct QuadTreeNode* quad_tree_node_init(float center_x, float center_y, float distance_x, float distance_y)
{
- QuadTreeNode *node = (QuadTreeNode*)malloc(sizeof(QuadTreeNode));
+ struct QuadTreeNode *node = (struct QuadTreeNode*)malloc(sizeof(struct QuadTreeNode));
if (node)
{
node->cell = cell_init(center_x, center_y, distance_x, distance_y);
for (int i = 0; i < 4; ++i)
{
- node->children[i] = nullptr;
+ node->children[i] = 0;
}
}
return node;
}
-void quad_tree_node_free(QuadTreeNode *node)
+void quad_tree_node_free(struct QuadTreeNode *node)
{
if (node)
{
@@ -83,7 +83,7 @@ void quad_tree_node_free(QuadTreeNode *node)
}
}
-void quad_tree_node_subdivide(QuadTreeNode *node, Star stars[], int num_stars)
+void quad_tree_node_subdivide(struct QuadTreeNode *node, struct Star stars[], int num_stars)
{
if (cell_count_stars_contained(node->cell, stars, num_stars) > MAX_STARS_PER_CELL)
{
diff --git a/main.c b/main.c
@@ -0,0 +1,368 @@
+#include <math.h>
+#include <inttypes.h>
+#include <SDL.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include "star.h"
+#include "barnes_hut.h"
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846264338327950288)
+#endif
+
+//#define TRAILS
+//#define FULLSCREEN
+
+#define TITLE "Stars"
+#define SCREEN_WIDTH 640
+#define SCREEN_HEIGHT 480
+#define BYTES_PER_PIXEL 4
+#define NUM_STARS 100
+#define DRAG 1
+
+#define SECOND 1000.0f
+#define FPS 60
+#define MS_PER_FRAME (SECOND / FPS)
+#define UPDATES_PER_SECOND 120
+#define MS_PER_UPDATE (SECOND / UPDATES_PER_SECOND)
+
+#define COLOR_WHITE 0xFFFFFF
+#define COLOR_BLACK 0x000000
+#define COLOR_SOL_BG 0x002B36
+#define COLOR_YELLOW 0xB58900
+#define COLOR_ORANGE 0xCB4B16
+#define COLOR_RED 0xDC322F
+#define COLOR_MAGENTA 0xD33682
+#define COLOR_VIOLET 0x6C71C4
+#define COLOR_BLUE 0x268bD2
+#define COLOR_CYAN 0x2AA198
+#define COLOR_GREEN 0x859900
+#define COLOR_BACKGROUND COLOR_BLACK
+
+typedef enum color_t
+{
+ YELLOW,
+ ORANGE,
+ RED,
+ MAGENTA,
+ VIOLET,
+ BLUE,
+ CYAN,
+ GREEN,
+ NUM_COLORS,
+} color_t;
+
+struct SDLOffscreenBuffer
+{
+ // NOTE(amin): pixels are always 32-bits wide. Memory order: BB GG RR XX.
+ SDL_Texture *texture;
+ void *memory;
+ unsigned int width;
+ unsigned int height;
+ unsigned int pitch;
+};
+
+struct SDLWindowDimension
+{
+ int width;
+ int height;
+};
+
+
+static struct SDLOffscreenBuffer global_back_buffer;
+
+
+struct SDLWindowDimension sdl_get_window_dimension(SDL_Window *window)
+{
+ struct SDLWindowDimension result;
+ SDL_GetWindowSize(window, &result.width, &result.height);
+ return(result);
+}
+
+
+void sdl_resize_texture(struct SDLOffscreenBuffer *buffer, SDL_Renderer *renderer, int width, int height)
+{
+ if (buffer->memory)
+ {
+ free(buffer->memory);
+ }
+
+ if (buffer->texture)
+ {
+ SDL_DestroyTexture(buffer->texture);
+ }
+
+ buffer->texture = SDL_CreateTexture(
+ renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ width, height);
+
+ buffer->width = width;
+ buffer->height = height;
+ buffer->pitch = width * BYTES_PER_PIXEL;
+
+ buffer->memory = malloc(width * height * BYTES_PER_PIXEL);
+}
+
+
+void sdl_update_window(SDL_Renderer *renderer, struct SDLOffscreenBuffer buffer)
+{
+ if (SDL_UpdateTexture(buffer.texture, 0, buffer.memory, buffer.pitch))
+ {
+ // TODO(amin): Handle this error
+ }
+
+ SDL_RenderCopy(renderer, buffer.texture, 0, 0);
+ SDL_RenderPresent(renderer);
+}
+
+
+bool handle_event(SDL_Event *event)
+{
+ bool should_quit = false;
+
+ switch(event->type)
+ {
+ case SDL_QUIT:
+ {
+ printf("SDL_QUIT\n");
+ should_quit = true;
+ } break;
+
+ case SDL_WINDOWEVENT:
+ {
+ switch(event->window.event)
+ {
+ case SDL_WINDOWEVENT_SIZE_CHANGED:
+ {
+ SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
+ SDL_Renderer *renderer = SDL_GetRenderer(window);
+ printf("SDL_WINDOWEVENT_SIZE_CHANGED (%d, %d)\n", event->window.data1, event->window.data2);
+ sdl_resize_texture(&global_back_buffer, renderer, event->window.data1, event->window.data2);
+ } break;
+
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ {
+ printf("SDL_WINDOWEVENT_FOCUS_GAINED\n");
+ } break;
+
+ case SDL_WINDOWEVENT_EXPOSED:
+ {
+ SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
+ SDL_Renderer *renderer = SDL_GetRenderer(window);
+ sdl_update_window(renderer, global_back_buffer);
+ } break;
+ }
+ } break;
+ }
+ return(should_quit);
+}
+
+
+// TODO: change buffer to a pointer
+void set_pixel(struct SDLOffscreenBuffer buffer, uint32_t x, uint32_t y, uint32_t color)
+{
+ /* Origin is (0, 0) on the upper left.
+ * To go one pixel right, increment by 32 bits.
+ * To go one pixel down, increment by (buffer.width * 32) bits.
+ */
+ if (x < buffer.width && y < buffer.height)
+ {
+ uint8_t *pixel_pos = (uint8_t *)buffer.memory;
+ pixel_pos += ((BYTES_PER_PIXEL*x) + (buffer.pitch * y));
+ uint32_t *pixel = (uint32_t *)pixel_pos;
+ *pixel = color;
+ }
+}
+
+
+// TODO: change buffer to a pointer
+void clear_screen(struct SDLOffscreenBuffer buffer, uint32_t pixel_value)
+{
+ // NOTE(amin): Memset is faster than nested for loops, but can only set
+ // pixels to single byte values
+ memset(buffer.memory, pixel_value, buffer.height * buffer.width * BYTES_PER_PIXEL);
+}
+
+
+void update(struct Star stars[], int num_stars, struct QuadTreeNode *cells_root)
+{
+ for (int i = 0; i < num_stars; ++i)
+ {
+ for (int j = i + 1; j < num_stars; ++j)
+ {
+ star_attract(&stars[i], &stars[j]);
+ }
+ stars[i].x += sinf(stars[i].angle) * stars[i].speed;
+ stars[i].y -= cosf(stars[i].angle) * stars[i].speed;
+ //printf("%d: (%f, %f)\n", i, stars[i].x, stars[i].y);
+
+ stars[i].speed *= DRAG;
+ //printf("%f, %f\n", stars[i].x, stars[i].y);
+ }
+
+ int center_x = global_back_buffer.width / 2;
+ int center_y = global_back_buffer.height / 2;
+ int dist_x = global_back_buffer.width / 2;
+ int dist_y = global_back_buffer.height / 2;
+
+ quad_tree_node_free(cells_root);
+ cells_root = quad_tree_node_init(center_x, center_y, dist_x, dist_y);
+ quad_tree_node_subdivide(cells_root, stars, num_stars);
+}
+
+// TODO: pass a pointer to buffer?
+void draw_grid(struct SDLOffscreenBuffer buffer, struct QuadTreeNode *node, uint32_t color)
+{
+ if (node)
+ {
+ for (int i = 0; i < 4; ++i)
+ {
+ if (node->children[i])
+ {
+ for (
+ int x = (node->cell->center_x - node->cell->distance_x);
+ x <= (node->cell->center_x + node->cell->distance_x);
+ ++x)
+ {
+ set_pixel(buffer, x, node->cell->center_y, color);
+ }
+
+ for (
+ int y = (node->cell->center_y - node->cell->distance_y);
+ y <= (node->cell->center_y + node->cell->distance_y);
+ ++y)
+ {
+ set_pixel(buffer, node->cell->center_x, y, color);
+ }
+ draw_grid(buffer, node->children[i], color);
+ }
+ }
+ }
+}
+
+void render(struct SDLOffscreenBuffer buffer, float dt, struct Star stars[], int num_stars, struct QuadTreeNode *cells_root)
+{
+ //printf("%f\n", dt);
+ for (int i = 0; i < num_stars; ++i)
+ {
+ set_pixel(
+ buffer,
+ stars[i].x + (sinf(stars[i].angle) * stars[i].speed) * dt,
+ stars[i].y - (cosf(stars[i].angle) * stars[i].speed) * dt,
+ stars[i].color);
+ }
+
+ draw_grid(buffer, cells_root, COLOR_GREEN);
+}
+
+
+int main(void)
+{
+ if (SDL_Init(SDL_INIT_VIDEO))
+ {
+ // TODO(amin): log SDL_Init error
+ }
+
+ SDL_Window *window = SDL_CreateWindow(
+ TITLE,
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ SCREEN_WIDTH,
+ SCREEN_HEIGHT,
+ SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+
+#ifdef FULLSCREEN
+ SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+#endif
+
+ if (window)
+ {
+ SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
+
+ if (renderer)
+ {
+ struct SDLWindowDimension dimension = sdl_get_window_dimension(window);
+ sdl_resize_texture(&global_back_buffer, renderer, dimension.width, dimension.height);
+
+ bool running = true;
+ srand((uint32_t)time(NULL));
+
+ uint64_t lag = 0;
+ uint64_t previous_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency();
+ struct Star stars[NUM_STARS];
+ for (int i = 0; i < NUM_STARS; ++i)
+ {
+ stars[i].x = rand() % dimension.width;
+ stars[i].y = rand() % dimension.height;
+ stars[i].angle = ((float)rand()/(float)(RAND_MAX)) * 2 * M_PI;
+ stars[i].speed = 0;
+ stars[i].mass = 5;
+ stars[i].size = star_calc_size(stars[i].mass);
+ stars[i].color = COLOR_WHITE;
+ //printf("%f, %f, %f\n", stars[i].angle, stars[i].speed, stars[i].mass);
+ }
+
+ struct QuadTreeNode *cells_root = quad_tree_node_init(
+ global_back_buffer.width / 2,
+ global_back_buffer.height / 2,
+ global_back_buffer.width / 2,
+ global_back_buffer.height / 2);
+
+ while (running)
+ {
+ uint64_t current_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency();
+ uint64_t elapsed_ms = current_ms - previous_ms;
+ previous_ms = current_ms;
+ lag += elapsed_ms;
+ //printf("%" PRIu64 ", %" PRIu64 ", %f\n", elapsed_ms, lag, MS_PER_UPDATE);
+
+ SDL_Event event;
+
+ while (SDL_PollEvent(&event))
+ {
+ running = !handle_event(&event);
+ }
+
+ SDL_PumpEvents();
+
+ dimension = sdl_get_window_dimension(window);
+
+ while (lag >= MS_PER_UPDATE)
+ {
+ update(stars, NUM_STARS, cells_root);
+ //printf("\t%" PRIu64 ", %f\n", lag, MS_PER_UPDATE);
+ lag -= MS_PER_UPDATE;
+ }
+#ifndef TRAILS
+ clear_screen(global_back_buffer, COLOR_BACKGROUND);
+#endif
+ render(global_back_buffer, lag/SECOND, stars, NUM_STARS, cells_root);
+ sdl_update_window(renderer, global_back_buffer);
+ if (elapsed_ms <= MS_PER_FRAME)
+ {
+ SDL_Delay(MS_PER_FRAME - elapsed_ms);
+ }
+ }
+ }
+ else
+ {
+ // TODO(amin): log SDL_Renderer error
+ }
+ }
+ else
+ {
+ // TODO(amin): log SDL_Window error
+ }
+
+ SDL_Quit();
+ return(0);
+}
diff --git a/main.cpp b/main.cpp
@@ -1,363 +0,0 @@
-#include <cmath>
-#include <inttypes.h>
-#include <SDL.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-#include "star.h"
-#include "barnes_hut.h"
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-//#define TRAILS
-#define FULLSCREEN
-
-#define TITLE "Stars"
-#define SCREEN_WIDTH 640
-#define SCREEN_HEIGHT 480
-#define BYTES_PER_PIXEL 4
-#define NUM_STARS 100
-#define DRAG 1
-
-#define SECOND 1000.0f
-#define FPS 60
-#define MS_PER_FRAME (SECOND / FPS)
-#define UPDATES_PER_SECOND 120
-#define MS_PER_UPDATE (SECOND / UPDATES_PER_SECOND)
-
-#define COLOR_WHITE 0xFFFFFF
-#define COLOR_BLACK 0x000000
-#define COLOR_SOL_BG 0x002B36
-#define COLOR_YELLOW 0xB58900
-#define COLOR_ORANGE 0xCB4B16
-#define COLOR_RED 0xDC322F
-#define COLOR_MAGENTA 0xD33682
-#define COLOR_VIOLET 0x6C71C4
-#define COLOR_BLUE 0x268bD2
-#define COLOR_CYAN 0x2AA198
-#define COLOR_GREEN 0x859900
-#define COLOR_BACKGROUND COLOR_BLACK
-
-enum color_t
-{
- YELLOW,
- ORANGE,
- RED,
- MAGENTA,
- VIOLET,
- BLUE,
- CYAN,
- GREEN,
- NUM_COLORS,
-};
-
-struct SDLOffscreenBuffer
-{
- // NOTE(amin): pixels are always 32-bits wide. Memory order: BB GG RR XX.
- SDL_Texture *texture;
- void *memory;
- int width;
- int height;
- int pitch;
-};
-
-struct SDLWindowDimension
-{
- int width;
- int height;
-};
-
-
-static SDLOffscreenBuffer global_back_buffer;
-
-
-SDLWindowDimension sdl_get_window_dimension(SDL_Window *window)
-{
- SDLWindowDimension result;
- SDL_GetWindowSize(window, &result.width, &result.height);
- return(result);
-}
-
-
-void sdl_resize_texture(SDLOffscreenBuffer *buffer, SDL_Renderer *renderer, int width, int height)
-{
- if (buffer->memory)
- {
- free(buffer->memory);
- }
-
- if (buffer->texture)
- {
- SDL_DestroyTexture(buffer->texture);
- }
-
- buffer->texture = SDL_CreateTexture(
- renderer,
- SDL_PIXELFORMAT_ARGB8888,
- SDL_TEXTUREACCESS_STREAMING,
- width, height);
-
- buffer->width = width;
- buffer->height = height;
- buffer->pitch = width * BYTES_PER_PIXEL;
-
- buffer->memory = malloc(width * height * BYTES_PER_PIXEL);
-}
-
-
-void sdl_update_window(SDL_Window *window, SDL_Renderer *renderer, SDLOffscreenBuffer buffer)
-{
- if (SDL_UpdateTexture(buffer.texture, 0, buffer.memory, buffer.pitch))
- {
- // TODO(amin): Handle this error
- }
-
- SDL_RenderCopy(renderer, buffer.texture, 0, 0);
- SDL_RenderPresent(renderer);
-}
-
-
-bool handle_event(SDL_Event *event)
-{
- bool should_quit = false;
-
- switch(event->type)
- {
- case SDL_QUIT:
- {
- printf("SDL_QUIT\n");
- should_quit = true;
- } break;
-
- case SDL_WINDOWEVENT:
- {
- switch(event->window.event)
- {
- case SDL_WINDOWEVENT_SIZE_CHANGED:
- {
- SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
- SDL_Renderer *renderer = SDL_GetRenderer(window);
- printf("SDL_WINDOWEVENT_SIZE_CHANGED (%d, %d)\n", event->window.data1, event->window.data2);
- sdl_resize_texture(&global_back_buffer, renderer, event->window.data1, event->window.data2);
- } break;
-
- case SDL_WINDOWEVENT_FOCUS_GAINED:
- {
- printf("SDL_WINDOWEVENT_FOCUS_GAINED\n");
- } break;
-
- case SDL_WINDOWEVENT_EXPOSED:
- {
- SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
- SDL_Renderer *renderer = SDL_GetRenderer(window);
- sdl_update_window(window, renderer, global_back_buffer);
- } break;
- }
- } break;
- }
- return(should_quit);
-}
-
-
-// TODO: change buffer to a pointer
-void set_pixel(SDLOffscreenBuffer buffer, uint32_t x, uint32_t y, uint32_t color)
-{
- /* Origin is (0, 0) on the upper left.
- * To go one pixel right, increment by 32 bits.
- * To go one pixel down, increment by (buffer.width * 32) bits.
- */
- if (x < buffer.width && y < buffer.height)
- {
- uint8_t *pixel_pos = (uint8_t *)buffer.memory;
- pixel_pos += ((BYTES_PER_PIXEL*x) + (buffer.pitch * y));
- uint32_t *pixel = (uint32_t *)pixel_pos;
- *pixel = color;
- }
-}
-
-
-// TODO: change buffer to a pointer
-void clear_screen(SDLOffscreenBuffer buffer, uint32_t pixel_value)
-{
- // NOTE(amin): Memset is faster than nested for loops, but can only set
- // pixels to single byte values
- memset(buffer.memory, pixel_value, buffer.height * buffer.width * BYTES_PER_PIXEL);
-}
-
-
-void update(Star stars[], int num_stars, QuadTreeNode *cells_root, SDLWindowDimension* dimension)
-{
- for (int i = 0; i < num_stars; ++i)
- {
- for (int j = i + 1; j < num_stars; ++j)
- {
- star_attract(&stars[i], &stars[j]);
- }
- stars[i].x += sinf(stars[i].angle) * stars[i].speed;
- stars[i].y -= cosf(stars[i].angle) * stars[i].speed;
- //printf("%d: (%f, %f)\n", i, stars[i].x, stars[i].y);
-
- stars[i].speed *= DRAG;
- //printf("%f, %f\n", stars[i].x, stars[i].y);
- }
-
- int center_x = global_back_buffer.width / 2;
- int center_y = global_back_buffer.height / 2;
- int dist_x = global_back_buffer.width / 2;
- int dist_y = global_back_buffer.height / 2;
-
- quad_tree_node_free(cells_root);
- cells_root = quad_tree_node_init(center_x, center_y, dist_x, dist_y);
- quad_tree_node_subdivide(cells_root, stars, num_stars);
-}
-
-// TODO: pass a pointer to buffer?
-void draw_grid(SDLOffscreenBuffer buffer, QuadTreeNode *node, uint32_t color)
-{
- if (node)
- {
- for (int i = 0; i < 4; ++i)
- {
- if (node->children[i])
- {
- for (
- int x = (node->cell->center_x - node->cell->distance_x);
- x <= (node->cell->center_x + node->cell->distance_x);
- ++x)
- {
- set_pixel(buffer, x, node->cell->center_y, color);
- }
-
- for (
- int y = (node->cell->center_y - node->cell->distance_y);
- y <= (node->cell->center_y + node->cell->distance_y);
- ++y)
- {
- set_pixel(buffer, node->cell->center_x, y, color);
- }
- draw_grid(buffer, node->children[i], color);
- }
- }
- }
-}
-
-void render(SDLOffscreenBuffer buffer, float dt, Star stars[], int num_stars, QuadTreeNode *cells_root)
-{
- //printf("%f\n", dt);
- for (int i = 0; i < num_stars; ++i)
- {
- set_pixel(
- buffer,
- stars[i].x + (sinf(stars[i].angle) * stars[i].speed) * dt,
- stars[i].y - (cosf(stars[i].angle) * stars[i].speed) * dt,
- stars[i].color);
- }
-
- draw_grid(buffer, cells_root, COLOR_GREEN);
-}
-
-
-int main(int argc, char **argv)
-{
- if (SDL_Init(SDL_INIT_VIDEO))
- {
- // TODO(amin): log SDL_Init error
- }
-
- SDL_Window *window = SDL_CreateWindow(
- TITLE,
- SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- SCREEN_WIDTH,
- SCREEN_HEIGHT,
- SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
-
-#ifdef FULLSCREEN
- SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
-#endif
-
- if (window)
- {
- SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
-
- if (renderer)
- {
- SDLWindowDimension dimension = sdl_get_window_dimension(window);
- sdl_resize_texture(&global_back_buffer, renderer, dimension.width, dimension.height);
-
- bool running = true;
- srand((uint32_t)time(NULL));
-
- uint64_t lag = 0;
- uint64_t previous_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency();
- Star stars[NUM_STARS];
- for (int i = 0; i < NUM_STARS; ++i)
- {
- stars[i].x = rand() % dimension.width;
- stars[i].y = rand() % dimension.height;
- stars[i].angle = ((float)rand()/(float)(RAND_MAX)) * 2 * M_PI;
- stars[i].speed = 0;
- stars[i].mass = 5;
- stars[i].size = star_calc_size(stars[i].mass);
- stars[i].color = COLOR_WHITE;
- //printf("%f, %f, %f\n", stars[i].angle, stars[i].speed, stars[i].mass);
- }
-
- QuadTreeNode *cells_root = quad_tree_node_init(
- global_back_buffer.width / 2,
- global_back_buffer.height / 2,
- global_back_buffer.width / 2,
- global_back_buffer.height / 2);
-
- while (running)
- {
- uint64_t current_ms = (SDL_GetPerformanceCounter() * SECOND) / SDL_GetPerformanceFrequency();
- uint64_t elapsed_ms = current_ms - previous_ms;
- previous_ms = current_ms;
- lag += elapsed_ms;
- //printf("%" PRIu64 ", %" PRIu64 ", %f\n", elapsed_ms, lag, MS_PER_UPDATE);
-
- SDL_Event event;
-
- while (SDL_PollEvent(&event))
- {
- running = !handle_event(&event);
- }
-
- SDL_PumpEvents();
-
- dimension = sdl_get_window_dimension(window);
-
- while (lag >= MS_PER_UPDATE)
- {
- update(stars, NUM_STARS, cells_root, &dimension);
- //printf("\t%" PRIu64 ", %f\n", lag, MS_PER_UPDATE);
- lag -= MS_PER_UPDATE;
- }
-#ifndef TRAILS
- clear_screen(global_back_buffer, COLOR_BACKGROUND);
-#endif
- render(global_back_buffer, lag/SECOND, stars, NUM_STARS, cells_root);
- sdl_update_window(window, renderer, global_back_buffer);
- if (elapsed_ms <= MS_PER_FRAME)
- {
- SDL_Delay(MS_PER_FRAME - elapsed_ms);
- }
- }
- }
- else
- {
- // TODO(amin): log SDL_Renderer error
- }
- }
- else
- {
- // TODO(amin): log SDL_Window error
- }
-
- SDL_Quit();
- return(0);
-}
diff --git a/star.h b/star.h
@@ -4,6 +4,10 @@
#include <math.h>
#include <stdint.h>
+#ifndef M_PI
+#define M_PI (3.14159265358979323846264338327950288)
+#endif
+
#define GRAVITATION 0.1f
struct Star
@@ -23,20 +27,20 @@ struct Vec2d
float length;
};
-Vec2d *vec2d_add(float angle1, float length1, float angle2, float length2)
+struct Vec2d *vec2d_add(float angle1, float length1, float angle2, float length2)
{
float x = sinf(angle1) * length1 + sinf(angle2) * length2;
float y = cosf(angle1) * length1 + cosf(angle2) * length2;
- Vec2d *new_vec = (Vec2d*)malloc(sizeof(Vec2d));
+ struct Vec2d *new_vec = (struct Vec2d*)malloc(sizeof(struct Vec2d));
new_vec->angle = 0.5 * M_PI - atan2f(y, x);
new_vec->length = hypotf(x, y);
return new_vec;
}
-void star_accelerate(Star *s, float angle, float acceleration)
+void star_accelerate(struct Star *s, float angle, float acceleration)
{
- Vec2d *new_vec = vec2d_add(s->angle, s->speed, angle, acceleration);
+ struct Vec2d *new_vec = vec2d_add(s->angle, s->speed, angle, acceleration);
s->angle = new_vec->angle;
s->speed = new_vec->length;
free(new_vec);
@@ -47,7 +51,7 @@ float star_calc_size(float mass)
return 0.5 * (powf(mass, 0.5));
}
-void star_attract(Star *s1, Star *s2)
+void star_attract(struct Star *s1, struct Star *s2)
{
float dx = s1->x - s2->x;
float dy = s1->y - s2->y;