commit c98d6bf39699913add712a0a0261359935d124b9 Author: gbucchino Date: Fri Aug 4 10:39:16 2023 +0200 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73499d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +buid/ +buid/** diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec629d9 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +### Introduction +This personal project is for making some simulator in C for the understanding of the Astrophysics, like the gravity. +I use the library SDL2 for the graphics. + +FYI, I am not an expert in astrophysics, it's not my field, but just a hobby. If you find some wrong maths calculation, please, let me know. + +### Installation +For executing the code, you must install these packages: + +``` +apt install libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev +``` + +### Configuration +The `gravity.yml` file contains all data for the physics laws, like the gravity or the data of the planet. You can change these datas and you can see hoz the gravity. + +### Projectile +For understanding the gravity, we can simulate the launch of a projectile and to see what happens. We can play with that and change some informations regarding the projectile and the planet. + diff --git a/argparser.c b/argparser.c new file mode 100644 index 0000000..d56a555 --- /dev/null +++ b/argparser.c @@ -0,0 +1,48 @@ +#include +#include +#include "argparser.h" + +void usage() { + printf("Cosmology: -c [--debug]\n"); +} + +int getArgs(char *arg) { + int res = FALSE; + int i; + /* List arguments */ + char listArgs[3][BUF_SIZE]; + strcpy(listArgs[0], "-c"); // Gravity + + for(i = 0; i < 3; i++){ + if(strcmp(listArgs[i], arg) == 0) + res = TRUE; + } + + if(res == FALSE){ + printf("%s: unknown\n", arg); + usage(); + } + return res; +} +int getArgsOptional(char *arg){ + int res = FALSE; + int i; + /* List arguments */ + char listArgs[1][BUF_SIZE]; + strcpy(listArgs[0], "--debug"); + + for(i = 0; i < 1; i++){ + if(strcmp(listArgs[i], arg) == 0) + res = TRUE; + } + + return res; +} +int checkParamFileExist(char *path){ + FILE *f = fopen(path, "r"); + + if (f == NULL) + return -1; + fclose(f); + return 0; +} diff --git a/argparser.h b/argparser.h new file mode 100644 index 0000000..a86388f --- /dev/null +++ b/argparser.h @@ -0,0 +1,12 @@ +#ifndef H_ARGPARSER +#define H_ARGPARSER + +#include +#include "constantes.h" + +void usage(); +int getArgs(char *); +int getArgsOptional(char *); +int checkParamFileExist(char *); + +#endif diff --git a/build/argparser.o b/build/argparser.o new file mode 100644 index 0000000..0197b84 Binary files /dev/null and b/build/argparser.o differ diff --git a/build/functions.o b/build/functions.o new file mode 100644 index 0000000..cd73ab9 Binary files /dev/null and b/build/functions.o differ diff --git a/build/gravity.o b/build/gravity.o new file mode 100644 index 0000000..4d273be Binary files /dev/null and b/build/gravity.o differ diff --git a/build/init_sdl.o b/build/init_sdl.o new file mode 100644 index 0000000..8a4b7a0 Binary files /dev/null and b/build/init_sdl.o differ diff --git a/build/main.o b/build/main.o new file mode 100644 index 0000000..b65dfb4 Binary files /dev/null and b/build/main.o differ diff --git a/build/motion.o b/build/motion.o new file mode 100644 index 0000000..a4ec42d Binary files /dev/null and b/build/motion.o differ diff --git a/build/projectile.o b/build/projectile.o new file mode 100644 index 0000000..661f838 Binary files /dev/null and b/build/projectile.o differ diff --git a/build/yaml.o b/build/yaml.o new file mode 100644 index 0000000..645c109 Binary files /dev/null and b/build/yaml.o differ diff --git a/constantes.h b/constantes.h new file mode 100644 index 0000000..312d84c --- /dev/null +++ b/constantes.h @@ -0,0 +1,27 @@ +#ifndef H_CONSTANTES +#define H_CONSTANTES + +#define TRUE 0 +#define FALSE 1 + +#define BUF_SIZE 128 + +/* Structure to define a planet */ +struct object{ + char name[BUF_SIZE]; + double rayon; + double masse; + double grav; + int eccentricity; + double orbital; // Orbital in second + double aphelie; // In meters + double perihelie; // In meters + double semi_axe; // In meters + double orbital_speed; // In meters/s +}; + +struct constantes { + double grav; // Newton gravitational +}; + +#endif diff --git a/exec.sh b/exec.sh new file mode 100755 index 0000000..6966dad --- /dev/null +++ b/exec.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# main -c gravity.yml + +#gcc sdl/init_sdl.c sdl/projectile.c sdl/orbitalSystem.c argparser.c yaml.c gravity.c main.c -lm -lpthread -lSDL2 -lSDL2_image -lSDL2_ttf -o main && ./main $1 $2 $3 +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c sdl/init_sdl.c -o build/init_sdl.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c sdl/projectile.c -o build/projectile.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c argparser.c -o build/argparser.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c functions.c -o build/functions.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c yaml.c -o build/yaml.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c gravity.c -o build/gravity.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c motion.c -o build/motion.o +##gcc -S -o build/gravity.o gravity.c +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf -Wunused-variable -c main.c -o build/main.o +#gcc -lm -lSDL2 -lSDL2_image -lSDL2_ttf build/init_sdl.o build/projectile.o build/argparser.o build/yaml.o build/functions.o build/gravity.o build/motion.o build/main.o -o build/main && ./build/main $1 $2 $3 + + +gcc functions.c motion.c sdl/init_sdl.c sdl/projectile.c argparser.c yaml.c gravity.c main.c -lm -lpthread -lSDL2 -lSDL2_image -lSDL2_ttf -o main && ./main $1 $2 $3 diff --git a/functions.c b/functions.c new file mode 100644 index 0000000..1ca7e97 --- /dev/null +++ b/functions.c @@ -0,0 +1,12 @@ +#include +#include +#include "functions.h" + +int fileExist(char *path){ + FILE *f = fopen(path, "r"); + + if (f == NULL) + return -1; + fclose(f); + return 0; +} diff --git a/functions.h b/functions.h new file mode 100644 index 0000000..9b548d8 --- /dev/null +++ b/functions.h @@ -0,0 +1,6 @@ +#ifndef H_FUNCTIONS +#define H_FUNCTIONS + +int fileExist(char *); + +#endif diff --git a/gravity.c b/gravity.c new file mode 100644 index 0000000..c28f80b --- /dev/null +++ b/gravity.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include "gravity.h" + + +double calcul_gravity_object(const double grav, const double masse, const double r){ + // Newton's law for gravitation + return grav * (masse / pow(r, 2)); +} diff --git a/gravity.h b/gravity.h new file mode 100644 index 0000000..5efb77f --- /dev/null +++ b/gravity.h @@ -0,0 +1,8 @@ +#ifndef H_GRAVITY +#define H_GRAVITY + +#include "constantes.h" + +double calcul_gravity_object(const double, const double, const double); + +#endif diff --git a/gravity.yml b/gravity.yml new file mode 100644 index 0000000..8b37b4b --- /dev/null +++ b/gravity.yml @@ -0,0 +1,16 @@ +--- +Constantes: + grav: 6.673e-11 + +Projectile: + x: 0 # Position in x + y: 0 # Position in y + v0: 10.0 # Initial speed in meter/s + angle: 30 # Angle in degree + masse: 100 # Masse of projectile + height: 20 # Height + width: 20 # Width + +Planet1: + rayon: 6.371e6 # Rayon earth in meter -> 6371.00 km + masse: 5.972e24 # Masse of earth, moon, etc... in kg diff --git a/main b/main new file mode 100755 index 0000000..afdcb7f Binary files /dev/null and b/main differ diff --git a/main.c b/main.c new file mode 100644 index 0000000..5167d3a --- /dev/null +++ b/main.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include "argparser.h" +#include "yaml.h" +#include "gravity.h" +#include "motion.h" +#include "constantes.h" +#include "functions.h" +#include "sdl/projectile.h" + +static void mainInitPlanet(const struct yamlFile *, struct object *, char *, double); +static void mainInitProjectile(const struct yamlFile *, struct projectile *, const double); +int main(int argc, char *argv[]) { + int res = -1; + int debug = FALSE; + FILE *f = NULL; + /* Create our structures */ + struct yamlFile *yamlFile = malloc(sizeof(struct yamlFile)); + struct constantes constantes; + struct object s_planet1; + struct projectile s_projectile; + + int i; + + /** CHECK ARGUMENTS **/ + if (argc == 1) + return -1; + + res = getArgs(argv[1]); + + if (res == FALSE) + exit(1); + + res = fileExist(argv[2]); + if (res == -1){ + printf("File %s doesn't exist\n", argv[2]); + exit(1); + } + + /* Check if debug */ + if(argc == 4){ + if(getArgsOptional(argv[3]) == TRUE){ + debug = TRUE; + } + } + + /** CONFIGURE VARIABLES **/ + f = fopen(argv[2], "r"); + + // Stock in struct yamlFile the data + bufferingFiles(f, yamlFile); + fclose(f); + + // Stock constants variables from YAML file + /* Get constantes variables */ + constantes.grav = parseYamlFileDouble(yamlFile, "Constantes:grav"); + + // Init planet + mainInitPlanet(yamlFile, &s_planet1, "Planet1", constantes.grav); + + // Initialise projectile + mainInitProjectile(yamlFile, &s_projectile, s_planet1.grav); + + switch (argv[1][1]){ + case 'c': + handleProjectile(&s_projectile, &s_planet1, debug); + break; + default: + break; + } + + /* We destroy our multi-array */ + for(i = 0; i < yamlFile->len; i++) + free(yamlFile->buf[i]); + free(yamlFile->buf); + free(yamlFile); + return 0; +} +static void mainInitPlanet(const struct yamlFile *yamlFile, struct object *s_planet, char *p, double grav){ + /* Initialise caracteristique of planet */ + char rayon[BUF_SIZE]; + char masse[BUF_SIZE]; + int res = 0; + + res = sprintf(rayon, "%s:rayon", p); + if(res < 0){ + printf("Failed to initialize planet: %s\n", p); + exit(1); + } + res = sprintf(masse, "%s:masse", p); + if(res < 0){ + printf("Failed to initialize planet: %s\n", p); + exit(1); + } + s_planet->rayon = parseYamlFileDouble(yamlFile, rayon); + s_planet->masse = parseYamlFileDouble(yamlFile, masse); + + // Calcul gravitational force in Newton + s_planet->grav = calcul_gravity_object(grav, s_planet->masse, s_planet->rayon); +} +/* + * This function initialize projectile's structure + */ +static void mainInitProjectile(const struct yamlFile *yamlFile, struct projectile *s_projectile, const double grav){ + double v0 = 0.0; + double deg_to_rad = 0.0; + s_projectile->height = parseYamlFileInt(yamlFile, "Projectile:height"); + s_projectile->width= parseYamlFileInt(yamlFile, "Projectile:width"); + s_projectile->x = parseYamlFileInt(yamlFile, "Projectile:x"); + s_projectile->y = parseYamlFileInt(yamlFile, "Projectile:y"); + v0 = parseYamlFileDouble(yamlFile, "Projectile:v0"); + s_projectile->masse = parseYamlFileInt(yamlFile, "Projectile:masse"); + s_projectile->alpha = parseYamlFileDouble(yamlFile, "Projectile:angle"); + deg_to_rad = degree_to_radian(s_projectile->alpha); + s_projectile->v0x = calcul_initial_speed(deg_to_rad, v0, 'x'); + s_projectile->v0y = calcul_initial_speed(deg_to_rad, v0, 'y'); + s_projectile->rect.x = s_projectile->x; + s_projectile->rect.y = s_projectile->y; + s_projectile->rect.w = s_projectile->height; + s_projectile->rect.h = s_projectile->width; + + /***** Informations about the projectile *****/ + // Calcul delta t + s_projectile->deltat = calcul_delta_t(s_projectile->v0y, grav); + + // calcul distance in meter + s_projectile->distance = calcul_distance_total(s_projectile->v0x, s_projectile->deltat); + + // Calcul height Max + s_projectile->hmax = calcul_height_max(0.0, s_projectile->v0y, grav); +} diff --git a/motion.c b/motion.c new file mode 100644 index 0000000..8aa7ec0 --- /dev/null +++ b/motion.c @@ -0,0 +1,35 @@ +#include "motion.h" +#include + +double calcul_initial_speed(double alpha, double speed, const char c) { + // We calculated the v0 of y + if (c == 'x') + return speed * cos(alpha); + // Otherwise, we calculated the v0 of x + else + return speed * sin(alpha); +} +/* + * This function calcul the during of the time before the projectile have touche the ground + */ + double calcul_delta_t(double v, double grav){ + return (2 * v) / grav; + } +/* + * This function calcul the distance total of the projectile + */ + double calcul_distance_total(double v, double deltat){ + return v * deltat; + } + /* + * This function calcul the height max of the Projectile + */ + double calcul_height_max(double vx, double vy, double grav){ + return (pow(vx, 2) - pow(vy, 2)) / (2 * -grav); + } +/* + * This function convert the degree in radian + */ + double degree_to_radian(double degree){ + return degree * M_PI / 180; + } diff --git a/motion.h b/motion.h new file mode 100644 index 0000000..b99ac0e --- /dev/null +++ b/motion.h @@ -0,0 +1,10 @@ +#ifndef H_MOTION +#define H_MOTION + +double calcul_initial_speed(double, double, const char); +double calcul_delta_t(double, double); +double calcul_distance_total(double, double); +double calcul_height_max(double, double, double); +double degree_to_radian(double); + +#endif diff --git a/sdl/fonts/FreeSans.otf b/sdl/fonts/FreeSans.otf new file mode 100644 index 0000000..062c939 Binary files /dev/null and b/sdl/fonts/FreeSans.otf differ diff --git a/sdl/imgs/projectile.png b/sdl/imgs/projectile.png new file mode 100644 index 0000000..427a584 Binary files /dev/null and b/sdl/imgs/projectile.png differ diff --git a/sdl/imgs/projectile.svg b/sdl/imgs/projectile.svg new file mode 100644 index 0000000..0c021a7 --- /dev/null +++ b/sdl/imgs/projectile.svg @@ -0,0 +1,62 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/sdl/init_sdl.c b/sdl/init_sdl.c new file mode 100644 index 0000000..e2b36a3 --- /dev/null +++ b/sdl/init_sdl.c @@ -0,0 +1,56 @@ +#include +#include "init_sdl.h" + +void initWindow(SDL_Window **win, TTF_Font **font, char *t, int h, int w){ + if(SDL_Init(SDL_INIT_VIDEO) != 0){ + printf("SDL: Failed to init sdl: %s\n", SDL_GetError()); + exit(1); + } + //SDL_Window *win; + *win = SDL_CreateWindow(t, SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + w, h, + SDL_WINDOW_SHOWN); + + /* Init TTF */ + if(TTF_Init() != 0){ + printf("SDL: Failed to init TTF: %s\n", SDL_GetError()); + SDL_Quit(); + exit(1); + } + + *font = TTF_OpenFont("sdl/fonts/FreeSans.otf", 25); + + if(*win == NULL){ + printf("SDL: Failed to init SDL\n"); + TTF_Quit(); + SDL_Quit(); + exit(1); + } + + if (*font == NULL){ + printf("SDL: Failed to open font\n"); + SDL_DestroyWindow(*win); + TTF_Quit(); + SDL_Quit(); + exit(1); + } +} +SDL_Surface *loadImage(const char *filename){ + SDL_Surface *s = IMG_Load(filename); + if(s == NULL) { + printf("SDL: Failed to load img\n"); + return NULL; + } + return s; +} +void destroyWindow(SDL_Window *w, SDL_Renderer *r, TTF_Font *f){ + if (f != NULL) + TTF_CloseFont(f); + if (r != NULL) + SDL_DestroyRenderer(r); + if (w != NULL) + SDL_DestroyWindow(w); + TTF_Quit(); + SDL_Quit(); +} diff --git a/sdl/init_sdl.h b/sdl/init_sdl.h new file mode 100644 index 0000000..fa5d82f --- /dev/null +++ b/sdl/init_sdl.h @@ -0,0 +1,20 @@ +#ifndef H_INITSDL +#define H_INITSDL + +#include +#include +#include + +struct window{ + SDL_Window *win; + TTF_Font *font; + SDL_Renderer *r; + int h; + int w; +}; + +void initWindow(SDL_Window **, TTF_Font **, char *, int, int); +SDL_Surface *loadImage(const char *); +void destroyWindow(SDL_Window *, SDL_Renderer*, TTF_Font*); + +#endif diff --git a/sdl/projectile.c b/sdl/projectile.c new file mode 100644 index 0000000..5ab20ad --- /dev/null +++ b/sdl/projectile.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include "projectile.h" + +/* State of projectile */ +int isLaunch; + +/* + * This function initialize our Projectile + */ +static void initProjectile(struct window *s_w, struct projectile *s_p){ + s_w->r = SDL_CreateRenderer(s_w->win, -1, 0); + if(s_w->r == NULL){ + printf("Failed to create renderer\n"); + destroyWindow(s_w->win, s_w->r, s_w->font); + exit(1); + } + s_p->s = loadImage("sdl/imgs/projectile.png"); + if(s_p->s == NULL){ + destroyWindow(s_w->win, s_w->r, s_w->font); + exit(1); + } + s_p->t = SDL_CreateTextureFromSurface(s_w->r, s_p->s); +} +/* + * This function init our rect for drawing Informations on the projectile + */ +static void initInfos(TTF_Font *font, SDL_Rect *r, const SDL_Surface *s, int x, int y){ + r->w = s->w; + r->h = s->h; + r->x = x; + r->y = y; +} +/* + * This function draw an celestial object, for instance a planet + */ +static void drawCelestialObject(const struct window window, const SDL_Rect rectObject){ + // Draw celestial object + SDL_SetRenderDrawColor(window.r, 55, 27, 7, 255); + SDL_RenderFillRect(window.r, &rectObject); +} +/* + * This function draw a text from SDL_Surface *surface in window + */ +static void drawText(const struct window window, const SDL_Rect rect, SDL_Surface *surface){ + SDL_Texture *tFont = SDL_CreateTextureFromSurface(window.r, surface); + + SDL_RenderCopy(window.r, tFont, NULL, &rect); + + SDL_DestroyTexture(tFont); +} +/* + * This function draw all objects in our screen + */ +static void drawObjects(const struct window window, const struct projectile *s_projectile, const SDL_Rect rectObject, const SDL_Rect *rectInfos, SDL_Surface **sInfos){ + /* Draw screen */ + SDL_SetRenderDrawColor(window.r, 0, 0, 0, 255); + SDL_RenderClear(window.r); + + /* Draw grid */ + drawGrid(window); + + // Draw celestial object + drawCelestialObject(window, rectObject); + drawText(window, *rectInfos, *sInfos); + + // Draw infos + drawText(window, *(rectInfos + 1), *(sInfos + 1)); + drawText(window, *(rectInfos + 2), *(sInfos + 2)); + drawText(window, *(rectInfos + 3), *(sInfos + 3)); + + // Draw balle + SDL_RenderCopy(window.r, s_projectile->t, NULL, &s_projectile->rect); + SDL_RenderPresent(window.r); +} +/* + * This function draw a grid in window + */ + static void drawGrid(const struct window window){ + int i; + int scale = SCALE * 5; + SDL_SetRenderDrawColor(window.r, 83, 83, 83, 255); + + // Draw vertical lines + for (i = 0; i < window.w; i = i + scale) + SDL_RenderDrawLine(window.r, i, 0, i, window.h); + + // Draw horizontal lines + for (i = 0; i < window.h; i = i + scale) + SDL_RenderDrawLine(window.r, 0, i, window.w, i); + } + /* + * This function execute the thread + */ +static int run(void *args){ + int i = 0; + struct thread_projectile_args *arg = (struct thread_projectile_args*)args; + double v0x = arg->projectile->v0x * SCALE; + double v0y = arg->projectile->v0y * SCALE; + double x0 = arg->projectile->x; + double y0; + SDL_Rect rectObject = arg->rectObject; + SDL_Rect *rectInfos = arg->rectInfos; + SDL_Surface **sInfos = arg->sInfos; + + /* Position projectile in altitude */ + arg->projectile->rect.y = rectObject.y + (-arg->projectile->y) - arg->projectile->width; + y0 = arg->projectile->rect.y; + arg->projectile->rect.x = arg->projectile->x - (arg->projectile->width / 2); + x0 = arg->projectile->rect.x; + + /* Draw projectile */ + drawObjects(arg->window, arg->projectile, rectObject, rectInfos, sInfos); + + while(1){ + while(isLaunch != LANDING && isLaunch != STOP) { + int res = y0 - ((v0y * i) - arg->planet->grav * (i * i)); + + if((res + arg->projectile->height) > rectObject.y){ + arg->projectile->rect.y = rectObject.y - arg->projectile->height; + isLaunch = LANDING; + } + else{ + arg->projectile->rect.x = x0 + v0x * i; + arg->projectile->rect.y = res; + } + + drawObjects(arg->window, arg->projectile, rectObject, rectInfos, sInfos); + + SDL_Delay(50); + if(arg->debug == TRUE) + printf("x: %d y:%d\n", arg->projectile->rect.x, arg->projectile->rect.y); + i++; + } + } + + return 0; +} +/* + * This is main function, init our objects and create a thread + */ +void handleProjectile(struct projectile *s_projectile, const struct object *s_planet, int debug){ + SDL_Event event; + SDL_Thread *sthread; + static struct thread_projectile_args args; + SDL_Rect rectObject; + SDL_Rect rectInfos[4]; + SDL_Surface *sInfos[4]; + SDL_Color colorFont = {255, 255, 255}; + char buf[BUF_SIZE]; + int done = 1; + struct window s_window; + s_window.h = WIN_PROJECTILE_HEIGHT; + s_window.w = WIN_PROJECTILE_WIDTH; + + args.projectile = s_projectile; + args.planet = s_planet; + args.debug = debug; + + // Init celestial object + rectObject.x = 0; + rectObject.y = WIN_PROJECTILE_HEIGHT - (WIN_PROJECTILE_HEIGHT / 5); + rectObject.h = WIN_PROJECTILE_HEIGHT - 200; + rectObject.w = WIN_PROJECTILE_WIDTH; + args.rectObject = rectObject; + + // Init Video + initWindow(&s_window.win, &s_window.font, "Projectile simulator", s_window.h, s_window.w); + + // Init projectile + initProjectile(&s_window, s_projectile); + args.window = s_window; + + /* Init celestial object */ + *sInfos = TTF_RenderText_Blended(s_window.font, "Earth", colorFont); + initInfos(s_window.font, &rectInfos[0], sInfos[0], (WIN_PROJECTILE_WIDTH / 2) - sInfos[0]->w, rectObject.y + 15); + + /* Get distance and time */ + sprintf(buf, "Distance: %f m", s_projectile->distance); + *(sInfos + 1) = TTF_RenderText_Blended(s_window.font, buf, colorFont); + initInfos(s_window.font, &rectInfos[1], sInfos[1], 10, rectInfos[0].y + 20); + + memset(buf, 0, BUF_SIZE); + sprintf(buf, "Time: %f s", s_projectile->deltat); + *(sInfos + 2) = TTF_RenderText_Blended(s_window.font, buf, colorFont); + initInfos(s_window.font, &rectInfos[2], sInfos[2], 10, rectInfos[1].y + 30); + + memset(buf, 0, BUF_SIZE); + sprintf(buf, "Height max: %f m", s_projectile->hmax); + *(sInfos + 3) = TTF_RenderText_Blended(s_window.font, buf, colorFont); + initInfos(s_window.font, &rectInfos[3], sInfos[3], 10, rectInfos[2].y + 30); + + args.rectInfos = rectInfos; + args.sInfos = sInfos; + + // Create our thread + isLaunch = STOP; + sthread = SDL_CreateThread(run, "Projectile", (void*)&args); + + if(sthread == NULL){ + printf("SDL_CreateThread failed: %s\n", SDL_GetError()); + exit(1); + } + + while(done){ + SDL_WaitEvent(&event); + switch(event.type){ + case SDL_KEYDOWN: + switch(event.key.keysym.sym){ + case SDLK_ESCAPE: + done = 0; + break; + case SDLK_RETURN: + // launch the projectile + isLaunch = LAUNCH; + break; + } + break; + } + } + + SDL_FreeSurface(sInfos[0]); + SDL_FreeSurface(sInfos[1]); + SDL_FreeSurface(sInfos[2]); + SDL_FreeSurface(sInfos[3]); + + cleanProjectile(&s_window, s_projectile); +} +/* + * This function clean our projectile object + */ +static void cleanProjectile(struct window *s_window, struct projectile *p){ + if(p->t != NULL) + SDL_DestroyTexture(p->t); + if(p->s != NULL) + SDL_FreeSurface(p->s); + + destroyWindow(s_window->win, s_window->r, s_window->font); +} diff --git a/sdl/projectile.h b/sdl/projectile.h new file mode 100644 index 0000000..89e76ac --- /dev/null +++ b/sdl/projectile.h @@ -0,0 +1,57 @@ +#ifndef H_SDL_PROJECTILE +#define H_SDL_PROJECTILE + +#include "init_sdl.h" +#include "../constantes.h" + +/* Defines for window's size */ +#define WIN_PROJECTILE_HEIGHT 712 +#define WIN_PROJECTILE_WIDTH 1024 + +#define SCALE 10 + +/* Structure used for thread args */ +struct thread_projectile_args{ + struct window window; + struct projectile *projectile; + const struct object *planet; + SDL_Rect rectObject; + SDL_Rect *rectInfos; + SDL_Surface **sInfos; + int debug; +}; + +struct projectile{ + SDL_Texture *t; + SDL_Surface *s; + SDL_Rect rect; + int x; /* Position in x */ + int y; /* Position in y */ + double v0x; /* Vitesse initiale x */ + double v0y; /* Vitesse initiale y */ + int masse; /* Projectile's masse */ + int height; + int width; + int alpha; /* Angle in degree */ + double deltat; /* Delta t */ + double distance; /* Distance */ + double hmax; /* Max height */ +}; + +enum stateProjectile{ + LAUNCH = 0, + STOP = 1, + LANDING = 2 +}; + +static void initProjectile(struct window *, struct projectile *); +static void initInfos(TTF_Font *, SDL_Rect *, const SDL_Surface *, int, int); +static void drawCelestialObject(const struct window, const SDL_Rect); +static void drawText(const struct window, const SDL_Rect, SDL_Surface *); +static void drawGrid(const struct window); +static void drawObjects(const struct window, const struct projectile *, const SDL_Rect, const SDL_Rect*, SDL_Surface**); +static int run(void *); +void handleProjectile(struct projectile*, const struct object *, int); +static void cleanProjectile(struct window *, struct projectile *); + +#endif diff --git a/yaml.c b/yaml.c new file mode 100644 index 0000000..f825b15 --- /dev/null +++ b/yaml.c @@ -0,0 +1,248 @@ +#include +#include +#include +#include +#include "constantes.h" +#include "yaml.h" + +void parseYamlFileVariables(const struct yamlFile *yamlFile, char *entry, char dst[2][BUF_SIZE]){ + int line, res; + char buf[2][BUF_SIZE]; + char buf_var[2][BUF_SIZE]; + char section[20]; + + /* Get entry and variable name */ + res = explodeEntry(entry, buf, ':'); + + if (res != YAML_SUCCESS) { + printf("Failed to parse YAML's file\n"); + exit(1); + } + + /* Seek section in yaml */ + res = addDoublePoint(buf[0], section); + line = getPositionSection(yamlFile, section); + if (line == -1){ + printf("Failed to find section %s in YAML's file\n", buf[0]); + exit(1); + } + + /* Get variables */ + res = getVariables(yamlFile, buf[1], buf_var, line); + if (res == VARIABLE_YAML_NOT_FOUND){ + printf("Variable %s not found in YAML's file\n", buf[1]); + exit(1); + } + strcpy(dst[0], buf_var[0]); + strcpy(dst[1], buf_var[1]); +} +void parseYamlFileChar(const struct yamlFile *yamlFile, char *entry, char *dst) { + char buf_var[2][BUF_SIZE]; + + /* Get variables */ + parseYamlFileVariables(yamlFile, entry, buf_var); + + strcpy(dst, buf_var[1]); +} +double parseYamlFileDouble(const struct yamlFile *yamlFile, char *entry) { + char buf[2][BUF_SIZE]; + char buf_var[2][BUF_SIZE]; + int res; + + /* Get variables */ + parseYamlFileVariables(yamlFile, entry, buf_var); + + /* Get if pow */ + res = explodeEntry(buf_var[1], buf, 'e'); + if (res == YAML_SUCCESS){ + double d1, d2; + d1 = atof(buf[0]); + d2 = atof(buf[1]); + return d1 * pow(10, d2); + } + return atof(buf_var[1]); +} +int parseYamlFileInt(const struct yamlFile *yamlFile, char *entry){ + char buf[2][BUF_SIZE]; + char buf_var[2][BUF_SIZE]; + int res; + + /* Get variables */ + parseYamlFileVariables(yamlFile, entry, buf_var); + + /* Get if pow */ + res = explodeEntry(buf_var[1], buf, 'e'); + if (res == YAML_SUCCESS){ + double d1, d2; + d1 = atof(buf[0]); + d2 = atof(buf[1]); + return d1 * pow(10, d2); + } + return atoi(buf_var[1]); +} +/* + * This function read the YAML's file and stock all data in structure + */ +struct yamlFile *bufferingFiles(FILE *f, struct yamlFile *yamlFile){ + char c; + char buf_tmp[BUF_SIZE]; + int i=0, lines=0; + + /* We count the number of lines */ + fseek(f, 0, SEEK_SET); + do{ + c = fgetc(f); + + if(c == '\n') + lines++; + }while (c != EOF); + + yamlFile->len = lines; + + /* We allocate our buffer */ + if((yamlFile->buf = malloc(lines * sizeof(char*))) == NULL){ + printf("Failed to malloc\n"); + fclose(f); + exit(1); + } + for(i = 0; i < lines; i++) + if((yamlFile->buf[i] = malloc(BUF_SIZE)) == NULL){ + printf("Failed to malloc\n"); + fclose(f); + exit(1); + } + + fseek(f, 0, SEEK_SET); + lines = 0; + do{ + c = fgetc(f); + + buf_tmp[i++] = c; + if(c == '\n'){ + buf_tmp[--i] = '\0'; + memcpy(yamlFile->buf[lines++], buf_tmp, i); + memset(buf_tmp, 0, BUF_SIZE); + i = 0; + } + }while (c != EOF); + + return yamlFile; +} +int addDoublePoint(char *src, char *dst){ + int i = 0; + while (src[i] != '\0'){ + dst[i] = src[i]; + i++; + } + dst[i++] = ':'; + dst[i++] = '\0'; + return i; +} +int readYaml(FILE *f, char *section){ + char buf[BUF_SIZE]; + char c; + int i = 0; + int line = 0; + int seek = PARSE_YAML_FAILED; + /* Seek the section, example gravity: in file */ + do { + c = fgetc(f); + buf[i++] = c; + if(c == '\n') { + buf[--i] = '\0'; /* Remove the '\n' */ + seek = findEntry(buf, section); + if (seek == YAML_SUCCESS) break; + /* Get cursor position in file */ + memset(buf, 0, BUF_SIZE); + i = 0; + } + line++; + }while(c != EOF); + if (seek == PARSE_YAML_FAILED) return seek; + return line; +} +int findEntry(char *buf, char *entry) { + int seek = PARSE_YAML_FAILED; + if (strcmp(buf, entry) == 0) { + seek = YAML_SUCCESS; + } + return seek; +} +int getVariables(const struct yamlFile *yamlFile, char *variable, char buf_var[2][BUF_SIZE], int posEntry) { + char buf[BUF_SIZE]; + char buf2[2][BUF_SIZE]; + memset(buf2[0], 0, BUF_SIZE); + memset(buf2[1], 0, BUF_SIZE); + char c; + int i = 0, j, pos=0, lines=0; + int res = PARSE_YAML_FAILED; + + for(lines = posEntry; lines < yamlFile->len; lines++){ + do { + c = yamlFile->buf[lines][pos++]; + if (c != ' ') + buf[i++] = c; + } while(c != '\0'); + + /* Seek our variable */ + if(strlen(buf) > 0){ + res = explodeEntry(buf, buf_var, ':'); + if(res == YAML_SUCCESS) { + char t[BUF_SIZE]; + if (buf_var[0][0] == '-'){ + int x = 0; + for(j = 1; j < strlen(buf_var[0]); j++) + t[x++] = buf_var[0][j]; + } + else + strcpy(t, buf_var[0]); + if(strcmp(t, variable) == 0){ + res = YAML_SUCCESS; + break; + } + else res = VARIABLE_YAML_NOT_FOUND; + memset(t, 0, BUF_SIZE); + } + } + + memset(buf, 0, BUF_SIZE); + i = 0; + pos = 0; + } + return res; +} +int explodeEntry(char *entry, char var[2][BUF_SIZE], char delimiter) { + char c; + int i = 0, j = 0, pos = 0; + /* Get position of delimiter */ + do { + c = entry[i]; + if (c == delimiter) pos = i; + i++; + }while(c != '\0'); + if (pos == 0) + return YAML_DELIMITER_NOT_FOUND; + + for(i = 0; i < pos; i++) { + var[0][i] = entry[i]; + } + var[0][i++] = '\0'; + for(i = pos + 1, j=0; i < strlen(entry); i++, j++) { + var[1][j] = entry[i]; + } + var[1][j++] = '\0'; + return YAML_SUCCESS; +} +/* + * This function get the position (int) for the section + */ +int getPositionSection(const struct yamlFile *yamlFile, char *section){ + int i = 0, pos = -1; + + for(i = 0; i < yamlFile->len; i++){ + if(strcmp(yamlFile->buf[i], section) == 0) + pos = i; + } + + return pos; +} diff --git a/yaml.h b/yaml.h new file mode 100644 index 0000000..c7beb51 --- /dev/null +++ b/yaml.h @@ -0,0 +1,26 @@ +#ifndef H_YAML +#define H_YAML + +#define YAML_SUCCESS 0x00000 +#define PARSE_YAML_FAILED 0x00001 +#define VARIABLE_YAML_NOT_FOUND 0x00002 +#define YAML_DELIMITER_NOT_FOUND 0x00003 + +struct yamlFile{ + char **buf; + size_t len; +}; + +void parseYamlFileVariables(const struct yamlFile *, char *, char dst[2][BUF_SIZE]); +double parseYamlFileDouble(const struct yamlFile *, char *); +int parseYamlFileInt(const struct yamlFile *, char *); +void parseYamlFileChar(const struct yamlFile *, char *, char *); +struct yamlFile *bufferingFiles(FILE *, struct yamlFile *); +int addDoublePoint(char *, char *); +int readYaml(FILE *, char *); +int findEntry(char *, char *); +int getVariables(const struct yamlFile *, char *, char buf_var[2][BUF_SIZE], int); +int explodeEntry(char *, char var[2][BUF_SIZE], char); +int getPositionSection(const struct yamlFile *, char *); + +#endif