Astrophysics/sdl/projectile.c

242 lines
6.8 KiB
C

#include <stdio.h>
#include <SDL2/SDL.h>
#include <time.h>
#include <sys/time.h>
#include "projectile.h"
/* State of projectile */
static 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, "Ground", 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);
}