diff --git a/gfx/gfx.c b/gfx/gfx.c index aca1933358386e2b4c3e2c0dd05bcc20f06373c1..da660733d390165061d46dba27fec27ad5c1bebe 100644 --- a/gfx/gfx.c +++ b/gfx/gfx.c @@ -11,31 +11,35 @@ /// @param width Width of the window in pixels. /// @param height Height of the window in pixels. /// @return a pointer to the graphic context or NULL if it failed. -struct gfx_context_t* gfx_create(char *title, uint width, uint height) { - if (SDL_Init(SDL_INIT_VIDEO) != 0) goto error; - SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE); - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); - SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, width, height); - uint32_t *pixels = malloc(width*height*sizeof(uint32_t)); - struct gfx_context_t *ctxt = malloc(sizeof(struct gfx_context_t)); +struct gfx_context_t *gfx_create(char *title, uint width, uint height) { + if (SDL_Init(SDL_INIT_VIDEO) != 0) + goto error; + SDL_Window *window = + SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + width, height, SDL_WINDOW_RESIZABLE); + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); + SDL_Texture *texture = + SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, width, height); + uint32_t *pixels = malloc(width * height * sizeof(uint32_t)); + struct gfx_context_t *ctxt = malloc(sizeof(struct gfx_context_t)); - if (!window || !renderer || !texture || !pixels || !ctxt) goto error; + if (!window || !renderer || !texture || !pixels || !ctxt) + goto error; - ctxt->renderer = renderer; - ctxt->texture = texture; - ctxt->window = window; - ctxt->width = width; - ctxt->height = height; - ctxt->pixels = pixels; + ctxt->renderer = renderer; + ctxt->texture = texture; + ctxt->window = window; + ctxt->width = width; + ctxt->height = height; + ctxt->pixels = pixels; - SDL_ShowCursor(SDL_DISABLE); - gfx_clear(ctxt, COLOR_BLACK); - return ctxt; + SDL_ShowCursor(SDL_ENABLE); + gfx_clear(ctxt, COLOR_BLACK); + return ctxt; error: - return NULL; + return NULL; } /// Draw a pixel in the specified graphic context. @@ -44,52 +48,60 @@ error: /// @param y Y coordinate of the pixel. /// @param color Color of the pixel. void gfx_putpixel(struct gfx_context_t *ctxt, int x, int y, uint32_t color) { - if (x < ctxt->width && y < ctxt->height) - ctxt->pixels[ctxt->width*y+x] = color; + x = x < 0 ? 0 : x; + y = y < 0 ? 0 : y; + if (x < ctxt->width && y < ctxt->height) + ctxt->pixels[ctxt->width * y + x] = color; } /// Clear the specified graphic context. /// @param ctxt Graphic context to clear. /// @param color Color to use. void gfx_clear(struct gfx_context_t *ctxt, uint32_t color) { - int n = ctxt->width*ctxt->height; - while (n) - ctxt->pixels[--n] = color; + int n = ctxt->width * ctxt->height; + while (n) + ctxt->pixels[--n] = color; } /// Display the graphic context. /// @param ctxt Graphic context to clear. void gfx_present(struct gfx_context_t *ctxt) { - SDL_UpdateTexture(ctxt->texture, NULL, ctxt->pixels, ctxt->width*sizeof(uint32_t)); - SDL_RenderCopy(ctxt->renderer, ctxt->texture, NULL, NULL); - SDL_RenderPresent(ctxt->renderer); + SDL_UpdateTexture(ctxt->texture, NULL, ctxt->pixels, + ctxt->width * sizeof(uint32_t)); + SDL_RenderCopy(ctxt->renderer, ctxt->texture, NULL, NULL); + SDL_RenderPresent(ctxt->renderer); } /// Destroy a graphic window. /// @param ctxt Graphic context of the window to close. void gfx_destroy(struct gfx_context_t *ctxt) { - SDL_ShowCursor(SDL_ENABLE); - SDL_DestroyTexture(ctxt->texture); - SDL_DestroyRenderer(ctxt->renderer); - SDL_DestroyWindow(ctxt->window); - free(ctxt->pixels); - ctxt->texture = NULL; - ctxt->renderer = NULL; - ctxt->window = NULL; - ctxt->pixels = NULL; - SDL_Quit(); - free(ctxt); + SDL_ShowCursor(SDL_ENABLE); + SDL_DestroyTexture(ctxt->texture); + SDL_DestroyRenderer(ctxt->renderer); + SDL_DestroyWindow(ctxt->window); + free(ctxt->pixels); + ctxt->texture = NULL; + ctxt->renderer = NULL; + ctxt->window = NULL; + ctxt->pixels = NULL; + SDL_Quit(); + free(ctxt); } /// If a key was pressed, returns its key code (non blocking call). /// List of key codes: https://wiki.libsdl.org/SDL_Keycode /// @return the key that was pressed or 0 if none was pressed. SDL_Keycode gfx_keypressed() { - SDL_Event event; - if (SDL_PollEvent(&event)) { - if (event.type == SDL_KEYDOWN) - return event.key.keysym.sym; - } - return 0; + SDL_Event event; + if (SDL_PollEvent(&event)) { + if (event.type == SDL_KEYDOWN) + return event.key.keysym.sym; + } + return 0; } +SDL_Event gfx_event() { + SDL_Event event; + SDL_PollEvent(&event); + return event; +} diff --git a/gfx/gfx.h b/gfx/gfx.h index a5bb5b341be20b1703f81b4187f306b4c83d03d1..49dcef81a60ee595a1da837c6017f358159877e3 100644 --- a/gfx/gfx.h +++ b/gfx/gfx.h @@ -1,41 +1,44 @@ #ifndef _GFX_H_ #define _GFX_H_ -#include <stdint.h> -#include <stdbool.h> /* log() */ #include <SDL2/SDL.h> +#include <stdbool.h> /* log() */ +#include <stdint.h> -#define MAKE_COLOR(r,g,b) ((uint32_t)b|((uint32_t)g<<8)|((uint32_t)r<<16)) +#define MAKE_COLOR(r, g, b) \ + ((uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16)) #define COLOR_GET_B(color) (color & 0xff) #define COLOR_GET_G(color) ((color >> 8) & 0xff) #define COLOR_GET_R(color) ((color >> 16) & 0xff) -#define COLOR_BLACK 0x00000000 -#define COLOR_RED 0x00FF0000 -#define COLOR_GREEN 0x0000FF00 -#define COLOR_BLUE 0x000000FF -#define COLOR_WHITE 0x00FFFFFF +#define COLOR_BLACK 0x00000000 +#define COLOR_RED 0x00FF0000 +#define COLOR_GREEN 0x0000FF00 +#define COLOR_BLUE 0x000000FF +#define COLOR_WHITE 0x00FFFFFF #define COLOR_YELLOW 0x00FFFF00 -typedef unsigned int uint; +typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned char uchar; struct gfx_context_t { - SDL_Window *window; - SDL_Renderer *renderer; - SDL_Texture *texture; - uint32_t *pixels; - int width; - int height; + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + uint32_t *pixels; + int width; + int height; }; -extern void gfx_putpixel(struct gfx_context_t *ctxt, int x, int y, uint32_t color); +extern void gfx_putpixel(struct gfx_context_t *ctxt, int x, int y, + uint32_t color); extern void gfx_clear(struct gfx_context_t *ctxt, uint32_t color); -extern struct gfx_context_t* gfx_create(char *text, uint width, uint height); +extern struct gfx_context_t *gfx_create(char *text, uint width, uint height); extern void gfx_destroy(struct gfx_context_t *ctxt); extern void gfx_present(struct gfx_context_t *ctxt); extern SDL_Keycode gfx_keypressed(); +extern SDL_Event gfx_event(); #endif diff --git a/main.c b/main.c index 4395d884c2c3bffdf9244cd44e7a53a2929a0f4b..e20714fa06ac136af2341741f3650ab84b8de19b 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,7 @@ #include "charge/charge.h" #include "gfx/gfx.h" #include <math.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <time.h> @@ -25,9 +26,38 @@ #define NB_POINTS 200 #define DELTA (1 / sqrt(pow(WINDOW_WIDTH, 2) + pow(WINDOW_HEIGHT, 2))) +void redraw_field(struct gfx_context_t *ctxt, int charge_count, + vec2 pos[charge_count], double chs[charge_count]) { + // Generate all the charges + charge_t charges[charge_count]; + for (int i = 0; i < charge_count; i++) + charges[i] = charge_create(chs[i], pos[i]); + + draw_charges(ctxt, charges, charge_count, x0, x1, y0, y1); + + // Generate all the points + vec2 points[NB_POINTS]; + generate_points(points, NB_POINTS); + for (int i = 0; i < NB_POINTS; i++) { + coordinates_t c = position_to_coordinates(WINDOW_WIDTH, WINDOW_HEIGHT, + x0, x1, y0, y1, points[i]); + draw_field_line(ctxt, charges, charge_count, DELTA, points[i], x0, x1, + y0, y1); + } +} + int main(void) { srand(time(NULL)); + int charge_count = NB_CHARGES; + vec2 pos[30]; + double chs[30]; + + for (int i = 0; i < charge_count; i++) { + chs[i] = rand_one() / (rand_one() * 10 - 5); + pos[i] = vec2_create(rand_one(), rand_one()); + } + // GFX initialization struct gfx_context_t *ctxt = gfx_create("draw", WINDOW_WIDTH, WINDOW_HEIGHT); @@ -36,26 +66,35 @@ int main(void) { return EXIT_FAILURE; } - // Generate all the charges - charge_t charges[NB_CHARGES]; - for (int i = 0; i < NB_CHARGES; i++) { - charges[i] = charge_create(rand_one() / (rand_one() * 10 - 5), - vec2_create(rand_one(), rand_one())); - } - draw_charges(ctxt, charges, NB_CHARGES, x0, x1, y0, y1); - - // Generate all the points - vec2 points[NB_POINTS]; - generate_points(points, NB_POINTS); - for (int i = 0; i < NB_POINTS; i++) { - coordinates_t c = position_to_coordinates(WINDOW_WIDTH, WINDOW_HEIGHT, - x0, x1, y0, y1, points[i]); - draw_field_line(ctxt, charges, NB_CHARGES, DELTA, points[i], x0, x1, y0, - y1); - } + redraw_field(ctxt, charge_count, pos, chs); + bool running = true; // GFX Draw loop - while (gfx_keypressed() != SDLK_ESCAPE) { + while (running) { + SDL_Event event = gfx_event(); + + switch (event.type) { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_ESCAPE) + running = false; + break; + + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) { + charge_count += 1; + gfx_clear(ctxt, 0x000000); + int m_x, m_y; + SDL_GetMouseState(&m_x, &m_y); + + pos[charge_count - 1] = vec2_create( + (double)m_x / WINDOW_WIDTH, (double)m_y / WINDOW_HEIGHT); + chs[charge_count - 1] = rand_one() / (rand_one() * 10 - 5); + + redraw_field(ctxt, charge_count, pos, chs); + } + break; + } + gfx_present(ctxt); }