#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); }